Generating a bills of material for a build

@dbuenzli soonish I will have to provide a software bill of materials and thought of an opam dependency list per release (package names + versions). How would you suggest to assemble such?

No idea. I guess @hannes knows better.

1 Like

Try How does one pin/freeze a version of the dependencies of an opam project/package and then install the project with such specified dependencies? - #7 by kit-ty-kate

1 Like

If you just need the package name, version and license, and if you are happy with a potential over-approximation you can use the same runes as in VPNKit.

ie. install your package in a switch and call opam list with the magic options:

$ opam list --installed --required-by=<your-package> --recursive --columns name,package,license: --separator=, --nobuild --color=never
1 Like

currently have the project just ad-hoc, not as a formal opam package yet, but will opamify it.

On we use Orb GitHub - roburio/orb: check opam package reproductibility to build packages and software. It records what opam packages and system packages are installed and is output to files opam-switch and system-packages. It can be inspected at e.g. this build:

opam-switch contains a switch export with probably more data than you care about if you’re not rebuilding. I made an issue on builder-web, the software behind, to have a view with just the versions of opam packages and system packages.


As mentioned by @reynir, we use orb for

It really depends how you assemble your piece of software. I recommend to just use orb (from GitHub - roburio/orb: check opam package reproductibility) – which uses the opam library for conducting the build of a single opam package. It outputs (a) the environment variables that were set while doing the build (b) the installed system packages (c) the opam packages.

So, best to use it in a minimal jail / container and have it create it’s own opam switch.

A more lightweight solution (if you’re only interested in the opam packages) is to use “opam switch export --full --freeze” – the generated file can be processed to only contain “package names + versions” only (but that information is not sufficient to rebuild the exact same binary, at least you will need to capture tarballs and their checksums or git commits (plus extra-files (patches) part of the opam package(s)), and the system packages influence the output as well (e.g. a different C compiler (or another version) leads to another binary.


If your build involves more than opam, you might also consider the dkml-runtime-common install_reproducible_* functions. It is a single script you can source, is available from the opam repository (but wget from Makefile is easier), and works on opam build platforms (Linux/macOS/Alpine/etc.) and Windows.

Documentation for now is just inline shell script comments. The minimal example is: . /z/source/dkml-runtime-common/unix/ && DEPLOYDIR_UNIX=deploydir BOOTSTRAPNAME=example install_reproducible_system_packages That will create a shell script deploydir/share/dkml/repro/example/ that will re-install all the system packages. Other functions are available to populate the rest of the “repro” tree with your required build scripts (ex. Makefile, a git clone script and an opam lock/manifest/export file).

(The intention was to be able to reproduce the ocaml compiler and opam from Diskuv OCaml using just a POSIX shell. So it is low level and nowhere near as nice and comprehensive as robur.)

1 Like

currently the is a bit messy (create changelog, build, sign source, copy to download server, deploy to demo) but I hesitate to pull in infrastructure yet or containerise. Also I want to currently focus on developing software rather than doing infra.

Nevertheless I want to be prepared for upcoming audits and be aware of some options.