【问题标题】:How can I pass include path flags to ocamlc/ocamlopt in my dune project如何在我的沙丘项目中将包含路径标志传递给 ocamlc/ocamlopt
【发布时间】: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 介绍了该功能。

标签: ocaml nix nixos


【解决方案1】:

使用stdenv.mkDerivation 或(如上面Robert Hensing 所建议的)ocamlPackages.buildDunePackage 而不是runCommand。后者导致在NIX_CFLAGS_COMPILENIX_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
  ];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 2016-07-13
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多