Hi,
I’m trying to migrate an OCamlbuild project to Dune, but I’m having trouble building a plugin (for Dynlink).
The idea is that the plugin adds a GTK UI, using lablgtk. This must not be linked into the main program, because it uses a C library that might not be present on the target system.
I’ve put up a minimal repository showing the problem here:
https://github.com/talex5/dune-test
git clone https://github.com/talex5/dune-test.git
cd dune-test
By default, it fails with:
$ make
dune build @all
dune exec ./myprog.exe
Failed to load GTK GUI plugin: error loading shared library:
/home/user/tmp/dune_plugin/_build/default/plugin/plugin.cmxs:
undefined symbol: camlGtkMain__init_inner_102598
That seems to indicate that the lablgtk archive isn’t being linked with the plugin.
The library rule I’m using is:
(library
(name plugin)
(optional)
(libraries lablgtk2 lwt_glib))
With ocamlfind, I would use -linkpkg
to fix the error.
I’ve added a rule to build real_plugin.cmxs
with an external call to ocamlfind
:
(rule
(targets real_plugin.cmxs)
(deps plugin.cmxa)
(action (run ocamlfind ocamlopt
-shared
-linkall
-linkpkg
-dontlink lwt.unix
-thread
-package lablgtk2,lwt_glib
%{deps}
-o %{targets}
)))
That works (change myprog.ml
to load real_plugin.cmxs
instead of plugin.cmxs
):
$ make
dune build @all
dune exec ./myprog.exe
Plugin init..."LC_CTYPE=en_GB.UTF-8;LC_NUMERIC=C;LC_TIME=en_GB.UTF-8;LC_COLLATE=en_GB.UTF-8;LC_MONETARY=en_GB.UTF-8;LC_MESSAGES=en_GB.UTF-8;LC_PAPER=en_GB.UTF-8;LC_NAME=en_GB.UTF-8;LC_ADDRESS=en_GB.UTF-8;LC_TELEPHONE=en_GB.UTF-8;LC_MEASUREMENT=en_GB.UTF-8;LC_IDENTIFICATION=en_GB.UTF-8"
Plugin loaded OK
However, it’s a bit ugly. Also, adding real_plugin.cmxs
to an install stanza forces Dune to try to build the plugin even if lablgtk isn’t available, ignoring the (optional)
in the library definition.
I also tried using ocamlfind
to get the archives:
(library
(name plugin)
(optional)
(ocamlopt_flags :standard (:include gtk_archives.sexp))
(libraries lablgtk2 lwt_glib))
(rule
(targets gtk_archives.sexp)
(action
(with-stdout-to %{targets}
(run ocamlfind query -r lablgtk2,lwt_glib -format "\"%+a\"" -predicates native -prefix "(" -suffix ")"
))
))
However, that fails with:
$ make
dune build @all
ocamlopt plugin/plugin.{a,cmxa} (exit 2)
(cd _build/default && /home/user/.opam/4.07.0/bin/ocamlopt.opt -w @a-4-29-40-41-42-44-45-48-58-59-60-40 -strict-sequence -strict-formats -short-paths -keep-locs -g /home/user/.opam/4.07.0/lib/lablgtk2/lablgtk.cmxa /home/user/.opam/4.07.0/lib/result/result.cmxa /home/user/.opam/4.07.0/lib/lwt/lwt.cmxa /home/user/.opam/4.07.0/lib/ocaml/unix.cmxa /home/user/.opam/4.07.0/lib/ocaml/bigarray.cmxa /home/user/.opam/4.07.0/lib/lwt/unix/lwt_unix.cmxa /home/user/.opam/4.07.0/lib/lwt_glib/lwt_glib.cmxa -a -o plugin/plugin.cmxa plugin/.plugin.objs/plugin.cmx)
Option -a cannot be used with .cmxa input files.
What’s the correct way to build a plugin with Dune?