Building Static Haskell Binaries with Nix
Skip to the end for a faster and easier way of getting this working.
The section of the Nixpkgs manual that talks about creating statically linked binaries with Haskell ends with the caveat:
It’s important to realize, however, that most system libraries in Nix are built as shared libraries only, i.e. there is just no static library available that Cabal could link!
That sounds like a challenge. Especially when doing it on other platforms is so easy.
On other platforms, building a static binary is meant to be as simple as
with the magic happening in the second step. On Nix, we do in fact have the necessary static libraries and we can provide them as build inputs but keeping track of the library paths gets hairy quickly. Fortunately Nix has an escape hatch called
buildFHSUserEnv that we can use to simulate an environment that
cabal is more familiar with.
Let’s put it through its paces by building a simple Scotty web app:
This defines a chroot where statically linked versions of
zlib are available, as well as
zlib.h. We enter this environment by running
and then we can run the commands above with only slight modifications:
The difference is the extra options passed to the linker. After the last command, I get a whole bunch of warnings about
"Using '<function>' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking"
but these don’t seem to cause any issues in practice. You can confirm that the executable has been statically linked by running
I’ve made this project available here if you’d like to tweak it. Since this was relatively straightforward, I think it might be possible to do this without
buildFHSUserEnv. Maybe I will try that next.
Happy static linking!
Edit 1: This turned out to be fairly easy. I took the output of
configureFlags as follows:
This is also available in the linked repository.
Edit 2: Moritz Angermann improved these instructions to be more robust. Thanks Moritz!