Tool like python poetry or elixirs mix that makes use of exhaustive lockfiles?

Is there a config/build tool similar to pythons poetry or elixirs mix or erlangs rebar3 that manages dependencies in a local “virtual environment” that sees only the dependencies specified? That also works with a lock file for full reproducability of the dev environment?

There’s esy although it’s not 1.0 yet.


opam also supports virtual environments with “local switches” and – as of Opam 2.1 – built-in support for lock file generation.

However, opam's lock files won’t get you truly reproducible builds since they don’t contain hashes of Opam packages (which can change by mutating either opam-repository or the package deployment after release). That may not matter for your use-case.

(edit: did some more digging into esy and it appears to hash the entire package on resolve. Neat!)

1 Like

I’ve been using Esy for a few months now and it’s been solid. I especially like its Nix-style compilation cache–it avoids dependency recompiles even across projects.

You can just use Nix whose config can be directly generated from the opam file with [ANN] opam2nix (v1).

1 Like

I’m already using nix :wink: had some trouble using opam2nix the other day… Will try again!

Okay tried opam2nix again, no dice… fails due to OCAMLTOP_INCLUDE_PATH: unbound variable when building dune, running nix-build directly in the examples/simple dir of opam2nix gives me OCAMLPATH: unbound variable when building cppo.

The linked repository of mine, just tries to mimick what the mentioned example does anyway, differences I am aware of, is that I want to use a more recent version of OCaml and I have resolved at a later point in time, both might lead to a different opam-selection.

Can someone help me figuring this out? Or should I go and open a ticket at opam2nix repo? Create a new thread here?

Thanks for the tip, though esy is currently not packaged for nixOS, and from the PRs comment that tries to introduce it, it seems to be a rather complicated thing to add.

Can you tell me more with examples about how to use that?

I’m really interested in OCaml, though never really got my feets wet in it, as I never really was able to even get simplest examples working. Even hello worlds were unable to build, because some “package” wasn’t found, which I then had to install globally on my system, which again broke other stuff because of version missmatches… This was true on Ubuntu, Funtoo and Arch Linux, today on nixOS, it seems that I can’t even properly install a toolchain which would then complain about missing libraries…

Felt worse than cabal

basically navigate to your project and type opam switch create .
This will create a local switch using the system version of ocaml.
If you’re having trouble with it, I suggest installing a fresh version of ocaml in your switch :

opam switch list-available #list  available compilers
opam switch create . 4.10.0 #install lastest version of the compiler 

Check that you’re in that switch by typing opam switch (gives you the current switch and a list of available swiches) or switch into it by typing opam switch .

Then install the libraries you want (like opam install batteries) for example

If all you want is automatic resolution of dependencies within a local ocaml compiler context, then that is what opam is designed for. If so, read below; if not, you probably want to supplement it with something else.

The key for the use case I mentioned is not to use your distribution’s package system to set up ocaml dependencies for you. Instead, use opam. Pretty much any version of opam will do for automatically resolving dependencies, including the one supplied by your distribution, although preferably it should be at version 2.0 or greater. Really, the only ocaml package you need to have installed from your distribution is opam (although your distribution may unnecessarily insist on also installing in the /usr prefix its own version of the ocaml compiler).

Having installed your distribution’s opam package, proceed as mentioned at . After initializing opam and before installing any other ocaml software using it, it would probably be helpful for you to set up a new local compiler “switch”. For example you can install a switch for the latest stable compiler release with:

opam switch create 4.10.0

After opam has compiled and installed the ocaml compiler for you in that switch, you can then install opam packages in the switch. You can also uninstall the ocaml system compiler provided in the /usr prefix by your distribution (if it will let you do that while retaining opam).

Edit: by the way, you run opam as user, not as root.

Esy is distributed from npm, so you would need to install NodeJS, then npm install --global esy. From there you would have the esy binary installed in your path (and you wouldn’t need Node any more).

That doesn’t work on nixOS, as it just installs a pre-installed binary which points to a non-existing interpreter on my system.

And after that?

I added dependencies to my opam file, how do I get them installed without having to opam switch remove and opam switch create . 4.10.0 afterwards? Even for my small project that takes close to 10 minutes…

You can pin the package: opam pin add packagename ..
Once that is installed by opam you can reinstall with opam update && opam reinstall packagename or build and run it directly from the project folder without the need to ask opam each time.

As I just want dependencies and build dependencies installed, but not the package I develop itself, what would be the workflow for that?

I’m basically searching for the equivalent of poetry install (which indeed installs the package, but as “editable” and in the sandbox for the project only) or mix do deps.get, deps.compile.

pin the package but don’t install it with: opam pin add packagename . -n. Then opam install packagename --deps-only.

There are local switches and support for lock files in opam if you prefer, but I rarely used them so I am not the best person to tell you what to do:

opam install aoc-ml --deps-only does nothing after I have added "core" to the deps…

Did you re-pin the package or run opam update before that?

Yes. Still:

$ opam install aoc-ml --deps-only

<><> Synchronising pinned packages ><><><><><><><><><><><><><><><><><><><><><><>
[NOTE] Ignoring uncommitted changes in /home/nmelzer/Projects/ocaml/aoc-ml (`--working-dir' not active).
[aoc-ml.~dev] no changes from git+file:///home/nmelzer/Projects/ocaml/aoc-ml#master