我如何在沙丘项目中将包含路径标志传递给ocamlc / ocamlopt

时间:2019-04-13 02:25:41

标签: ocaml nix nixos

我正在使用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文件中读取环境变量?

1 个答案:

答案 0 :(得分:0)

使用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
  ];
}
相关问题