Static binaries are useful to distribute Haskell applications without requiring the user to build it themselves. Fully static Haskell executables are mostly supported by Nix; see this issue for details on whatβs left.
To get started quickly with building static binaries for your Haskell project,
-
Nixify your project: write a
default.nix
(See Nix recipes for Haskellers) -
Switch to a fork of nixpkgs reverting
3c7ef6b
. 1- You can try mine.
-
Write a
static.nix
(see below), that invokes thisdefault.nix
, using musl to build your app with static linking -
Run
nix-build static.nix
to produce a static binary under./result/bin
- Expect it to take a long time as it builds everything from source.
let
# Assuming we pin nixpkgs using https://github.com/nmattia/niv
sources = import ./nix/sources.nix;
# Your nixpkgs fork (see step 2 above)
nixpkgs = import sources.nixpkgs-fork { };
# Use `pkgsMusl` for static libraries to link against
pkgs = nixpkgs.pkgsMusl;
# This is your Haskell app compiled normally.
# It's default.nix takes a `pkgs` argument which we override with `pkgsMusl`
myapp = import ./default.nix { inherit pkgs; };
inherit (pkgs.haskell.lib) appendConfigureFlags justStaticExecutables;
in
# All that's left to do is call `justStaticExecutables` to configure Cabal to
# produce a static executable, as well as add the necessary GHC configure
# flags to link against static libraries.
appendConfigureFlags (justStaticExecutables ka)
[
"--ghc-option=-optl=-static"
"--extra-lib-dirs=${pkgs.gmp6.override { withStatic = true; }}/lib"
"--extra-lib-dirs=${pkgs.zlib.static}/lib"
"--extra-lib-dirs=${pkgs.libffi.overrideAttrs (old: { dontDisableStatic = true; })}/lib"
"--extra-lib-dirs=${pkgs.ncurses.override { enableStatic = true; }}/lib"
]
Other changes you might need to make
More complex projects may require additional fixes and workarounds.
-
If you see the error
crtbeginT.o: relocation R_X86_64_32 against hidden symbol '__TMC_END__'
, you might want to add"--disable-shared"
to the configure flags (see above). 2 -
Some tests may fail on musl (eg: hslua); disable them using
dontCheck
For Neuron in particular, see this PR for the actual changes to support building static binaries on Linux.
macOS
macOS does not support fully static binaries. And there is nothing in nixpkgs to build partially static binaries either.