Jbuilder templates

Hey all,

I made two series of templates to help myself and others get started with jbuilder:


The first one is for a simple OCaml library, meant to be distributed via opam.

The second series of templates is for an application made up of several folders and several executables. I’m not quite sure if I did the right thing there. Please let me know what can be improved. In particular, the requirement for having one opam file per library seems unnecessary since I have no intention of distributing these libraries. Maybe I’m doing it wrong and there’s a simpler way of having multiple folders with OCaml sources, which is really just what I want.


There’s no such requirement. You can simply omit the public_name for your library and jbuilder will no longer require an .opam file. However, the library will no longer build whenever you request the @install alias ($ jbuilder build or $ jbuilder build @install). You may still depend on this library in your libraries as usual.

Maybe I’m doing it wrong and there’s a simpler way of having multiple folders with OCaml sources, which is really just what I want

This is now possible in beta14. Have a look at the copy_files stanza.


(copy_files# subfolder1/*)
(copy_files# sbufolder2/*.ml)

I just realized that the copy_files# is not that well documented. We should probably add an example of this feature in the manual. Perhaps even start a FAQ.

1 Like

Here is a related idea: configure your editor to load templates for jbuild or opam files. I’m using Vim and have this in my .vimrc:

autocmd BufNewFile jbuild     silent! 0r $HOME/.vim/templates/jbuild
autocmd BufNewFile Makefile   silent! 0r $HOME/.vim/templates/Makefile
autocmd BufNewFile opam*      silent! 0r $HOME/.vim/templates/opam

The templates files could be from this repository. My jbuild file contains various stanzas and I simply delete the ones I don’t need.


Indeed, a proper IDE should take care of managing the structure of the project.

Thanks. I’m trying these changes right now. The goal is to build:

  • One big library that contains everything except the “main” for the executable
  • One executable that links against the library

My past experience with OCaml projects includes building multiple executables. The linking phase was slow, so we ended up building just one executable with sub-commands for performing various tasks. Having just one (mostly) statically-linked executable makes installations a little easier to manage, too.

My previous projects were building one library per directory. I don’t know what will happen if we build just one big library. A perceived advantage was that we could load a library in utop and test it event if the rest of the project wasn’t building yet.

I’m done with the changes. It looks good to me so I’ll start using it for my own private application.

The emacs/merlin setup is another pain point for me. I’m not sure of the best place to address this since not everyone uses emacs. Maybe we could just create emacs, vim, etc. folders in this repo. Let me know of your ideas.

Maybe it is possible to get integration in tuareg for emacs. There is already a feature like this but for opam:

Actually, I discovered while writing this response that there is already a template for jbuilder there:

The one big executable idea is sound but it doesn’t seem like it’s always a win to relink one huge binary on every change rather than possibly many small ones. I’d want to experiment here before committing to this.

One advantage of the one big library approach in jbuilder is that ocamldep will hopefully give you a more fine grained dependency graph. As jbuilder runs ocamldep only inside a library definition.

@mjambon you might also want to familiarize yourself with the $ jbuilder utop <dir> command. Which will load all the libraries defined in <dir> into a fresh utop instance. I saw that you’ve added some instructions to make it easier to use utop in development. Wondering if this command will simplify some things for you.

1 Like

Nice. One issue: testing your templates with a project using Menhir yields an error because Menhir cannot (AFAIK) parse lines beginning with # as inserted by copy-files#. I only had to add the following line to get Menhir to be happy: (copy_files lib/*.mly).

1 Like