我正在使用NixOS,并使用cohttp server example编译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创建了一个程序,以将环境变量中的标志添加到沙丘可执行文件的构建标志中。
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})))
config / dune
(executable
(name discover)
(libraries dune.configurator))
config / 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参数的方法似乎很麻烦。
在沙丘中是否有完成此操作的标准方法(使用-I
向ocamlopt命令行添加路径)?
如果没有,是否有更简单的方法从dune
文件中读取环境变量?
答案 0 :(得分:0)
使用stdenv.mkDerivation
或(如上文Robert Hensing所建议)使用ocamlPackages.buildDunePackage
而不是runCommand
。后者导致环境在NIX_CFLAGS_COMPILE
或NIX_LDFLAGS
环境变量中不包含openssl和libev。使用mkDerivation
会导致填充这些变量。
这些变量到位后,将通过dune
进行编译,并且可执行文件将链接到libssl和libev。
此外,没有必要明确包含libev和openssl,因为它们被声明为通过cohttp-lwt-unix传播的构建输入。
shell.nix:
with import <nixpkgs> { };
with ocamlPackages;
buildDunePackage {
pname = "dummy";
version = "0";
buildInputs = [
cohttp-lwt-unix
];
}