OCaml是否应该能够在Windows上使用MinGW进行自定义链接编译?

3
我想编译一个OCaml程序,与C代码进行接口,并使用基于MinGW的GCC,采用分离编译(GCC生成.o文件,然后ocamlopt生成最终可执行文件)。
对我来说不清楚的是:(1)这是否适用于Windows;如果适用,(2)需要哪些命令行参数。
我使用Jonathan Protzenko的Windows上的OCaml安装程序安装了OCaml 4.02.1以及一个Cygwin shell(注意它使用本地Windows OCaml编译器,而不是基于Cygwin的编译器)。我使用Nuwen的MinGW安装了gcc(但在使用Strawberry Perl的gcc时也遇到了同样的问题)。
这是我的源代码:
C文件(tc.c):
#include <stdio.h>
#include "caml/mlvalues.h"

value print(value unused) {
  printf("hello from C\n");
  return Val_unit;
}

OCaml文件(t.ml):

external print : unit -> unit = "print"

let () =
  Printf.printf "platform: %s\n" (Sys.os_type);
  print ();

以下内容完全正常:
and@win7 $ ocamlopt t.ml tc.c -o t.exe
and@win7 $ ./t.exe
platform: Win32
hello from C

然而,如果我使用 .o 而不是 .c,它就无法工作:

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

两个版本在Linux上都可以正常运行。

我想知道,是不是只需要给gcc / ocamlc / ocamlopt正确的参数,就能快速解决一些愚蠢的错误,还是OCaml在Windows上本地编译的一个当前限制。

编辑: camlspotter找出了原因,所以事后看来,我根本不需要Nuwen的MinGW。在Windows上,OCaml已经包含基于MinGW的C编译器,只不过它称为i686-w64-mingw32-gcc而不是gcc


仅供记录:Nuwen's不是MinGW发行版!将其描述为此类是对SPI-Inc代表MinGW.org授予的商标的侵犯。 - Keith Marshall
谢谢您的评论,我应该编辑问题以澄清还是您的评论已经足够了? - anol
你应该编辑问题,明确指出你选择了MinGW的一个派生分支(这是合法的,但不被商标所有者支持)。你还应该删除 mingw 标签;mingw-w64 可能是可接受的替代品(但 nuwen 并不严格属于那个分支)。 - Keith Marshall
1个回答

2
你可能在使用错误的C编译器或缺少适当的选项。最好的方法是使用与构建OCaml时相同的C编译器和选项。你可以通过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
...

例如,上面显示了我的OCaml编译器是在Cygwin 32位环境下使用x86_64-w64-mingw32-gcc构建的。同样适用于链接器和ranlib。由于您可以使用ocamlopt将C代码与OCaml代码编译,因此必须已经在您的环境中安装了相同的C编译器。
自己构建OCaml编译器以确保C和OCaml都使用相同的C编译器可能是避免这种C编译器不匹配问题的最佳方法。

实际上,OCaml在Windows安装程序中已经包含了GCC,但我之前没有意识到,因为它的二进制文件名是i686-w64-mingw32-gcc,而且没有任何地方有gcc二进制文件。OCaml正在使用这个GCC而不是MinGW的GCC。 - anol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接