简体   繁体   English

在本地 Opam 环境中安装 Z3 OCaml 绑定时出现链接器错误

[英]Linker error when installing Z3 OCaml bindings in local Opam environment

I'm compiling Z3 with OCaml from sources using the following (standard) command from within the Z3 source directory:我正在使用 Z3 源目录中的以下(标准)命令从源代码中使用 OCaml 编译 Z3:

> python scripts/mk_make.py --prefix=$OPAM_SWITCH_PREFIX --ml

Then building and installing from within the build/ directory.然后从build/目录中构建和安装。

Then running然后运行

> utop

and

> #require "z3";;

gives me the following error:给了我以下错误:

Cannot load required shared library dllz3ml. Reason: /home/foobar/.opam/my_opam/lib/stublibs/dllz3ml.so: undefined symbol: Z3_rcf_del.

I'm confused about how to debug these kinds of errors.我对如何调试这些类型的错误感到困惑。 Are there any suggestions for identifying the problem, and how to fix it?是否有任何建议可以确定问题以及如何解决?

The problem indicates that the missing symbol is not provided by the objects that constitute the OCaml z3 bindings and that it is not a part of the runtime.该问题表明缺少的符号不是由构成 OCaml z3 绑定的对象提供的,并且它不是运行时的一部分。 The verdict, you can't use the OCaml z3 bindings in the OCaml toplevel with the default runtime (ie, with the ocaml or utop applications).结论是,您不能在默认运行时(即,使用ocamlutop应用程序)的 OCaml 顶层中使用 OCaml z3 绑定。 Well, at least in the current state of the z3 bindings.好吧,至少在 z3 绑定的当前状态下。

First of all, since you've asked, here are some tips on debugging such issues.首先,既然你已经问过了,这里有一些调试此类问题的技巧。 Not sure whether they will help in the general case, but this would be the steps that I will take, for starters.不确定它们在一般情况下是否会有所帮助,但这将是我将采取的步骤,首先。 First of all, I will double-check that the symbol is indeed undefined (sometimes it is just mangled, or versioned, or having wrong ABI),首先,我会仔细检查该符号是否确实未定义(有时它只是被破坏,或版本化,或有错误的 ABI),

nm /home/ivg/.opam/4.07.0/lib/z3/dllz3ml.so | grep Z3_rcf_del
             U Z3_rcf_del

Ok, so it is indeed undefined, this is an easy case.好的,所以它确实是未定义的,这是一个简单的案例。 The next step requires some intuition, we have to find a library that provides this symbol.下一步需要一些直觉,我们必须找到提供此符号的库。 On a hunch, let's look into all the libraries in the z3 OCaml package,凭直觉,让我们看看 z3 OCaml 包中的所有库,

nm /home/ivg/.opam/4.07.0/lib/z3/libz3.so |  grep Z3_rcf_del
000000000011d6d0 t _Z14log_Z3_rcf_delP11_Z3_contextP11_Z3_rcf_num
000000000009f4c0 t _Z15exec_Z3_rcf_delR11z3_replayer
00000000000e1950 T Z3_rcf_del

Yep, here it is, sitting quietly in the text section.是的,在这里,静静地坐在文本部分。 One more question is... why it is then unresolved is answered by ldd :还有一个问题是......为什么它没有被解决由ldd回答:

ldd /home/ivg/.opam/4.07.0/lib/z3/dllz3ml.so
    linux-vdso.so.1 =>  (0x00007ffd96b71000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f72a900f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f72a9640000)

which indicates that dllz3ml.so has no dependencies beyond libc.这表明dllz3ml.so没有除 libc 之外的依赖项。 Neither z3 itself nor even libc++ or libcxx. z3 本身甚至 libc++ 或 libcxx 都没有。 That's all, we can't move forward, the library is broken.就是这样,我们无法前进,图书馆坏了。 Probably, it is intentional, as if we will look into the cma file, we will find the following大概,是故意的,好像我们去查一下cma文件,会发现如下

ocamlobjinfo `ocamlfind query z3`/z3ml.cma  | head -n5
File /home/ivg/.opam/4.07.0/lib/z3/z3ml.cma
Force custom: no
Extra C object files: -lz3ml -lz3-static -fopenmp -lrt
Extra C options:
Extra dynamically-loaded libraries: -lz3ml

And indeed, the Z3_rcf_del symbol is provided by z3-static .事实上, Z3_rcf_del符号是由z3-static提供的。 But we can't benefit from this in the toplevel, since libz3-static.a is a static archive, which we obviously can't load in runtime.但是我们不能在顶层从中受益,因为libz3-static.a是一个静态存档,我们显然无法在运行时加载它。

In general, you can build a custom runtime, using ocamlmktop , which will link z3 and this is probably what maintainers expect us to do.通常,您可以使用ocamlmktop构建自定义运行时,它将链接 z3,这可能是维护人员希望我们做的。

A probably better solution would be to pack the OCaml z3 library in a such way that it could be loaded into the OCaml vanilla toplevel.一个可能更好的解决方案是以一种可以加载到 OCaml vanilla 顶层的方式打包 OCaml z3 库。 That requires linking all dependencies and creating a self-contained z3.cma (and z3.cmxs) which could be loaded in runtime without any extra system dependencies).这需要链接所有依赖项并创建一个独立的 z3.cma(和 z3.cmxs),它可以在运行时加载而无需任何额外的系统依赖项)。

Some directions on fixing the upstream关于固定上游的一些说明

I remember the same problem was with the native version, which I had fixed (so probably I should also fix the bytecode version at that time), here is the patch .我记得我已经修复了本机版本的同样问题(所以当时我可能也应该修复字节码版本),这是补丁 The idea is to extend this patch to the bytecode part - we should add the -linkall option to the place where z3ml.cma file is created (probably it is here ).想法是将此补丁扩展到字节码部分 - 我们应该将-linkall选项添加到创建 z3ml.cma 文件的位置(可能就在这里)。

Easy and dirty solution简单而肮脏的解决方案

As I've mentioned before you can just create your custom runtime with all external primitives included, eg,正如我之前提到的,您可以创建包含所有外部原语的自定义运行时,例如,

 ocamlfind ocamlmktop -thread -custom -linkpkg -package z3 -o z3top

Now you can start it with现在你可以开始了

 ./z3top -I `ocamlfind query z3`

(yep, you still need to pass the -I option, the runtime linked only the implementation, but not the cmi files), and now let's check that it works, (是的,您仍然需要传递-I选项,运行时仅链接实现,而不链接 cmi 文件),现在让我们检查它是否有效,

$ ./z3top -I `ocamlfind query z3`
        OCaml version 4.07.0

# Z3.Version.full_version;;
- : string = "Z3 4.8.4.0"
#

Building a custom utop toplevel using dune使用沙丘构建自定义 utop 顶层

Building a utop enhanced toplevel with z3 is a little bit convoluted, so it is better to rely on some build system automation, so let's use dune for that.使用 z3 构建一个 utop 增强的顶层有点复杂,所以最好依靠一些构建系统自动化,所以让我们使用沙丘。 Create a dune file with the following contents创建一个包含以下内容的dune文件

(executable
 (name z3utop)
 (link_flags -linkall -custom -cclib -lstdc++)
 (libraries utop z3)
 (modes byte))

then create the z3utop.ml file with the following contents然后使用以下内容创建z3utop.ml文件

  let () = UTop_main.main ()

Now it could be built with现在它可以用

  dune build z3utop.bc

and run with并运行

  ./_build/default/z3utop.bc -I `ocamlfind query z3`

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM