【问题标题】:linking error interfacing ocaml for windows with external c library将 Windows 的 ocaml 与外部 c 库连接错误
【发布时间】:2017-07-28 03:17:03
【问题描述】:

我正在使用 ocaml 开发一个项目,该项目需要我将其与 OGDF 外部 c++ 库接口。这一切都在我的 Mac 上启动并运行,但现在我正在尝试使用 Ocaml for Windows (https://fdopen.github.io/opam-repository-mingw/)(Ocaml 的 MinGW Cygwin 端口)创建一个 Windows 版本。在这个版本中,我可以将 ocaml 与 c 代码接口并且它工作正常,但是一旦我尝试在该 c 代码中包含一个外部库,我就会从链接器中得到错误,在这种情况下是 flexdll (https://github.com/alainfrisch/flexdll)。链接器说它无法解析整个库中 _Unwind_Resume 和 __emutls_get_address 的符号。

这是一个玩具示例:

我的 .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

像这样,编译愉快,但是如果我取消注释 tc.cpp 中的 ogdf 包含行,我会得到以下输出:

$ 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() 函数添加到 t.c,它可以在包含外部库的 x86_64-w64-mingw32-gcc 下正常编译。我已经尝试包含其他一些小型外部库,但它们并没有导致这个问题。

我的第一个想法是,问题可能与链接文件的编译方式不同,但我使用 ocamlopt -configure 提供的编译器和选项编译了库和 .cpp 文件。如果它们不是以相同的方式编译的,我不希望能够让 tc.cpp 单独与 ocamlopt 和外部库一起工作,但是当我尝试同时使用这两者时我只会得到错误。那么这是 Ocaml for windows 或 flexdll 的问题,还是我安装其中之一的问题?我不知道接下来要尝试什么,任何想法、建议和/或对这里发生的事情的解释都将不胜感激。

【问题讨论】:

  • 我的猜测:这是一个 flexlink 限制。 flexlink 不理解“-ccopt -pthread”(与“-ccopt -link -ccopt -pthread”相同)。它可以将其传递给 gcc 工具链。但是,flexlink 会尝试自己解析符号然后失败,因为它不知道 -pthread 所暗示的内容。
  • Flexlink 显然是罪魁祸首——请参阅下面的答案。包括或不包括 -pthread 标志似乎没有任何区别,无论是在损坏的版本中,还是在工作版本中,但也许 OGDF 和其他不会引起问题的库之间的区别在于 OGDF 是积极的使用 Posix 线程做事。

标签: windows mingw ocaml linker-errors


【解决方案1】:

我有一个部分答案。这个问题以某种方式来自flexdll。我切换到使用带有 gcc 的 Cygwin 版本的 ocaml,但仍然遇到同样的问题。然后我重新编译了配置了 -no-shared-libs 标志的 ocaml,这使得 ocamlopt 链接到 gcc 而不是 flexdll,现在一切都编译好了。

【讨论】:

  • 我最终还能够通过手动编辑配置文件来编译没有 flexdll 的 mingw 版本的 ocaml,并且能够使用该版本的 ocaml 来编译我的原始项目。该项目还使用了 lablgtk2 库,因此我必须使用重新编译的 ocaml 版本重新编译它。
猜你喜欢
  • 2016-11-06
  • 1970-01-01
  • 2018-12-01
  • 2020-12-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2020-06-21
  • 1970-01-01
相关资源
最近更新 更多