ocaml / dune

A composable build system for OCaml.
https://dune.build/
MIT License
1.63k stars 409 forks source link

Cannot compile OCaml into native library #2143

Closed ffreling closed 5 years ago

ffreling commented 5 years ago

I am trying to build an OCaml project as a C library so I can use it inside a C/C++ project. Most examples I see are linking a C library to OCaml but I want the other way around. Or they only compile a single file via an explicit call to ocamlopt.

I tried making a simple library with dune and building it via dune build ocaml/hello.a:

(library                                                                                                                                                    
    (name hello))                                                                                                                                           

But when I link it to a C program, I have a lot of undefined internal Caml symbols _caml_*. If I understand correctly, that means the OCaml runtime is missing.

I tried to compile sources by hand and then I was able to link by specifying the -output-complete-obj flag to ocamlopt:

ocamlopt $(OCAMLOPT_FLAGS) ocaml/hello.ml -o $(BUILD)/hello_obj.o
ocamlopt $(OCAMLOPT_FLAGS) ocaml/bye.ml -o $(BUILD)/bye_obj.o
ar -rs $(BUILD)/libfoo.a $(BUILD)/hello_obj.o $(BUILD)/bye_obj.o

I made a sample repository to exhibit my issue: https://gitlab.com/ffreling/ocaml-native-lib Running make clean ocaml-manual c run links properly (although I have one remaining issue with a callback) whereas running make clean ocaml c run leads to:

Undefined symbols for architecture x86_64:
  "_caml_apply2", referenced from:
      _caml_callback2_exn in libasmrun.a(amd64.o)
  "_caml_apply3", referenced from:
      _caml_callback3_exn in libasmrun.a(amd64.o)
...

It seems that the flag -output-complete-obj is not passed in dune. I looked at these links:

Environment

nojb commented 5 years ago

You should package your code as an executable and set (modes object) to generate an .o file that can be linked into a C application, e.g.

(executable
  (name hello)
  (modes object))

Then doing

$ dune build hello.exe.o

will produce an .o file that you can link into a C application.

ffreling commented 5 years ago

Thank you @nojb, it indeed fixed my issue :) I was a bit confused between executable and library, and I was too focused on getting a .a output for a library.

nojb commented 5 years ago

Great, thanks!