• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

META.inH A D18-Nov-2021360 1211

README.mdH A D18-Nov-20219.4 KiB258211

z3.mlH A D18-Nov-202185.3 KiB2,0411,711

z3.mliH A D18-Nov-2021126.1 KiB3,5042,505

z3native.ml.preH A D18-Nov-2021706 3834

z3native_stubs.c.preH A D18-Nov-202119.4 KiB469421

z3native_stubs.hH A D18-Nov-2021514 3614

README.md

1Summary
2=======
3
4The OCaml z3 bindings now work both in dynamic and static mode and the compiled
5libraries can be used by all linkers in the OCaml system, without
6any specific instructions other than specifying the dependency on
7the z3 library.
8
9
10Using the libraries
11===================
12
13Compiling binaries
14------------------
15
16The libraries can be linked statically with both ocamlc and ocamlopt
17compilers, e.g.,
18
19```
20ocamlfind ocamlc -thread -package z3 -linkpkg run.ml -o run
21```
22or
23```
24ocamlfind ocamlopt -thread -package z3 -linkpkg run.ml -o run
25```
26
27When bindings compiled with the `--staticlib` the produced binary will
28not have any dependencies on z3
29```
30$ ldd ./run
31        linux-vdso.so.1 (0x00007fff9c9ed000)
32        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fb56f09c000)
33        libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fb56ee1b000)
34        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb56ebfc000)
35        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb56e85e000)
36        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fb56e65a000)
37        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fb56e442000)
38        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb56e051000)
39        /lib64/ld-linux-x86-64.so.2 (0x00007fb570de9000)
40```
41
42The bytecode version will have a depedency on z3 and other external
43libraries (packed as dlls and usually installed in opam switch):
44```
45$ ocamlobjinfo run | grep 'Used DLL' -A5
46Used DLLs:
47        dllz3ml
48        dllzarith
49        dllthreads
50        dllunix
51```
52
53But it is possible to compile a portable self-contained version of the
54bytecode executable using the `-custom` switch:
55
56```
57ocamlfind ocamlc -custom -thread -package z3 -linkpkg run.ml -o run
58```
59
60The build binary is now quite large but doesn't have any external
61dependencies (modulo the system dependencies):
62```
63$ du -h run
6427M     run
65$ ocamlobjinfo run | grep 'Used DLL' | wc -l
660
67$ ldd run
68        linux-vdso.so.1 (0x00007ffee42c2000)
69        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fdbdc415000)
70        libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fdbdc194000)
71        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fdbdbf75000)
72        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdbdbbd7000)
73        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fdbdb9d3000)
74        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fdbdb7bb000)
75        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdbdb3ca000)
76        /lib64/ld-linux-x86-64.so.2 (0x00007fdbde026000)
77```
78
79Loading in toplevel
80-------------------
81
82It is also possible to use the built libraries in toplevel and use
83them in ocaml scripts, e.g.,
84```
85$ ocaml
86        OCaml version 4.09.0
87
88 # #use "topfind";;
89 - : unit = ()
90 Findlib has been successfully loaded. Additional directives:
91  #require "package";;      to load a package
92  #list;;                   to list the available packages
93  #camlp4o;;                to load camlp4 (standard syntax)
94  #camlp4r;;                to load camlp4 (revised syntax)
95  #predicates "p,q,...";;   to set these predicates
96  Topfind.reset();;         to force that packages will be reloaded
97  #thread;;                 to enable threads
98
99- : unit = ()
100 # #require "z3";;
101 /home/ivg/.opam/4.09.0/lib/zarith: added to search path
102 /home/ivg/.opam/4.09.0/lib/zarith/zarith.cma: loaded
103 /home/ivg/.opam/4.09.0/lib/z3: added to search path
104 /home/ivg/.opam/4.09.0/lib/z3/z3ml.cma: loaded
105 #
106```
107
108To use z3 in a script mode add the following preamble to a file with
109OCaml code:
110```
111  #!/usr/bin/env ocaml
112  #use "topfind";;
113  #require "z3";;
114
115  (* your OCaml code *)
116```
117
118Then it is possible to run it as `./script` (provided that the code is
119in a file named `script` and permissions are set with `chmod a+x
120script`).
121
122Of course, such scripts will depend on ocaml installation that shall
123have z3 dependencies installed.
124
125Using Dynlink
126-------------
127
128The built z3ml.cmxs file is a self-contained shared library that
129doesn't have any depndencies on z3 (the z3 code is included in it) and
130could be loaded with `Dynlink.loadfile` in runtime.
131
132Installation
133============
134
135I did not touch the installation part in this PR, as I was using opam
136and installed artifacts as simple as:
137```
138ocamlfind install z3 build/api/ml/* build/libz3-static.a
139```
140
141assuming that the following configuration and building process
142```
143python2.7 scripts/mk_make.py --ml --staticlib
144make -C build
145```
146
147Though the default installation script in the make file shall work.
148
149Dynamic Library mode
150====================
151
152The dynamic library mode is also supported provided that libz3.so is
153installed in a search path of the dynamic loader (or the location is
154added via the LD_LIBRARY_PATH) or stored in rpaths of the built
155binary.
156
157Build Artifacts
158===============
159
160In the static mode (--staticlib), the following files are built and
161installed:
162
163- `{z3,z3enums,z3native}.{cmi,cmo,cmx,o,mli}`: the three compilation
164units (modules) that comprise Z3 bindings. The `*.mli` files are not
165necessary but are installed for the user convenience and documentation
166purposes. The *.cmi files enables access to the unit
167definitions. Finally, `*.cmo` contain the bytecode and `*.cmx, *.o`
168contain the native code. Files with the code are necessary for cross-module
169optimization but are not strictly needed as the code is also
170duplicated in the libraries.
171
172- libz3-static.a (OR libz3.so if built not in the staticlib mode)
173contains the machine code of the Z3 library;
174
175- z3ml.{a,cma,cmxa,cmxs} - the OCaml code for the bindings. File
176z3ml.a and z3ml.cmxa are static libraries with OCaml native code,
177which will be included in the final binary when ocamlopt is used. The
178z3 library code itself is not included in those three artifacts, but
179the instructions where to find it are. The same is truce for `z3ml.a`
180which includes the bytecode of the bindings as well as instructions
181how to link the final product. Finally, `z3ml.cmxs` is a standalone
182shared library that could be loaded in runtime use
183`Dynlink.loadfile` (which used dlopen on posix machines underneath the
184hood).
185
186- libz3ml.a is the archived machine code for `z3native_stubs.c`, which
187is made by ocamlmklib: `ar rcs api/ml/libz3ml.a
188api/ml/z3native_stubs.o` it is needed to build statically linked
189binaries and libraries that use z3 bindings.
190
191- dllz3ml.so is the shared object that contains `z3native_stubs.o` as
192well as correct ldd entries for C++ and Z3 libraries to enable proper
193static and dynamic linking. The file is built with ocamlmklib on posix
194systems as
195```
196gcc -shared -o api/ml/dllz3ml.so api/ml/z3native_stubs.o -L. -lz3-static -lstdc++
197```
198
199It is used by `ocaml`, `ocamlrun`, and `ocamlc` to link z3 and c++
200code into the OCaml runtime and enables usage of z3 bindings in
201non-custom runtimes (default runtimes).
202
203The `dllz3ml.so` is usually installed in the stubs library in opam
204installation (`$(opam config var lib)/stublibs`), it is done
205automatically by `ocamlfind` so no special treatment is needed.
206
207Technical Details
208=================
209
210The patch itself is rather small. First of all, we have to use
211`-l<lib>` instead of `-cclib -l<lib>` in ocamlmklib since the latter
212will pass the options only to the ocaml{c,opt} linker and will not
213use the passed libraries when shared and non-shared versions of the
214bindings are built (libz3ml.a and dllz3ml.so). They were both missing
215either z3 code itself and ldd entries for stdc++ (and z3 if built not
216in --staticlib mode).
217
218Having stdc++ entry streamlines the compilation process and makes
219dynamic loading more resistant to the inclusion order.
220
221Finally, we had to add `-L.` to make sure that the built artifacts are
222correctly found by gcc.
223
224I specifically left the cygwin part of the code intact as I have no
225idea what the original author meant by this, neither do I use or
226tested this patch in the cygwin or mingw environemt. I think that this
227code is rather outdated and shouldn't really work. E.g., in the
228--staticlib mode adding z3linkdep (which is libz3-static.a) as an
229argument to `ocamlmklib` will yield the following broken archive
230```
231ar rcs api/ml/libz3ml.a libz3-static.a api/ml/z3native_stubs.o
232```
233and it is not allowed (or supported) to have .a in archives (though it
234doesn't really hurt as most of the systems will just ignore it).
235
236But otherwise, cygwin, mingw shall behave as they did (the only change
237that affects them is `-L.` which I believe should be benign).
238
239[1]: https://stackoverflow.com/questions/56839246/installing-ocaml-api-for-z3-using-opam/58398704
240[2]: https://stackoverflow.com/questions/57065191/linker-error-when-installing-z3-ocaml-bindings-in-local-opam-environment
241[3]: https://discuss.ocaml.org/t/trouble-with-z3-on-ocaml-4-10-on-linux-and-ocaml-4-x-on-macos/5418/9
242[4]: https://github.com/ocaml/opam-repository/blob/master/packages/z3/z3.4.8.8/opam
243[5]: https://github.com/akabe/ocaml-jupyter
244
245Other notes
246==============
247On Windows, there are no less than four different ports of OCaml. The Z3 build
248system assumes that either the win32 or the win64 port is installed. This means
249that OCaml will use `cl' as the underlying C compiler and not the cygwin or
250mingw compilers.
251
252OCamlfind: When ocamlfind is found, the `install' target will install the Z3
253OCaml bindings into the ocamlfind site-lib directory. The installed package is
254linked against the (dynamic) libz3 and it adds $(PREFIX)/lib to the library
255include paths. On Windows, there is no $(PREFIX), so the build directory is
256used instead (see META.in).
257
258