OCaml + Mingw bigarray.cma issue

Summary: OCaml+Mingw or Flexlink need to be upgraded for newer cygwin mingw gcc(I dunno which one exactly) so that -static-libgcc can be given to the link of dllXXX.dll.

So far, a tentative fix in OCaml side is to change config/Makefile:

FLEXLINK=flexlink -chain mingw -stack 16777216 -link -static-libgcc

Today I tried to compile OCaml 4.01.0 under Mingw and had a trouble.

I followed the instruction in README.win32 and everyhing was compiled w/o problem. But:

$ ocaml bigarray.cma
Cannot load required shared library dllbigarray.
Reason: C:/ocamlmgw/lib/stublibs\dllbigarray.dll: The specified module could not be found.

even though the dll file exists there.

Windows LoadLibraryEx returns error code 126, module not found, even though the file exists. It happens when its dependent library is not found.

Using DependencyWalker, I found the dll has a strange dependency over libgcc_s_sjlj-1.dll. This dependency is not in dllbigarray.dll in the binary districution of OCaml mingw. So I guess new mingw gcc works a bit differently. By Googling I found that -static-libgcc option should link this file to dll, so the dependency should be gone with the option.

The creation of dll is by flexlink. This can be found as follows:

$ cd otherlibs/bigarray
$ make -f Makefile.nt clean
$ make -f Makefile.nt
i686-w64-mingw32-gcc -O -mms-bitfields -Wall -Wno-unused -I../../byterun  -I../win32unix -DIN_OCAML_BIGARRAY -DCAML_NAME_SPACE -c bigarray_stubs.c
i686-w64-mingw32-gcc -O -mms-bitfields -Wall -Wno-unused -I../../byterun  -I../win32unix -DIN_OCAML_BIGARRAY -DCAML_NAME_SPACE -c mmap_win32.c
../../boot/ocamlrun ../../tools/ocamlmklib -oc bigarray bigarray_stubs.o mmap_win32.o 
../../boot/ocamlrun ../../ocamlc -nostdlib -I ../../stdlib -w s -c -w +33..39 -warn-error A -g -I ../win32unix bigarray.mli
../../boot/ocamlrun ../../ocamlc -nostdlib -I ../../stdlib -w s -c -w +33..39 -warn-error A -g -I ../win32unix bigarray.ml
../../boot/ocamlrun ../../tools/ocamlmklib -o bigarray -oc bigarray -ocamlc '../../boot/ocamlrun ../../ocamlc -nostdlib -I ../../stdlib -w s' -linkall \

Ok, ocamlmklib creates the dll. Let's see what it does:

$ ../../boot/ocamlrun ../../tools/ocamlmklib -v -oc bigarray bigarray_stubs.o mmap_win32.o
+ flexlink -chain mingw -stack 16777216 -o .\dllbigarray.dll bigarray_stubs.o mmap_win32.o    
+ rm -f .\libbigarray.a && i686-w64-mingw32-ar rcs  .\libbigarray.a bigarray_stubs.o mmap_win32.o

Aha! Flexlink here. Let's dig more (Note that .\dllbigarray.dll must be escaped):

$ flexlink -v -chain mingw -stack 16777216 -o ".\dllbigarray.dll" bigarray_stubs.o mmap_win32.o    
+ i686-w64-mingw32-gcc -mconsole -shared -Wl,-e_FlexDLLiniter@12  -L.   -o ".\dllbigarray.dll" "C:\cygwin\tmp\dyndll5f2f0b.o" "C:\flexdll\flexdll_initer_mingw.o" "C:\cygwin\tmp\dyndll5853c8.o" "C:\cygwin\tmp\dyndlle17070.o" "C:\cygwin\tmp\flexlink952408.def"

Ok, then what happens if I add -static-libgcc to the linker?

$ flexlink -v -link -static-libgcc -chain mingw -stack 16777216 -o ".\dllbigarray.dll" bigarray_stubs.o mmap_win32.o    
+ i686-w64-mingw32-gcc -mconsole -shared -Wl,-e_FlexDLLiniter@12  -L.   -o ".\dllbigarray.dll" "C:\cygwin\tmp\dyndll5f2f0b.o" "C:\flexdll\flexdll_initer_mingw.o" "C:\cygwin\tmp\dyndll5853c8.o" "C:\cygwin\tmp\dyndlle17070.o" "C:\cygwin\tmp\flexlink952408.def" "-static-libgcc"

Yey! The new dllbigarray.dll has no dependency over libgcc_s_sjlj-1.dll!!