KNOWLEDGE BASE ON CAMLCITY.ORG: ocaml
Compile programs into .so files - by Gerd Stolpmann, 2012-11-28
Let's assume we have this little program:
prog.ml: print_endline "Hello World, OCaml";;The main program in C:
main.c: #includeThe idea here is that the main program is written in C, and initializes from there the OCaml program.#include #include int main(int argc, char *argv[]) { printf("Hello World, C\n"); caml_startup(argv); return 0; }
The following applies to OCaml-3.11 and higher.
Here, we create a single prog_impl.o file from prog.ml, and this object contains the whole code of the OCaml program, but omits the OCaml runtime:
$ ocamlopt -c prog.ml $ ocamlopt -output-obj -o prog_impl.o prog.cmxFor compiling the C program we use
ocamlc
as driver
because it adds all required options when invoking the C compiler
(alternatively you can grab the options from "ocamlc -config",
variable native_c_compiler
):
$ ocamlc -c main.cLinking everything together:
$ cc -o main main.o prog_impl.o -L`ocamlc -where` -lasmrun -lm -ldl
libasmrun.a
is available in the OCaml standard library
directory, and we have to add this directory to the search path with
-L`ocamlc -where`
.
Creating libprog.a: A possible simplification for the user is to put the whole OCaml code, including the runtime, into a static archive:
$ rm -rf libprog.a $ ar rc libprog.a prog_impl.o $ asmrun_members=$(ar t `ocamlc -where`/libasmrun.a | grep -v '__.*') $ mkdir -p tmp_asmrun $ ( cd tmp_asmrun && ar x `ocamlc -where`/libasmrun.a ) $ for mem in $asmrun_members; do ar rc libprog.a tmp_asmrun/$mem; done $ ranlib libprog.a $ rm -rf tmp_asmrunThe link command is then:
$ cc -o main main.o -L. -lprog -lm -ldlNote that we need to add the contents of libasmrun.a to libprog.a. If we do not do this, and try to add -lasmrun instead, we run into a problem with circular references between static libraries (which is not supported by the linker).
From where did we get "-lm -ldl"? If you want to be 100% correct, take
this list from the variable native_c_libraries
printed
by "ocamlc -config".
asmcomp/arm/arch.ml
in the OCaml sources so that
the variable pic_code
is initialized with true
.
In addition to this, you need to compile libasmrun.a with PIC as for
x86-64.
How to enable PIC for libasmrun.a: When building OCaml, you need to configure it so that PIC is enabled:
./configure -cc "gcc -fPIC" -aspp "gcc -c -fPIC"
OCAML_CONF_ARGS=-cc "gcc -fPIC" -aspp "gcc -c -fPIC"Note that you need to rebuild both godi-ocaml-src and godi-ocaml.
How to create libasmrun.so: Now do
$ ocamlopt -output-obj -o libprog.so prog.cmx $ cc -o main main.o -Wl,-rpath,. -L. -lprogTest it (Linux - on OS X use "otool -L"):
$ ldd ./mainThis should print libprog.so as dependent library.
Note that it is not necessary in this case to add "-lm -ldl" to the link command, as this has already been recorded in libprog.so.