【发布时间】:2019-04-13 02:25:40
【问题描述】:
我正在使用NixOS 并使用dune 编译cohttp server example。该示例值得注意的是它链接到两个 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 的非标准位置。我需要将相关路径添加到 dune 调用的 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})))
配置/沙丘
(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 文件中读取环境变量?
【问题讨论】:
-
你不pass flags in directly有什么原因吗?
-
标志不是静态的:
${openssl.dev}/lib扩展为/nix/store/$somehash-openssl-$version/lib其中$somehash可以比 openssl 版本更频繁地更改。我可以直接传递它们,但它很不雅,需要随着时间的推移不断编辑。 -
可能,让这更自动化的方法是让你的 shell 基于
buildDunePackage而不是runCommand。 Nixpkgs 手册的This section 介绍了该功能。