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!)
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).
I’m already using nix had some trouble using opam2nix the other day… Will try again!
Okay tried opam2nix
again, no dice…
https://gitlab.com/NobbZ/ocaml2nix-hello-example 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 opam - Usage . 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: https://khady.info/opam-sandbox.html
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