[Haskell-cafe] GHC + musl = easier static linking

Marios Titas redneb8888 at gmail.com
Fri May 29 22:46:15 UTC 2015

I posted some notes about GHC on musl here:
https://github.com/redneb/ghc-alt-libc. I also posted there some notes
and a download link of a (mostly working) port of GHC to uClibc.

On Wed, May 27, 2015 at 6:40 PM, Marios Titas <redneb8888 at gmail.com> wrote:
> TL;DR: I made some GHC binaries for linux that rely on musl instead of
> glibc for easier static linking. Scroll down for the link.
> Dear *,
> As most of you know, musl is a linux only C standard library that is
> optimized for static linking. Statically linked binaries can simplify
> distribution and deployment. If you have tried to statically link a
> program with glibc, you will probably know that this does not always
> work as expected: for example, in many cases the resulting binary will
> require to be executed in a system that has the exact same version of
> glibc as the one that was used to compiled it. In essence, static
> binaries linked with glibc are oftentimes *less* portable than dynamic
> ones.
> I decided to see if I could use GHC with musl. The problem was that
> while I could find some references online, I could not find a
> precompiled version of GHC that uses musl. So I decided to try and a
> build one myself. I was able to successfully bootstrap GHC under musl
> and I am posting it today in case someone else finds it usefull:
>     https://drive.google.com/folderview?id=0B0zktggRQYRkbGJkbmU0UFFSYUE#list
> I posting this on google drive, I have no better place to host this,
> hopefully google will not disable my account :-)
> This is a fully bootstrapped (i.e. stage 2) GHC and *not* a cross
> compiler. So this will *not* work in a typical glibc based linux
> distribution. You need a complete musl based environment to use it
> (see bellow for that). Also, the binaries produced by this GHC will
> all depend on musl and not work on most glibc based distros. On the
> other hand, statically compiled binaries should be very portable and
> will not depend on any particular C standard library. I have done some
> minimal testing and it seems to work rather well; everything I tried
> to compile from hackage just worked. Additionally it can compile GHC
> itself which is always a good test. The size of the resulting static
> binaries is acceptable. In my 64 bit system, a simple hello world has
> the following sizes (stripped): 800K glibc dynanic, 1648K glibc
> static, and 1012K musl static.
> Why not use a cross-compiler? I have found that in practice it is
> easier to have a separete environment for producing static binaries. A
> cross-compiler requires that you also cross-compile all the C
> libraries that you use. Additionally, cabal has still problems (e.g.
> [1]) with cross-compiling and will not work out of the box.
> Note that musl is not 100% compatible with glibc, so some things might
> work slightly differently.
> If you do not like using a GHC precompiled by someone else, you can
> use my binaries to compile GHC under musl yourself; it would be easier
> than cross-compiling GHC from scratch.
> So how do you use this? You need a complete musl based environment.
> There a few musl based distros [2], albeit most of them are geared
> towards embedded applications. I personally use the experimental musl
> based gentoo image [3] which feels more like a regular distro. You can
> use it with chroot, lxc, or systemd-nspawn. For the sake of
> completeness, I have included at the end of this message some quick
> and dirty instructions on how to do this.
> [1] https://github.com/haskell/cabal/issues/1493
> [2] http://wiki.musl-libc.org/wiki/Projects_using_musl
> [3] http://distfiles.gentoo.org/experimental/amd64/musl/
> 8<-------------------------------------
> # gentoo stage3 image instructions
> CHROOT_PATH=/var/tmp/gentoo-musl
> cd /var/tmp
> wget http://distfiles.gentoo.org/experimental/amd64/musl/stage3-amd64-musl-vanilla-20150405.tar.bz2
> mkdir "$CHROOT_PATH"
> tar xjf stage3-amd64-musl-vanilla-20150405.tar.bz2 -C "$CHROOT_PATH"
> for x in dev proc sys; do mount --bind /$x "$CHROOT_PATH/$x"; done
> cp -L /etc/resolv.conf "$CHROOT_PATH/etc"
> chroot "$CHROOT_PATH" /bin/bash -l
> PS1="(chroot) $PS1"
> # fetch the gentoo package db for the first time (slow):
> emerge-webrsync
> # enable static libraries (*.a), which are disabled by default:
> sed -ie 's/USE="/USE="static-libs /' /etc/portage/make.conf
> # reinstall/recompile gmp so that we have its static libs:
> emerge --oneshot dev-libs/gmp
> # install ghc:
> tar xJf /path/to/ghc-7.10.1-x86_64-unknown-linux-musl.tar.xz -C /tmp
> cd /tmp/ghc-7.10.1; ./configure --prefix=/opt/ghc-7.10.1; make install
> # compile a hello world:
> cd /tmp
> echo 'main = putStrLn "Hello world"' > test.hs
> /opt/ghc-7.10.1/bin/ghc --make -O -optl-static test.hs
> ./test
> file ./test
> # Of course, using chroot this way is insecure, don't use to install
> packages from hackage.

More information about the Haskell-Cafe mailing list