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

问题描述 投票:2回答:1

我正在使用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的非标准位置。我需要将相关路径添加到由dune调用的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参数的方法似乎很笨拙。

是否有一种标准方法可以在沙丘中实现这一目标(使用-I添加ocamlopt命令行的路径)?

如果没有,是否有更简单的方法从dune文件中读取环境变量?

ocaml nix nixos
1个回答
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
  ];
}
© www.soinside.com 2019 - 2024. All rights reserved.