Writing ctypes bindings to system shared libraries for bytecode targets via the dune ctypes stanza

Working on GitHub - lukstafi/ocaml-gccjit: OCaml bindings for libgccjit, I’m facing a problem with the same symptom as in this issue: Add link flags ocamlmklib when using ctypes stubs.

lukstafi@DESKTOP-6RRUNR4:~/ocaml-gccjit$ dune exec examples/tut01_hello_world.bc
Fatal error: cannot load shared library dllgccjit_stubs
Reason: /home/lukstafi/ocaml-gccjit/_build/install/default/lib/stublibs/dllgccjit_stubs.so: undefined symbol: gcc_jit_context_new_opaque_struct
Aborted

The stubs library is found, but the underlying libgccjit.so library is not loaded. I tried various things like: adding -linkall; setting the env variables DYLD_LIBRARY_PATH, LD_LIBRARY_PATH, CAML_LD_LIBRARY_PATH; using byte_complete (doesn’t produce a .bc target); adding (ocamlc_flags (-custom)) (breaks the build).

Any ideas I could follow?

I’m not familiar with Ctypes, so don’t have much to offer. But it is often useful to look at the link flags recorded in libgccjit.cma/libgccjit.cmxa, which you can do with eg ocamlobjinfo libgccjit.cma. I think you would like to see at least -lgccjit and -lgccjit_stubs (in that order). If -lgccjit is missing then it means that some link-time flag is not being passed correctly somewhere.

Cheers,
Nicolas

1 Like

Yes, -lgccjit is neither in Extra dynamically-loaded libraries:, nor in the result of ldd build/_default/lib/dllgccjit_stubs.so. All flags are crammed into Extra C object files:.

Is it possible the lib is loaded but the symbol is stripped? I encountered this recently. The fix was -Wl,-export-dynamic (or -export_dynamic for mac).

-Wl,-export-dynamic did not help.

I managed to get ocamlobjinfo ==> Extra C options: -lgccjit -Wl,-export-dynamic, but it did not help.

Is there any way to pass additional parameters for ocamlmklib? Dune -verbose:

Running[26]: (cd _build/default && /home/lukstafi/.opam/5.1.1/bin/ocamlmklib -g -o lib/gccjit_stubs lib/libgccjit__c_cout_generated_functions__Gccjit_bindings__Functions.o)

I think you need to get -lgccjit inside the “Extra dynamically-loaded libraries” field of your archive. This is typically achieved by passing -lgccjit to the ocamlmklib invocation.

Cheers,
Nicolas

1 Like

Yes but does it mean I need to abandon the ctypes stanza? Since I wasn’t able to achieve passing arguments to ocamlmklib. Edit: despite this line, meaning it should be possible, maybe outside of the ctypes stanza: dune/src/dune_rules/lib_rules.ml at e515c294686999610e14079608a7d912c77bfe1b · ocaml/dune · GitHub

I don’t know enough about the ctypes stanza to answer this question, sorry.

Did you try adding (c_library_flags -lgccjit) directly to the (library) stanza?

Cheers,
Nicolas

Yes IIRC. (Double-checked now it doesn’t help.) I definitely also tried (flags -cclib -lgccjit). And also global env c_flags and flags.

This might help, had similar issue with ctypes and dune when using bytecode.

1 Like

Thanks, I haven’t seen this in my searches! In the meantime, I had another idea to try: generate/vendor libgccjit.pc and use (build_flags_resolver pkg_config). If it doesn’t work, I’ll study this PR. Edit: ah, sorry I did see this. I linked this PR in my original post!

I now converted to (build_flags_resolver pkg_config), but the situation is the same: ocamlmklib still does not get any arguments (in particular it does not ask to link the external_library_name), and the execution still fails with the original error message.

Edit (updated): I now patched Add link flags ocamlmklib when using ctypes stubs. by frejsoya, and it solves the problem (both the (build_flags_resolver pkg_config) variant and the (build_flags_resolver (vendored ...)) variant). It still has the bytecode + c stubs not working as expected · Issue #108 problem when dune clean; dune exec – but it is easily solved by dune build; dune exec; alternatively need to update CAML_LD_LIBRARY_PATH i.e. dune clean; CAML_LD_LIBRARY_PATH=... dune exec works, but using (env (_ (env-vars (CAML_LD_LIBRARY_PATH ...)))) does not work.