I have an OCaml library that has a C binding. The C binding has a dependency on a native component that I would like to also build with dune. At the moment, the dune file looks like:
(rule
(deps
(source_tree vendor))
(targets libexample.a)
(action
(no-infer
(progn
(chdir
vendor
(progn (* RUN A BUILD STEP HERE *))
(copy vendor/libexample.a libexample.a)))))
(library
(name exampleWithNativeDep)
(package examplePackage)
(flags -linkall)
(libraries base)
(wrapped false)
(foreign_stubs
(language c)
(names binding)
;; Note that there's a separate C binding file that relies on Dune to be built.
;; This needs the libexample.a produced above but libexample is not directly targeted by OCaml.
(flags :standard -Ivendor/Include -I.))
(c_library_flags -lutil -lpthread)
(foreign_archives example)
This works fine when running OCaml native builds but fails when I want to run a bytecode build. The issue is that the bytecode build wants dllexample.so to also exist.
Given that:
- I only need the artefacts of the rule to statically link them in my OCaml consumed C binding;
- I still want to rely on Dune to build the C binding;
- I need the binding to be statically linked to
libexample.aboth when the binding is built as a static library for consumption from native builds and dynamic library for consumption from bytecode builds.
is there a way to express this kind of behaviour with in dune?
If you really want to rely on dune to build your C library, then just let dune do it work. There is the foreign_library stanza exactly for this.
Put the following
dunefile into your vendor folder,and add
(foreign_archives vendor/example)to yourexampleWithNativeDeplibrary definition.Also, you don't need to pass
-linkallas OCaml will linklibexample.aby default (i.e., it will use static linking). And-linkallis actually have a different meaning, it doesn't really control static linking.P.S., and don't forget to remove your
rulestanza.