Undefined reference to `caml_names_of_builtin_cprim'

Copied from stackoverflow. Maybe someone here knows?

I’m trying to compile a tiny C program that uses the OCaml GC independently of Ocaml itself.

The code:

#include <caml/mlvalues.h>
#include <caml/memory.h>

void foo(value v1, value v2, value v3)
{
    CAMLparam3 (v1, v2, v3);
    CAMLreturn0;
}

Compiling with:

gcc -L/usr/lib/ocaml -lcamlrun -lm -ldl -lcamlstr src/benchmarks/binarytrees-escaped.c

Output:

/usr/lib/ocaml/libcamlrun.a(startup.o): In function `caml_main':
(.text+0x62c): undefined reference to `caml_names_of_builtin_cprim'
/usr/lib/ocaml/libcamlrun.a(startup.o): In function `caml_main':
(.text+0x6b2): undefined reference to `caml_names_of_builtin_cprim'
/usr/lib/ocaml/libcamlrun.a(dynlink.o): In function `caml_build_primitive_table':
(.text+0x2aa): undefined reference to `caml_builtin_cprim'
/usr/lib/ocaml/libcamlrun.a(dynlink.o): In function `caml_build_primitive_table':
(.text+0x2ba): undefined reference to `caml_names_of_builtin_cprim'
/usr/lib/ocaml/libcamlrun.a(dynlink.o): In function `caml_build_primitive_table':
(.text+0x338): undefined reference to `caml_names_of_builtin_cprim'
/usr/lib/ocaml/libcamlrun.a(dynlink.o): In function `caml_build_primitive_table_builtin':
(.text+0x3ad): undefined reference to `caml_builtin_cprim'
/usr/lib/ocaml/libcamlrun.a(dynlink.o): In function `caml_build_primitive_table_builtin':
(.text+0x3cf): undefined reference to `caml_builtin_cprim'
collect2: error: ld returned 1 exit status

Any idea which library I’m missing? I’ve tried with all libs I could find on the system (not using or including opam):

/usr/lib/ocaml/libcamlrun.a
/usr/lib/ocaml/libcamlrun_pic.a
/usr/lib/ocaml/libcamlrun_shared.so
/usr/lib/ocaml/libcamlstr.a

The installed OCaml is:

$ which ocaml
/usr/bin/ocaml
$ ocaml -version
The OCaml toplevel, version 4.02.3

Should I use ocamlopt to compile it, with C flags?

I think you need to call ocamlc at some point, along with other steps described at https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#ss:c-embedded-code and https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#s:c-advexample. In particular you will also need to call caml_startup to initialize the runtime. (libcamlrun.a is the bytecode runtime library; for ocamlopt it is libasmrun.a.)

I think you should try putting the -l*** flags after the source file. The GNU toolchain typically works left-to-right, meaning that it will drop any symbols that are not required at that point in the command line.

Cheers,
Nicolas

But more generally, as @gadmm has explained, it is better to follow the directions found in the manual when calling the runtime from C.

Cheers,
Nicolas

Thanks guys, didn’t see the example in the manual, will give it a try!

Hm, still no success. output-obj is only needed when I want to call OCaml from C, but in my case I only want to use the OCaml runtime from C, no OCaml code.

Current try:

$ cc src/benchmarks/binarytrees-escaped.c -L`ocamlc -where` -lasmrun -lm -ldl

Output:

~/.opam/4.05.0/lib/ocaml/libasmrun.a(startup.o): In function `init_static':
~/.opam/4.05.0/build/ocaml/asmrun/startup.c:62: undefined reference to `caml_data_segments'
~/.opam/4.05.0/build/ocaml/asmrun/startup.c:65: undefined reference to `caml_data_segments'
~/.opam/4.05.0/build/ocaml/asmrun/startup.c:62: undefined reference to `caml_data_segments'
~/.opam/4.05.0/build/ocaml/asmrun/startup.c:73: undefined reference to `caml_code_segments'
~/.opam/4.05.0/build/ocaml/asmrun/startup.c:71: undefined reference to `caml_code_segments'
~/.opam/4.05.0/build/ocaml/asmrun/startup.c:72: undefined reference to `caml_code_segments'
~/.opam/4.05.0/build/ocaml/asmrun/startup.c:76: undefined reference to `caml_code_segments'
~/.opam/4.05.0/build/ocaml/asmrun/startup.c:73: undefined reference to `caml_code_segments'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(roots.o): In function `caml_init_frame_descriptors':
~/.opam/4.05.0/build/ocaml/asmrun/roots.c:158: undefined reference to `caml_frametable'
~/.opam/4.05.0/build/ocaml/asmrun/roots.c:158: undefined reference to `caml_frametable'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(roots.o): In function `caml_oldify_local_roots':
~/.opam/4.05.0/build/ocaml/asmrun/roots.c:257: undefined reference to `caml_globals'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(roots.o): In function `caml_darken_all_roots_slice':
~/.opam/4.05.0/build/ocaml/asmrun/roots.c:371: undefined reference to `caml_globals'
~/.opam/4.05.0/build/ocaml/asmrun/roots.c:371: undefined reference to `caml_globals'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(roots.o): In function `caml_do_roots':
~/.opam/4.05.0/build/ocaml/asmrun/roots.c:407: undefined reference to `caml_globals'
~/.opam/4.05.0/build/ocaml/asmrun/roots.c:407: undefined reference to `caml_globals'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(fail.o): In function `caml_failwith':
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:121: undefined reference to `caml_exn_Failure'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(fail.o): In function `caml_failwith_value':
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:126: undefined reference to `caml_exn_Failure'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(fail.o): In function `caml_invalid_argument':
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:131: undefined reference to `caml_exn_Invalid_argument'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(fail.o): In function `caml_invalid_argument_value':
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:136: undefined reference to `caml_exn_Invalid_argument'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(fail.o): In function `caml_raise_constant':
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:81: undefineexternal sqrt : float -> float = "caml_sqrt_float" "sqrt"d reference to `caml_exn_Out_of_memory'
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:81: undefined reference to `caml_exn_Stack_overflow'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(fail.o): In function `caml_raise_sys_error':
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:151: undefined reference to `caml_exn_Sys_error'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(fail.o): In function `caml_raise_constant':
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:81: undefined reference to `caml_exn_End_of_file'
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:81: undefined reference to `caml_exn_Division_by_zero'
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:81: undefined reference to `caml_exn_Not_found'
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:81: undefined reference to `caml_exn_Sys_blocked_io'
~/.opam/4.05.0/lib/ocaml/libasmrun.a(fail.o): In function `caml_is_special_exception':
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:197: undefined reference to `caml_exn_Match_failure'
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:196: undefined reference to `caml_exn_Assert_failure'
~/.opam/4.05.0/build/ocaml/asmrun/fail.c:197: undefined reference to `caml_exn_Undefined_recursive_module'

