Currently guix provides OCaml libraries for OCaml 4.14.1 only. We are working on 5.3 right now. You might want to try building something like:
guix build -e '((@@ (guix build-system ocaml) package-with-ocaml5.3) (@@ (gnu packages ocaml) ocaml-zarith))' (No guarantee) Otherwise, use 4.14.1 for now: guix shell [email protected] ocaml-zarith Le 3 décembre 2025 15:44:15 GMT+01:00, Zelphir Kaltstahl <[email protected]> a écrit : >Hello Guix Users! > >In the past I thought I had it figured out, thanks to help from someone on the >mailing list, how to run Ocaml projects in a reproducible (hashes/checksums >verified!) way. > >It is December and I thought I would give Ocaml a try at Advent of Code this >year. However, I learned, that my previous project structure/setup no longer >works. I thought: "Why not check out how people, who don't use or know guix do >this?" and looked into opam. Long story short: Unfortunately, it does not >provide a lock file that one could commit into a repo to ensure >reproducibility. Even the tool opam-lock merely pins version numbers without >hashes. Disappointing. So I am back to trying to fix my guix using project >setup. Last stop before giving up on Ocaml for another year or so. In the >following I will describe my project setup, and why it hopefully is >reproducible not only on my machine, but also on other machines. > >*The guix part* > >I have the following files: > >(1) guix-env/channels.scm: Specifying the exact guix channel that is used, and >thereby locking down hashes, which are specified in the guix repository itself. > >~~~~ >(list (channel > (name 'guix) > (url"https://git.guix.gnu.org/guix.git") > (branch "master") > (commit > "7c6d8a6224cf3209efa179dbe1509759a580cb05") > (introduction > (make-channel-introduction > "9edb3f66fd807b096b48283debdcddccfea34bad" > (openpgp-fingerprint > "BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA"))))) >~~~~ > >(2) guix-env/manifest.scm: Specifying the package, that I want to use for my >project. > >~~~~ >(specifications->manifest > '("[email protected]" > "ocaml-utop" > "dune" > "bash" > "make" > "ocaml-findlib" > "ocaml-zarith")) >~~~~ > >(3) Makefile: Used as a task runner, basically, to avoid having to type >complicated commands. > >~~~~ Makefile (variable definitions) ~~~~ >.POSIX: >.RECIPEPREFIX = > >.DELETE_ON_ERROR: > >MAKEFLAGS += --warn-undefined-variables >MAKEFLAGS += --no-builtin-rules > >SHELL ::= guix time-machine --channels=guix-env/channels.scm -- shell --check >--manifest=guix-env/manifest.scm -- bash -c >.SHELLFLAGS ::= -Euxo pipefail -c > >BUILD_DIR ::= _build > >OCAML_PACKAGES ::= zarith > >... >~~~~ > >Here one can see, that I am setting the `SHELL` environment variable to using >`bash -c`, which will evaluate the actual commands that are defined later in >Makefile targets. `bash` runs in the `guix shell`, that is created in a `guix >time-machine` call, which refers to the `guix-env/channels.scm` file, to make >sure, that I am using exactly the versions defined in that commit of the guix >repository, implying that I am using exactly the hashes defined on that commit >of the guix repository. That should make things reproducible and make it so >that when I run things on another machine, the same software, the exact same >packages are used. > >I also define a list of Ocaml packages I am using, currently only one: >`zarith` which is important for big integers. > >Then come the actual targets: > >~~~~ Makefile (targets) ~~~~ >... > >.PHONY: repl >repl: >> utop > > >.PHONY: shell >shell: >> bash > >... >~~~~ > >The target `shell` is merely for debugging purposes, or for when I need to run >a command in a shell that has the dependencies installed. > >When I run `make shell` and in that resulting shell run `ocaml --version`, I >get the output: `The OCaml toplevel, version 5.3.0`. Great so far! > >*(Issue 1)* > >One problem is with `utop`. Somehow it does not use the correct Ocaml version >and I don't know where it gets another Ocaml version even from. When I run >`make repl` I get a `utop` REPL that says: > >~~~~ utop on command line ~~~~ >───────────┬───────────────────────────────────────────────────────────────────┬ > │ Welcome to utop version %%VERSION%% (using OCaml version 4.14.1)! > │ > > └───────────────────────────────────────────────────────────────────┘ > >Type #utop_help for help about using utop. >~~~~ > >What? Why is it using Ocaml version 4.14.1?? Where does it get that from? No >idea. It shouldn't be using anything but the installed packages. Maybe it >internally depends on an older Ocaml version implicitly, and guix installs >that, so that utop can run at all, satisfying utop's dependencies? But on >https://hpc.guix.info/package/ocaml-utop I click the link to >https://codeberg.org/guix/guix/src/commit/23dbcfaef682c41e9cb2a6aea9ad69feea65f26a/gnu/packages/ocaml.scm#L5660, > where I see the inputs: > >~~~~ ocaml.scm ~~~~ > (native-inputs > (list ocaml-cppo)) > (propagated-inputs > (list ocaml-lambda-term > ocaml-logs > ocaml-lwt > ocaml-lwt-react > ocaml-react > ocaml-zed)) >~~~~ > >There I at least don't see any direct dependency on an older Ocaml version. >Might be one of those packages listed there is only available for older Ocaml >version. I don't know. > >But this issue is not the main issue. The main issue is with other targets. >The Makefile also has targets to run an Ocaml file: > >~~~~ Makefile (targets for running ocaml things) ~~~~ >%.byte: %.ml >> ocamlfind ocamlc $(foreach OCAML_PACKAGE,$(OCAML_PACKAGES),-package >> $(OCAML_PACKAGE)) -linkpkg -o $*.byte $< > > ># Simply running depends on building the byte files, which ># are to be considered intermediate files. >.PRECIOUS: %.byte >%: %.byte >> ./[email protected] >~~~~ > >Here I define a target `%`. This target will be used when I write things like >`make main`. It depends on `%.byte`, which means that `main` depends on >`main.byte`. The other target `%.byte` describes how to build that. It depends >on there being a `%.ml` which in case of `main` would be `main.ml`. It runs >the long command written there, which makes use of `ocamlfind`. The hint to >use `ocamlfind` is the decisive hint someone gave me on this mailing list some >time ago. If there is a better way, please let me know. I need to be able to >specify arbitrary packages, that I install using guix, by writing them in the >`guix-env/manifest.scm` file. > >*(Issue 2)* > >So lets see what actually happens, when I try to run some `main.ml` file with >some code: > >~~~~ main.ml ~~~~ >(* In REPL instead use: > #require "zarith";; *) > >open Z >~~~~ > >`make main`: > >~~~~ make main result ~~~~ >ocamlfind ocamlc -package zarith -linkpkg -o main.byte main.ml >guix shell: checking the environment variables visible from shell >'/bin/bash'... >guix shell: All is good! The shell gets correct environment variables. >+ ocamlfind ocamlc -package zarith -linkpkg -o main.byte main.ml >findlib: [WARNING] Package unix has multiple definitions in >/gnu/store/q1jdsy1y8kzk18iy4snb9c85m6awl2jp-profile/lib/ocaml/unix/META, >/gnu/store/q1jdsy1y8kzk18iy4snb9c85m6awl2jp-profile/lib/ocaml/site-lib/unix/META, > >/gnu/store/yjik976n23235nhkr0amkrymb6kyfkxs-ocaml-findlib-1.9.5/lib/ocaml/site-lib/unix/META >findlib: [WARNING] Package threads has multiple definitions in >/gnu/store/q1jdsy1y8kzk18iy4snb9c85m6awl2jp-profile/lib/ocaml/threads/META, >/gnu/store/q1jdsy1y8kzk18iy4snb9c85m6awl2jp-profile/lib/ocaml/site-lib/threads/META, > >/gnu/store/yjik976n23235nhkr0amkrymb6kyfkxs-ocaml-findlib-1.9.5/lib/ocaml/site-lib/threads/META >File "main.ml", line 1: >Error: >/gnu/store/q1jdsy1y8kzk18iy4snb9c85m6awl2jp-profile/lib/ocaml/site-lib/zarith/z.cmi > is not a compiled interface for this version of OCaml. >It seems to be for an older version of OCaml. >make: *** [Makefile:23: main.byte] Error 2 >~~~~ > >For starters, the `findlib` warnings seem to be worrisome. Why does findlib >ever search somewhere, where it finds multiple definitions? I don't remember >this issue from this project setup appearing 1 or 2 years ago. This might >already be the cause for the next part of the issue. > >~~~~ >Error: >/gnu/store/q1jdsy1y8kzk18iy4snb9c85m6awl2jp-profile/lib/ocaml/site-lib/zarith/z.cmi > is not a compiled interface for this version of OCaml. >It seems to be for an older version of OCaml. >~~~~ > >Well, seems like it is not using the correct package, or Ocaml version >specified in manifest.scm, or the package got compiled using another Ocaml >version, or I don't know what's going on and what is going wrong. > >The issue with utop showing another version is already suspect. Maybe somehow >the `zarith` package got compiled using that older version of Ocaml too! > >But I don't know how to check that. Or how to stop Guix from doing that. Or >how to nail down the versions in a way that doesn't allow this to happen. > >I already tried running `guix gc` to maybe delete old `guix shell`s, but to no >avail. > >Here is a repository, which contains the project setup I described: >https://codeberg.org/ZelphirKaltstahl/advent-of-code-2025/src/commit/aa7d26056fc0ff442978d4bdebe615d533e54db4. > >Here is my `guix --version` output, in case it is relevant: > >~~~~ guix --version output ~~~~ >guix (GNU Guix) 7c6d8a6224cf3209efa179dbe1509759a580cb05 >Copyright (C) 2025 the Guix authors >License GPLv3+: GNU GPL version 3 or later<http://gnu.org/licenses/gpl.html> >This is free software: you are free to change and redistribute it. >There is NO WARRANTY, to the extent permitted by law. >~~~~ > >Here is my OS: > >~~~~ lsb_release -a ~~~~ >No LSB modules are available. >Distributor ID: Debian >Description: Debian GNU/Linux 12 (bookworm) >Release: 12 >Codename: bookworm >~~~~ > >So my questions are at this point: > >(1) How do people make reproducible Ocaml project setups? I don't mean only >version numbers ... It must be hashes and verifying those hashes. Otherwise I >don't think I will pursue things further with Ocaml. > >(2) How to fix my guix-using Ocaml project setup, so that I can run my code, >including ocaml-* packages that I install via guix? > >I am aware, that I could also create a guix profile. However, I don't think >that will change things and I am fine with a guix shell. All I want is >something reproducible, whether that is a guix profile or a guix shell, >doesn't really matter to me. guix shells are also cached, so it is not like I >need to rebuild the guix shell at every call of my Makefile targets either. > >I am at the end of my wits. If anyone can point me to a reproducible project >setup, or tell me what I am doing wrong in my setup, that would be great : ) > >Best regards, >Zelphir >
