Compared to opam: brew is hell!

My god, the reproducibility of builds is terribly bad with Mac OS X brew.
They don’t keep track of all the versions of a given package that
were available over time.
If you were relying on package X at version 1.60, tomorrow
someone could overwrite 1.60 with 1.61 and break everything
for all those who rely on 1.60…
And people don’t have a simple way of installing the lost 1.60 version.
brew is just a hack. I am so disappointed.


Years ago, Maven (for Java) was like that. Since I no longer need to think about Java, I don’t know if they ever fixed it. But yeah, it was hell trying to get reproducible build-environments.

1 Like

You can give Nix a try. Sadly Guix, which I prefer over Nix, doesn’t support OS X for now.


Yeah, nix is one of those things nagging at me for some time. :slight_smile:

About nix, I found this language introduction very well written:


Why does is guix better? I haven’t used either nix or guix but am curious about your opinion on this

1 Like

Brew is not a build tool though. And neither is opam if we’re being specific. They’re both package managers. Neither has very good support for build reproducibility. It sounds like Nix is your best bet :slight_smile:

But a package-manager that doesn’t make it straightforward to specify/pin versions of dependencies, is kind of useless. B/c at installation-time for production system, you need to know that you’re getting the precise versions in prod, that you had in staging, etc, etc. Version skew is unacceptable in production systems. So a package-manager actually should have -stronger- requirements than a build-tool, in this regard.

For myself, this is why I became (and remain) a (Debian) dpkg bigot.

1 Like

Perhaps this recent thread would interest you :slight_smile: Should opam use a lockfile by default?

There is pkgsrc. Brew is pathetic (but unfortunately very popular).

Closer to home, there is 0install which is famously written in OCaml!

1 Like

@sid here are two quite good comparisons:

A few points I recite here:

  • Packages are first class citizens in Guix. In Nix the idea of functional package management is very obvious in the way that packages are defined, namely as functions. These functions take their concrete inputs from an enormous mapping. In Guix you define first-class package values as Scheme variables. These package values reference other package values, which leads to a lazily constructed graph of packages. This emergent graph can be used as a library to trivially build other tools like “guix graph” (for visualising the graph in various ways) or “guix web” (for a web interface to installing and searching packages), “guix refresh” (for updating package definitions), a lovely feature-rich Emacs interface etc.
  • Graph rewriting. Having everything defined as regular Scheme values means that you can almost trivially go through the package graph and rewrite things, e.g. to replace one variant of a package with a different one. Your software environment is just a Scheme value and can be inspected or precisely modified with a simple Scheme API.
  • Bootstrapping. Some of us are very active in the “bootstrappable builds” community (see and are working towards full bootstrap paths for self-hosting compilers and build systems. One result is a working bootstrap path of the JDK from C (using jikes, sablevm, GNU classpath, jamvm, icedtea, etc). In Guix we take bootstrapping problems serious and prefer to take the longer way to build things fully from source instead of just adding more binary blobs. This means that we cannot always package as many things as quickly as others (e.g. Java libraries are hard to build recursively from source). I’m currently working on bootstrapping GHC without GHC and without the generated C code, but via interpreting a variant of GHC with Hugs. Others are working on bootstrapping GCC via Scheme.

Pkgsrc should seriously improve on the “working out of the box” front.
Brew is so popular because it gets you started very fast (at least it has this “feature” right).
I gave a try at pkgsrc, I got errors and I did not want to edit a Makefile
to fix it, so I gave up pretty quickly.

1 Like

In opam / the opam-repository, one thing that could improve build reproducibility would be
to record which package versions were present in the repository when a package
was introduced. So, if one day the package doesn’t build anymore, but one really needs this package now, he could ask to try forcing all the package dependencies to this at-least-seen-once working state.

Exactly :slight_smile: see the recent thread on lockfiles.