与ocamlbuild的可选依赖项

时间:2016-09-30 17:31:36

标签: ocaml ocamlbuild oasis

我有一个OCaml项目,目前使用OCamlMake构建。我对当前的构建系统不满意,因为它将所有构建工件保留在与源文件相同的目录中,此外还需要手动指定模块之间的依赖关系顺序。我想切换到不受这些问题影响的构建系统。我决定试试Oasis,但遇到了问题。

问题源于项目以非常具体的方式构建。它支持几种不同的数据库后端(PostgreSQL,MySQL,SQLite)。目前,要编译数据库后端,用户必须安装该后端所需的额外库,并通过设置环境变量来启用它。这是它在Makefile中的外观:

ifdef MYSQL_LIBDIR
   DB_CODE    += mysql_database.ml
   DB_AUXLIBS += $(MYSQL_LIBDIR)
   DB_LIBS    += mysql
endif

请注意,这也会将额外的模块添加到已编译模块的列表中。重要的一点是,从应用程序入口点和数据库后端模块可以访问的任何模块之间没有依赖关系(在模块导入的意义上)。更确切地说,每个数据库后端模块都包含在启动模块时运行的顶级代码,并使用副作用将其自身注册到主应用程序。

我无法使用此设置与Oasis一起使用。我将每个数据库后端模块声明为一个单独的库,可以使用标志启用编译:

Library mysql-backend
  Path          : .
  Build        $: flag(mysql)
  Install       : false
  BuildTools    : ocamlbuild
  BuildDepends  : main, mysql
  Modules       : Mysql_backend

但是,我无法想办法告诉Oasis将可选模块链接到可执行文件中。我试图通过修改myocamlbuild.ml文件找出一种方法,但是失败了。我可以使用here所述的rule函数来实现这一目标吗?

如果使用ocamlbuild无法实现我所描述的内容,是否有任何ither工具可以完成工作并避免OCamlMake出现问题?

3 个答案:

答案 0 :(得分:1)

嗯,我想这回答了它:https://github.com/links-lang/links/pull/77:)

答案 1 :(得分:1)

在我注意到Drup上面的回答之前,我看到了这个问题并开始研究它。下面是一个独立的ocamlbuild解决方案,与Drup的解决方案基本相同。

open Ocamlbuild_plugin

let enable_plugin () =
  let plugins = try string_list_of_file "plugin.config" with _ -> [] in
  dep ["ocaml"; "link_with_plugin"; "byte"]
    (List.map (fun p -> p^".cmo") plugins);
  dep ["ocaml"; "link_with_plugin"; "native"]
    (List.map (fun p -> p^".cmx") plugins);
  ()

let () = dispatch begin
    function
    | Before_rules -> enable_plugin ()
    | _ -> ()
end

在ocamlbuild目标上使用标记link_with_plugin将使其依赖于文件plugin.config中列出其路径(不带扩展名)的任何模块。例如,如果您有插件pluga.mlplugb.ml和文件main.ml,那么在pluga plugb中编写plugin.config<main.{cmo,cmx}>: link_with_plugin将{}}链接主要可执行文件中的模块。

答案 2 :(得分:0)

不幸的是,这超出了绿洲的能力。此限制与ocamlbuild无关,只是因为oasis作者试图保持简单,并且没有提供可选的依赖项作为功能。

与往常一样,额外的间接级别可以解决您的问题。您需要的是一个配置脚本(configure),它将为您生成_oasis文件,具体取决于用户提供的参数。

例如,在our project中,我们有一个类似的设置,即多个不同的后端,用户可以在配置阶段选择--{enable,disable}-<feature>。我们通过编写自己生成./configure文件的_oasis脚本来实现这一点,具体取决于配置。配置脚本只是将_oasis文件从oasis文件夹中描述的部分连接起来。

另一种解决方案是使用m4cpp,并使用_oasis.in文件进行预处理。