Problem to compile a DLL on mingw

Hello,

I hit a problem to create a working DLL with OCaml for Windows 4.07.1+mingw32c, while it worked fine with 4.06.1+mingw32c.

I’m not sure if I missed some modification that occurred between those two versions?

I’d appreciate any help to understand the origin of this problem.

I wrote a trivial project to demonstrate the problem (it’s there, as a git repository). Interestingly, there is no line of OCaml in this demo project. Only dune and C files.

Below is a session that demonstrate the problem: it’s a C test file calling the generated DLL. I detected the problem while trying to load it from LabVIEW or Python.

  1. I’d like to have the confirmation that my problem can be reproduced
  2. And of course any hint toward a solution to it

Working switch

$ uname -a
CYGWIN_NT-10.0 DESKTOP-9DIKPMF 3.0.5(0.338/5/3) 2019-03-31 11:17 x86_64 Cygwin
$ opam switch
#   switch                          compiler                             description
->  4.06.1+mingw32c                 ocaml-variants.4.06.1+mingw32c       4.06.1+mingw32c
    4.07.1+mingw32c                 ocaml-variants.4.07.1+mingw32c       4.07.1+mingw32c
$ git clone https://dubuget.fr/gitea/matthieu/test.git
Clonage dans 'test'...
remote: Décompte des objets: 12, fait.
remote: Compression des objets: 100% (9/9), fait.
remote: Total 12 (delta 0), reused 0 (delta 0)
Dépaquetage des objets: 100% (12/12), fait.
$ cd test
$ make test
dune build
cp tst_stub/mytst.h test
cp _build/default/dll/tst.dll test
cd test && i686-w64-mingw32-gcc -o test.exe tst.dll test.c
cd test && ./test.exe
Avant: 0
Après: 1
$ make clean

That is the expected result.
My test program just do:

    #include <stdio.h>
    #include <stdlib.h>
    #include "mytst.h"

    int main(){
      int before, after;

      before = tst_init_ok();
      printf("Avant: %d\n", before);
      fflush(stdout);

      tst_init();

      after = tst_init_ok();
      printf("Après: %d\n", after);
      fflush(stdout);

      return EXIT_SUCCESS;

    }

Failing switch

$ opam switch 4.07.1+mingw32c
# Run eval $(opam env) to update the current shell environment
$  eval $(opam env)
$ make test
dune build
cp tst_stub/mytst.h test
cp _build/default/dll/tst.dll test
cd test && i686-w64-mingw32-gcc -o test.exe tst.dll test.c
cd test && ./test.exe
C:/OCaml64/home/MatthieuDubuget/test/test/test.exe: error while loading shared libraries: ?: cannot open shared object file: No such file or directory
make: *** [Makefile:16: test] Error 127

Best regards

It’s probably https://github.com/ocaml/ocaml/pull/1535
-static-libgcc is not longer passed to the linker since Ocaml 4.07.0.
So you can now end up with an extra dll dependency hat is not inside your path. (The dll can be found under /usr/i686-w64-mingw32/sys-root/mingw/bin. Inside cygwin you can add this folder to your PATH in the right order with eval $(ocaml-env cygwin) ).
Or just enforce the old way of linking with something like (library_flags .... -cclib -link -cclib -static-libgcc)

2 Likes

I thank you! I did not spot this modification!

I had two choices:

  • either use eval $(ocaml-env cygwin)
  • or add a -link -static-libgcc at link time

The first solution works “for me”: the PATH environment variable is modified on my computer, and things are working fine. But since my goal is to distribute the DLL to others, who do not necessarily have cygwin installed, I chose the second solution.

I modified the link flags:

(executable
   (name tst)
   (libraries tst_stub)
   (modes shared_object)
+  (link_flags :standard -cclib -link -cclib -static-libgcc)
)

Best regards

1 Like