选择要编译的文件以使用 Oasis 获取模块

Choose which file to compile to get a module with Oasis

我决定将编译环境从 Makefile 和配置文件切换到 Oasis。

在我的 configure 文件中我有这个命令:

EXTERNALLIB=""
if test "$USEOCAMLFIND" = yes; then
  EXTERNALLIB=$(ocamlfind query -i-format External)
fi

在我的 Makefile 中:

externalwrapper.ml: externalwrapper_actual.ml externalwrapper_fake.ml config.status
    @rm -f externalwrapper.ml
    @if [ -z "$(EXTERNALLIB)" ]; then \
    cat externalwrapper_fake.ml >> externalwrapper.ml;\
    else \
    cat externalwrapper_actual.ml >> externalwrapper.ml;\
    fi;\
    chmod -w externalwrapper.ml

如果我的计算机中存在该库,它允许我编译一个实际的 Externalwrapper 模块,如果不存在,则编译一个假的。

现在,我尝试在 Oasis 中这样做,但我不知道是否可行,如果可行,我应该怎么做?

在撰写本文时,OASIS 0.4.8 既不支持可选也不支持条件 linking。尽管您可以选择性地构建目标,但目标的配方应该是静态的。有传闻,OASIS 作者计划在 0.4.9 中添加此功能,但目前,他被 ocamlbuild.an issue 阻止。

但是,解决方法很少。

预处理

您可以只添加一个额外的间接层,并从一些 _oasis.in 文件构建您的 _oasis 文件。您甚至可以为此使用 autoconf,例如

AC_INIT([Name], [0.1-beta], [your@email])
AC_CONFIG_FILES([_oasis])  

EXTERNALLIB=$(ocamlfind query -i-format External)
WRAPPER_MODULE=externalwrapper_fake.ml
if test -z "$(EXTERNALLIB)"; then
    WRAPPER_MODULE=externalwrapper_actual.ml
fi

AC_OUTPUT
AC_SUBST(WRAPPER_MODULE)

并且在 _oasis.in 中,您可以使用 @WRAPPER_MODULE@ 变量,该变量将被实现为 externalwrapper_actual.mlexternalwrapper_fake.ml

您实际上可以构建自己的配置脚本来构造 _oasis 文件,而不是使用 autoconf 替换。例如,在 BAP 中,我们正在构建一个最终的 _oasis 文件,方法是将它从我们的自定义 configure 脚本中的片段粘合起来。

使用对象部分并扩展 OCamlBuild

Drup 提出了替代解决方案(参见 following PR 作为示例)。这个想法是将每个变体描述为一个有条件的构建对象,然后用一个特殊的构建规则扩展 OCamlbuild,根据一个标志,找到这个对象并直接 link 它。

两种解决方案各有优缺点,因此我们都期待将此功能添加到 OASIS 中。

一种可能性是使用带有您的库名称的标志,并在库存在时要求 opam 启用它们(oasis2opam does that for you). See for example the definition of a lwt flag and its use to conditionally build a library. You can also have setup.ml enable the flag if the library is present. Finally, you can add cppo rules in myocamlbuild 以启用条件代码编译。