Optional dependencies with ocamlbuild

ⅰ亾dé卋堺 提交于 2019-12-11 06:38:37

问题


I have an OCaml project that is currently built using OCamlMake. I am not happy with the current build system since it leaves all build artefacts in the same directory as source files, plus it also requires to manually specify order of dependencies between modules. I would like to switch to a build system that does not suffer from these issues. I decided to give Oasis a try but have run into issues.

The problems arise from the fact that the project is built in a very specific way. It supports several different database backends (PostgreSQL, MySQL, SQLite). Currently, to compile a database backend user must install extra libraries required by that backend and enable it by setting an environment variable. This is how it looks in the Makefile:

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

Notice that this also adds extra module to the list of compiled modules. The important bit is that there is no dependency (in a sense of module import) between any module reachable from the applications entry point and database backend module. What happens rather is that each database backend module contains top-level code that runs when a module is initiated and registers itself, using side-effects, with the main application.

I cannot get this setup to work with Oasis. I declared each of the database backend modules as a separate library that can be enabled for compilation with a flag:

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

However, I cannot figure out a way to tell Oasis to link the optional modules into the executable. I tried to figure out a way of doing this by modifying myocamlbuild.ml file but failed. Can I achieve this with the rule function described here?

If what I describe cannot be achieved with ocamlbuild, is there any ither tool that would do the job and avoid problems of OCamlMake?


回答1:


Well, I guess that answers it: https://github.com/links-lang/links/pull/77 :)




回答2:


I saw the question and started working on it before I noticed Drup's answer above. Below is a self-contained ocamlbuild solution that is essentially the same as Drup's.

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

Using the tag link_with_plugin on an ocamlbuild target will make it depend on any module whose path (without extension) is listed in the file plugin.config. For example if you have plugins pluga.ml, plugb.ml and a file main.ml, then writing pluga plugb in plugin.config and having <main.{cmo,cmx}>: link_with_plugin will link both plugin modules in the main executable.




回答3:


Unfortunately, this is beyond oasis capabilities. This limitation has nothing to do with ocamlbuild, it just because oasis author tried to keep it simple, and didn't provide optional dependencies as a feature.

As always, an extra level of indirection may solve your problem. What you need, is a configuration script (configure) that will generate _oasis file for you, depending on parameters, provided by a user.

For example, in our project we have a similar setup, i.e., multiple different backends, that might be chosen by a user during the configuration phase, with --{enable,disable}-<feature>. We achieved this by writing our own ./configure script that generate _oasis file, depending on configuration. The configuration script just concatenates the resulting _oasis files from pieces, described in oasis folder.

An alternative solution would be to use m4 or just cpp, and have an _oasis.in file, that is preprocessed.



来源:https://stackoverflow.com/questions/39796986/optional-dependencies-with-ocamlbuild

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!