Я использую NixOS и компилирую пример cohttp-сервера , используя dune . Этот пример примечателен тем, что он ссылается на две C-библиотеки: openssl и libev.
начальная попытка
Вот мой shell.nix:
with import <nixpkgs> { };
let spec = {
buildInputs = with ocamlPackages; [
ocaml
findlib
dune
# ocaml libs (and external library deps)
cohttp-lwt-unix openssl libev
]);
};
in runCommand "dummy" spec ""
Вот мой файл с дюнами:
(executable
(name server_example)
(libraries cohttp-lwt-unix))
А на выходе dune build server_example.exe
...
/nix/store/3xwc1ip20b0p68sxqbjjll0va4pv5hbv-binutils-2.30/bin/ld: cannot find -lssl
/nix/store/3xwc1ip20b0p68sxqbjjll0va4pv5hbv-binutils-2.30/bin/ld: cannot find -lcrypto
/nix/store/3xwc1ip20b0p68sxqbjjll0va4pv5hbv-binutils-2.30/bin/ld: cannot find -lev
Ладно, не удивительно, потому что они в нестандартных местах в NixOS. Мне нужно добавить соответствующие пути в командную строку ocamlopt, вызываемую дюной, например: -I ${openssl.out}/lib -I ${libev}/lib
.
Теперь openssl включает в себя файлы pkg-config, но добавление pkg-config в мой shell.nix
не имеет видимого эффекта.
вторая попытка с использованием конфигуратора
Я использовал configurator , чтобы создать программу для добавления флагов из переменной среды в флаги сборки моего исполняемого файла dune.
shell.nix
with import <nixpkgs> { };
let spec = {
buildInputs = with ocamlPackages; [
ocaml
findlib
dune
configurator
# ocaml libs (and external library deps)
cohttp-lwt-unix openssl libev
]);
shellHook = ''
export OCAML_FLAGS="-I ${openssl.out}/lib -I ${libev}/lib"
'';
};
in runCommand "dummy" spec ""
Дюна
(executable
(name server_example)
(flags (:standard (:include flags.sexp)))
(libraries cohttp-lwt-unix))
(rule
(targets flags.sexp)
(deps (:discover config/discover.exe))
(action (run %{discover})))
конфиг / Дюна
(executable
(name discover)
(libraries dune.configurator))
конфиг / discover.ml
open Sys
module C = Configurator.V1
let () =
C.main ~name:"getflags" (fun _c ->
let libs =
match getenv_opt "OCAML_FLAGS" with
| None -> []
| Some flags -> C.Flags.extract_blank_separated_words flags
in
C.Flags.write_sexp "flags.sexp" libs)
Компиляция теперь успешна, но такой подход написания пользовательской программы, которая берет переменную окружения и помещает ее в аргумент flags, кажется неуклюжим.
Есть ли стандартный способ сделать это в дюне (добавить пути к командной строке ocamlopt с помощью -I
)?
Если нет, есть ли более простой способ прочитать переменную окружения из dune
файлов?