Maybe I need to compile some dummy OCaml code with ocamlc so that it fetches the parts of the runtime that are missing?

libasmrun contains the runtime system for OCaml
code (compiled with ocamlopt) and, as you can see in the error message
from the linker, it depends on symbols provided by the OCaml program.
For instance, the garbage collector (in libasmrum) needs to find special
symbols, to locate some data structures (in libhello_world.a) created by
the compiler.

Related google searches:

https://fa.caml.narkive.com/ODgBQ3KX/caml-list-static-c-library-of-wrappers-compilation-issues

http://caml.inria.fr/pub/ml-archives/caml-list/2009/01/eabe0f1126a9d8c37e11c08054d99a36.en.html

Funny enough, when doing

ocamlopt -output-obj -o dummy.o dummy.ml

I get

dummy.o: file not recognized: File truncated
File "caml_startup", line 1:
Error: Error during linking

:angry:

Edit: Solved by this: c++ - File not recognized: File truncated GCC error - Stack Overflow

Yep, including a dummy.ml object file named test.o in final linking phase solves the problem! Code now runs. The dummy file contains only let i = 10 - maybe something even shorter could work too? Strange.

ocamlopt -output-obj -o test.o dummy.ml
cc src/benchmarks/binarytrees-escaped.c test.o -L`ocamlc -where` -lasmrun -lm -ldl

Edit: Tried with completely empty dummy.ml, worked too.