61
votes

It is unclear to newcomers to the ecosystem what is the canonically preferred way to structure and manage building small to medium sized OCaml projects. I understand the basics of ocamlc, &c.--they mirror conventional UNIX C compilers enough to seem straightforward. But, above the level of one-off compilation of individual files, it is unclear how best to manage compilation simply and cleanly. The issue is not searching for potential tools, but seeing one or a few Right (enough) Ways--as validated by the experience of the community--for structuring and building standard OCaml projects.

My model use case is a modest but nontrivial project, of pure OCaml or OCaml plus a C dependency. Such a project:

  1. contains a number of source files
  2. links to a number of standard libraries
  3. links to one or more 3rd party libraries
  4. optionally includes a C library and OCaml wrapper as a subproject (though this could also be managed separately and included as a 3rd party library, as in (3))

Several alternative tools stand out:

  • Custom Makefiles seem to be the common standard in most open source OCaml packages, but appear frustratingly verbose and complex--even more so than for modest C/C++ projects. Worse, many even seemingly simple OCaml libraries layer autoconf/automake on top for even greater complexity.
  • ocamlbuild appears to offer a modern, streamlined mechanism for automating builds with minimal configuration, but it is not well documented for newcomers, nor represented by example in the introductory materials in the OCaml ecosystem, nor visibly used by any of the various published OCaml projects which I have browsed for inspiration.
  • OASIS seems to be a layer of convention and library code atop other build systems to support building a package manager and library, like Cabal.

(I have also seen OMake, which appears to be a self-styled "make++" which also includes a suite of standard rules for common languages, including OCaml, and ocaml-make née OCamlMakefile, providing a template of standard rules for GNU make.)

Are any of these a preferred, modern way of managing OCaml builds?

How are project files best structured?

How are 3rd party library dependencies included and managed? Is it preferred to install them at the system level, or is there a standard and straightforward way of managing them locally to a project? I would much prefer a model in which projects remain as self-contained as possible.

5

5 Answers

23
votes

You've got a thorough listing of the options available, but this question will not have a clear answer. My personal recommendation is also to use ocamlbuild. The myocamlbuild.ml file provided here is a good start. It will allow you to easily compile projects that depend on various libraries. I don't think it handles the case of binding to C libraries, but there are additional examples on the wiki that may help.

Some people object to ocamlbuild because it is yet another build tool, complicating package managers jobs. However, its ease of use and the fact that it is included in the official distribution is making it more and more widely used.

You can also skip all this and use oasis directly. It is very new, and a stable release has not yet been announced, but it is very usable. It will generate the myocamlbuild.ml automatically for you. This is probably the way to go in the very near future, if not already. Furthermore, by using oasis, you will immediately have the benefit of oasis-db, a CPAN like system for OCaml that is under development.

Regarding managing libraries, the answer is ocamlfind. If you have multiple instances of OCaml installed, calling the appropriate copy of ocamlfind will automatically cause all references to libraries be those for that particular instance, assuming you use ocamlfind systematically for all libraries. I currently use godi to install OCaml and libraries. It uses ocamlfind, and I have no problem having multiple instances of OCaml installed.

15
votes

Personally I'd give +1 for ocamlbuild. It's default rules are good enough to compile small to medium projects with one command and none to very minimal configuration. It also enforces some very reasonable conventions (not mixing sources with build results). And for larger projects it can be customized to one's desire, with extra rules & plugins. At the company where I work we are using it for a large project (Ocaml + some C + some preprocessing + ...) and it works like a charm (and gives us much less headaches than Makefiles would).

As for manuals, I'd think the user guide (available from the author's webpage,) should be enough to get you started. More funky stuff may require a bit more digging.

10
votes

+1 for OMake.

We revamped our build infrastructure a few years ago and chose OMake for the following reasons:

  • our products are composed of mixture of C, C++, Managed C++, Ruby and OCaml.
  • we target both Linux and Windows.
  • we interact with databases at build time.
  • for some productions we had to use OCaml 3.10.
  • our original build system used autoconf/automake.
  • we require out-of-source builds*.

To be honest I don't know if we could have done it with ocamlbuild, I haven't tested it. The tool is in use for sure since there is some activity around it in OCaml's bugtracker. If you opt for ocamlbuild, make sure you have an up-to-date version of OCaml.

*OMake supports out-of-source builds in a bit non-obvious way. It also has some issues when sources are read-only. We had to patch and rebuild our Windows version of OMake.

7
votes

The current recommendation is to use Dune, a composable build system that supports OCaml and Reason compilation. It's being actively developed.

The Quickstart page gives a variety of project templates to start with.

Dune can also handle the following:

Opam is the de-facto package manager for OCaml. Besides finding and installing packages, it can also handle multiple OCaml installations.

Esy is a newer, package.json-driven package manager born from the Reason community. Its pitch is that it brings out-of-the-box project sandboxing, and provides an easy way to pull existing opam packages.

3
votes

good question. I would tend to say :

1) ocamlbuild It is likely to be the standard way to compile, because it is efficient, fast, and the default tool given by the official distribution. The fact that it is in the official distribution is good point, because it is more likely to remain with time. Furthermore, it has ocamlfind enabled, so it can manage packages installed with ocamlfind, another standard for installing packages (ocamlfind is a bit like pkg-config for C)

2) But it won't be enough for your project. The integration with C is basic with ocamlbuild. So here I would maybe advise you to use oasis to finally answer your question. I also tried OMake, but did not like it.

3) However, your build scripts are not likely to work straight if you wan't other people to be able to download and build your project on their own machine. Furthermore, oasis does not handle pkg-config. For those reasons, I would tend to advise you to use ocaml-autoconf (ocaml macros for autotools). Because autotools are the standard for managing C libraries and it is well known by package maintainers. It can also handle cross-compilation...

=> ocaml-autoconf with ocamlbuild