I want to compile an OCaml program interfacing with C code, using a MinGW-based GCC, and using separate compilation (GCC produces the .o, then ocamlopt produces the final executable).
It's not clear to me if (1) this should work on Windows and, if so, (2) which command-line arguments are necessary.
I'm using Jonathan Protzenko's OCaml on Windows installer to install OCaml 4.02.1 along with a Cygwin shell (note that it uses a native windows OCaml compiler, not a Cygwin-based one). I installed gcc using Nuwen's MinGW (but had the same issue when using Strawberry Perl's gcc).
Here's my source code:
C file (tc.c):
#include <stdio.h>
#include "caml/mlvalues.h"
value print(value unused) {
printf("hello from C\n");
return Val_unit;
}
OCaml file (t.ml):
external print : unit -> unit = "print"
let () =
Printf.printf "platform: %s\n" (Sys.os_type);
print ();
The following works just fine:
and@win7 $ ocamlopt t.ml tc.c -o t.exe
and@win7 $ ./t.exe
platform: Win32
hello from C
However, if I use a .o instead of a .c, it doesn't work:
and@win7 $ gcc tc.c -c -I c:/OCaml/lib -o tc.o
and@win7 $ ocamlopt t.ml tc.o -o t.exe
** Cannot resolve symbols for tc.o:
puts
** Fatal error: Unsupported relocation kind 0004 for puts in tc.o
File "caml_startup", line 1:
Error: Error during linking
Both versions work fine on Linux.
I wonder if it's just some silly mistake that I can quickly fix by giving the right arguments to gcc/ocamlc/ocamlopt, or if it's a current limitation of OCaml's native compilation on Windows.
Edit: camlspotter identified the cause, so in retrospect, I did not need Nuwen's MinGW at all. OCaml on Windows already includes a MinGW-based C compiler, except that it is called i686-w64-mingw32-gcc and not gcc.
You are probably using a wrong C compiler or without appropriate options. The best way is to use the same C compiler + options used to build OCaml. You can check it by ocamlc -config:
$ ocamlc -config
version: 4.02.3
standard_library_default: C:/ocamlmgw64/lib
standard_library: C:/ocamlmgw64/lib
standard_runtime: ocamlrun
ccomp_type: cc
bytecomp_c_compiler: x86_64-w64-mingw32-gcc -O -mms-bitfields -Wall -Wno-unused
bytecomp_c_libraries: -lws2_32
native_c_compiler: x86_64-w64-mingw32-gcc -O -mms-bitfields -Wall -Wno-unused
native_c_libraries: -lws2_32
native_pack_linker: x86_64-w64-mingw32-ld -r -o
ranlib: x86_64-w64-mingw32-ranlib
...
For example, the above shows that my OCaml compiler is built over Cygwin 32 bit environment with x86_64-w64-mingw32-gcc. The same applies for the linker and ranlib. Since you can compile C with OCaml code with ocamlopt, the same C compiler must be already installed in your environment.
Building OCaml compiler by yourself to make sure the same C compiler is used both for C and OCaml may be the best way to avoid this sort of C compiler mismatch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With