如何使用 ocamlbuild 编译 jocaml 文件并包含一个包?

How to compile a jocaml file with ocamlbuild and include a package?

如何使用 ocamlbuild 工具编译需要 cryptokit package(与配套 ocaml 成功编译)的 jocaml 源文件?

当我执行命令 ocamlbuild -pkg cryptokit -use-jocaml a.native 时出现此错误:

Warning: tag "package" does not expect a parameter, but is used with parameter "cryptokit"¬
+ jocamlopt -I /prefix/lib/ocaml -I /prefix/lib/ocaml/site-lib/cryptokit -I /prefix/lib/ocaml/site-lib/num /prefix/lib/ocaml/unix.cmxa /prefix/lib/ocaml/nums.cmxa /prefix/lib/ocaml/site-lib/cryptokit/cryptokit.cmxa a.cmx -o a.native¬
File "_none_", line 1:¬ 
Error: Files /prefix/lib/ocaml/unix.cmxa¬
       and /prefix/lib/ocaml/unix.cmxa¬
              both define a module named Unix¬
              Command exited with code 2.¬ 
              Compilation unsuccessful after building 4 targets (3 cached) in 00:00:00.

本质上是ocaml Unix模块跟自己冲突了。 仅当我包含 Cryptokit(使用 -pkg cryptokit)时才会出现此错误,这可能是因为 Cryptokit 需要 Unix。 a.ml 实际上可以为空,但仍会重现错误。

我尝试添加 -use-ocamlfind 标志,但由于它也使用 ocamlfind 获取编译器,因此它选择了 ocaml 编译器而不是 jocaml 编译器。

通过按顺序执行与 ocamlbuild 相同的命令(由 -verbose 1 显示),我得到了当我执行最后一个没有 /.../unix.cmxa 的命令时,不再有冲突,但是错误的 Unix 模块已加载:它来自 ocaml 而不是来自 jocaml,因此当我在 a.ml:

中使用任何 jocaml 功能时它会完全崩溃
jocamlopt -I /prefix/lib/ocaml -I /prefix/lib/ocaml/site-lib/cryptokit -I /prefix/lib/ocaml/site-lib/num /prefix/lib/ocaml/nums.cmxa /prefix/lib/ocaml/site-lib/cryptokit/cryptokit.cmxa a.cmx -o a.native

然而,当我也删除 -I /prefix/lib/ocaml 部分时,它编译成功:

jocamlopt -I /prefix/lib/ocaml/site-lib/cryptokit -I /prefix/lib/ocaml/site-lib/num /prefix/lib/ocaml/nums.cmxa /prefix/lib/ocaml/site-lib/cryptokit/cryptokit.cmxa a.cmx -o a.native

总而言之,我通过手动执行对最后一个命令的修改使其工作,但我想让 ocamlbuild 工作。

我认为这个错误与 Cryptokit 需要 Unix 模块这一事实有关:当我用 ocaml 而不是 jocaml 编译它时,在 linking 阶段它试图 link ocaml stdlib 一个(需要包含在内)而不是 jocaml stdlib 一个(作为 stdlib 的一部分隐式包含)。

我不知道 ocamlbuild+JOcaml 组合有活跃用户!出于好奇,你能多说说你使用 JOCaml+cryptokit 的目的吗?

我不太了解 Cryptokit 或 JOCaml,但看起来您的主要问题与 ocamlbuild 无关。如果我理解正确,(1) Cryptokit 需要 Unix 和 (2) JOCaml 需要使用它自己的 Unix 变体。如果这是正确的,针对 ocaml 的 Unix 编译 Cryptokit 并期望它在与本身需要 JOCaml 的 Unix 的 JOCaml 程序链接时工作,势必会产生很多麻烦。如果这适用于您的情况,那一定是因为您使用的 Cryptokit 部分实际上不需要 Unix,或者您正在测试的 JOCaml 程序实际上不需要 JOCaml 的 Unix。在长 运行 中,最好直接用 JOCaml 编译 Cryptokit(我不知道你对 OCaml 生态系统的总体感觉如何,但我个人会尝试构建一个 OPAM 开关,其中 ocaml{c,opt}jocaml{c,opt} 的别名,并从中构建程序。

关于 ocamlbuild 的特定部分,如果没有 tarball 来重现您的设置并进行试验,很难给出任何准确的建议。但我会尝试以下两个选项之一:

  • 您可以使用 -use-ocamlfind 并教导 ocamlfind 使用 jocaml 而不是 ocaml 通过使用 OCAMLFIND_COMMANDS 环境变量(参见 man ocamlfind)
  • 您可以完全避免 -use-ocamlfind,而是调用 ocamlfind 作为命令行工具来获取 cryptokit 库 (ocamlfind query cryptokit) 的位置。然后你会 使用 -pkg cryptokit 但你自己传递路径(使用 -lflags-cflags 或通过修改你的 myocamlbuild.ml 配置文件) .

按照 gasche 的建议详细说明 -use-ocamlfind 选项,我通过添加一个小的讨厌的 hack 来实现它:从 requires 字段中删除 "unix" META cryptokit 包的文件。它之所以有效,是因为 jocaml 默认情况下将所有内容与 threadsunix 链接(真正的解决方案是禁用此行为,但似乎更难)。所以工作编译命令是:

ocamlbuild -use-ocamlfind -use-jocaml -pkg cryptokit a.ml

我认为在使用 jocaml 编译时可以将其推广到任何使用 unixthreads 的包。一个附属问题是是否可以使用 _tagsmyocamlbuild.ml 文件动态地执行此操作(注意:如果需要移动此注释,请注释)。