In my endeavor to statically compile the Elm compiler with a musl-based GHC I first had to cross-compile the latter since my system (Ubuntu 16.04) is glibc-based. This post describes how I did that. Most of it is inspired by other guides.

This post assumes that a cross-compiled toolchain can be found at $HOME/x-tools/x86_64-unknown-linux-musl/ and has been added to $PATH (crosstools-ng 1.22.0 has been used for this post). Instructions on how to configure crosstools-ng can be found in this post.

$ export PATH=$HOME/x-tools/x86_64-unknown-linux-musl/bin:$PATH

Now we’re ready to download the GHC source (and check its integrity by verifying its signature).

$ wget
$ wget

$ gpg --search-keys 97DB64AD
$ gpg --verify ghc-7.10.3b-src.tar.bz2.sig

We extract the source code and configure it to use our cross-compiling toolchain. Since the toolchain has been added to $PATH it can be found by configure automatically. To not interfere with our host system we set the prefix to /opt/ghc (where the binaries will later be installed to).

$ tar xf ghc-7.10.3b-src.tar.bz2
$ cd ghc-7.10.3/
$ ./configure --target=x86_64-unknown-linux-musl --prefix=/opt/ghc

We then copy the sample configuration and adapt it to out needs.

$ cp mk/ mk/
$ sed --in-place 's/#BuildFlavour = quick$/BuildFlavour = quick/' mk/

We don’t want our build to depend on GMP.

$ echo "INTEGER_LIBRARY = integer-simple" >> mk/

If we now tried to compile GHC we would run into all sorts of compiler and linker errors because of ncurses. We have two options: We can either get GHC to compile with ncurses by fixing the errors or we can circumvent them by not depending on ncurses. We take the latter choice and remove all dependencies on Haskell’s terminfo package from our build configuration (as is done here and here).

$ sed --in-place s/terminfo//
$ sed --in-place s/^.*terminfo// utils/ghc-pkg/ghc-pkg.cabal
$ sed --in-place s/unix,/unix/ utils/ghc-pkg/ghc-pkg.cabal
$ echo "utils/ghc-pkg_HC_OPTS += -DBOOTSTRAPPING" >> mk/

Now we’re finally ready to start the compilation and install the resulting binaries.

$ make -j 8
$ make install

/opt/ghc now contains a GHC compiler that won’t run on our glibc-based host system. It will, however, run on a musl-based system.