Как создать плагин GTK (cmxs) для моей программы OCaml

Я хотел бы создать плагин GTK для моего приложения OCaml, загруженный с помощью Dynlink. Как я могу заставить ocamlbuild включить библиотеку lablgtk2 в сгенерированный плагин?

В качестве теста у меня есть main.ml:

let () =
  try
    Dynlink.loadfile "_build/gtk_plugin.cmxs"
  with Dynlink.Error err ->
    failwith (Dynlink.error_message err)

gtk_plugin.ml:

let () =
  print_endline "GTK plugin loaded!";
  GMain.Main.main ()

_tags:

<main.*>: package(dynlink)
<gtk_plugin.*>: package(lablgtk2)

Но я получаю:

$ ocamlbuild -use-ocamlfind main.native gtk_plugin.cmxs
$ ./main.native 
Fatal error: exception Failure("error loading shared library:
.../_build/gtk_plugin.cmxs: undefined symbol: camlGtkMain")

Примечание: основной двоичный файл не должен зависеть от libgtk (который может быть не установлен в целевой системе) - если плагин не загружается, я хочу вернуться в режим консоли.

1 ответ

Решение

Вам нужно

  1. добавить linkall флаг для mainв противном случае будут удалены части среды выполнения OCaml, которые впоследствии понадобятся динамическим плагинам.

  2. скомпилировать gtk_plugin.cmxs файл с опцией -lflag lablgtk.cma (который я вывел, увидев в _log что этот вариант не был пройден)

Как ocamlbuild выводит .cmxs В настоящее время зависимости не оптимальны, и это трудно, потому что разные пользователи могут хотеть разные вещи (минимальные плагины, предполагающие наличие библиотек, или наоборот, переносимые статически связанные вещи). Для модулей из вашего проекта вы можете написать foo.mldylib файл должен быть явным о том, что вы хотите исключить, но я не знаю, возможно ли включить "все модули этой внешней библиотеки".

Обратите внимание, что также можно распространять lablgtk.cmxs и соответствующие .cmi вместе с вашим плагином, и сначала загрузите его динамически.

mkdir lablgtk
cp `ocamlfind query lablgtk2`/lablgtk.cmxs lablgtk
cp `ocamlfind query lablgtk2`/*.cmi lablgtk
echo "\"lablgtk\": not_hygienic" >> _tags

тогда в вашем main.ml

let () =
  try
    Dynlink.loadfile "lablgtk/lablgtk.cmxs";
    Dynlink.loadfile "_build/gtk_plugin.cmxs"
  ...
Другие вопросы по тегам