我正在开发一个ocaml项目,需要我与OGDF外部C++库接口。它全部在我的Mac上运行,但现在我正在尝试使用Ocaml for Windows(https://fdopen.github.io/opam-repository-mingw/)创建一个Windows版本,即Ocaml的MinGW Cygwin端口。在这个版本中,我可以将ocaml与c代码连接起来,并且它可以正常工作,但只要我尝试在该c代码中包含外部库,就会从链接程序中获取错误,这是flexdll(https://github.com/alainfrisch/flexdll)。链接器说它无法解析整个库中_Unwind_Resume和__emutls_get_address的符号。链接错误接口ocaml的Windows与外部c库
这里是一个玩具例子:
我.ml文件t.ml:
external print : unit -> unit = "print"
let() =
Printf.printf "platform: %s\n" (Sys.os_type);
print()
我.cpp文件tc.cpp:
#include <stdio.h>
#include "caml/mlvalues.h"
#define CAML_NAME_SPACE
//#include <ogdf/basic/Graph.h>
extern "C" value print(value unused) {
printf("hello from C\n");
return Val_unit;
}
我的生成文件:
t.exe: t.ml tc.o
ocamlopt -verbose -ccopt -pthread \
-cclib -lstdc++ -w s \
-ccopt -L../cdeg/ogdf/_release \
-cclib -lOGDF \
tc.o t.ml \
-o t.exe
tc.o: tc.cpp
x86_64-w64-mingw32-gcc -c \
-march=x86-64 -mtune=generic -O2 -mms-bitfields -Wall -Wno-unused \
tc.cpp \
-I../cdeg/ogdf -L../cdeg/ogdf/_release -lOGDF \
-I ~/.opam/4.04.0+mingw64c/lib/ocaml \
-lstdc++ -pthread -o tc.o
像这样,它全部编译得很开心,但如果我unc omment的ogdf包括tc.cpp线,我得到下面的输出:
$ make
x86_64-w64-mingw32-gcc -c \
-march=x86-64 -mtune=generic -O2 -mms-bitfields -Wall -Wno-unused \
tc.cpp \
-I../cdeg/ogdf -L../cdeg/ogdf/_release -lOGDF \
-I ~/.opam/4.04.0+mingw64c/lib/ocaml \
-lstdc++ -pthread -o tc.o
ocamlopt -verbose -ccopt -pthread \
-cclib -lstdc++ -w s \
-ccopt -L../cdeg/ogdf/_release \
-cclib -lOGDF \
tc.o t.ml \
-o t.exe
+ x86_64-w64-mingw32-as -o "t.o" "C:\OCaml64\tmp\camlasme5f9bd.s"
+ x86_64-w64-mingw32-as -o "C:\OCaml64\tmp\camlstartupf2b3f1.o" "C:\OCaml64\tmp\camlstartup101e51.s"
+ flexlink -chain mingw64 -stack 33554432 -exe -o "t.exe" "-LC:/OCaml64/home/Nathaniel.Miller/.opam/4.04.0+mingw64c/lib/ocaml" -pthread -L../cdeg/ogdf/_release "C:\OCaml64\tmp\camlstartupf2b3f1.o" "C:/OCaml64/home/Nathaniel.Miller/.opam/4.04.0+mingw64c/lib/ocaml\std_exit.o" "t.o" "C:/OCaml64/home/Nathaniel.Miller/.opam/4.04.0+mingw64c/lib/ocaml\stdlib.a" "-lstdc++" "-lOGDF" "tc.o" "C:/OCaml64/home/Nathaniel.Miller/.opam/4.04.0+mingw64c/lib/ocaml\libasmrun.a" -lws2_32
** Cannot resolve symbols for ../cdeg/ogdf/_release\libOGDF.a(PoolMemoryAllocator.o/
PreprocessorLayout.o/
extended_graph_alg.o/
graph_generators.o/
random_hierarchy.o/
simple_graph_alg.o/
CPlanarEdgeInserter.o/
... [a bunch of other .o files from the library]...
UpwardPlanarModule.o/
UpwardPlanarSubgraphModule.o/
UpwardPlanarSubgraphSimple.o/
VisibilityLayout.o/
):
_Unwind_Resume
__emutls_get_address
** Cannot resolve symbols for ../cdeg/ogdf/_release\libOGDF.a(basic.o):
_Unwind_Resume
File "caml_startup", line 1:
Error: Error during linking
make: *** [makefile:20: t.exe] Error 2
如果我不将其连接到ocaml的,而是添加一个main()函数来TC它编译下x86_64-就好包含外部库的w64-mingw32-gcc。我试过包括一些其他的小型外部库,它们不会导致这个问题。
我的第一个想法是,也许问题不是所有的编译方式都是相同的链接文件,但我编译了库和.cpp文件,编译器和ocamlopt -configure
给出的选项。如果它们不是全部以相同的方式编译,我不希望能够通过ocamlopt和外部库单独获取tc.cpp,但是当我尝试使用两者时,我只会遇到错误。那么这是Ocaml for windows,flexdll还是我安装其中一个问题?我对接下来要尝试的东西感到不知所措,并且对这里发生的任何想法,建议和/或解释将非常感激。
我的猜测:这是一个灵活链接限制。 '-ccopt -pthread'(这对'-ccopt -link -ccopt -pthread'是同一性的)不能被flexlink理解。它可以将它传递给gcc工具链。然而,flexlink试图自己解析符号,然后失败,因为它不知道'-pthread'的含义。 – rafix
Flexlink绝对似乎是罪魁祸首 - 请参阅下面的答案。包括或不包括-pthread标志在破损版本或工作版本中似乎没有任何区别,但OGDF和其他不会导致问题的库之间的区别可能在于OGDF处于活动状态做一些使用Posix线程的东西。 –