Description
Currently static HLS binaries for linux are built using --enable-executable-static
. This makes cabal build fully static binaries, but statically linking glibc
is not a supported configuration by glibc
. In addition to this, glibc mismatches between the CI images and user environments can lead to many problems, including:
- Adding one empty import causes "Unexpected usage error" #1687
- HLS failing with
Assertion freesize < size failed
on a fairly minimal example #2328 - assertion failure from hls and ghc 8.10: `freesize < size' failed #429 as well as all the other similar issues (https://github.com/haskell/haskell-language-server/search?p=1&q=allocatestack&type=issues)
I also believe many of the segfaults reported on TH code have this as the underlying cause rather than bugs with the RTS linker (which do exist, but they aren't responsible for all of the pain).
Instead, we should be using the following configuration for building releases:
executable-dynamic: False
This uses the (vanilla, static) way to build and link Haskell code, but system libraries will still be linked in dynamically.
The difference between the binaries can be observed like so:
$ ldd hls-static-full # built with --enable-execuatable-static
not a dynamic executable
$ ldd hls-static # built with --disable-executable-dynamic
linux-vdso.so.1 (0x00007fff50bcf000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f408a70d000)
libz.so.1 => /usr/lib/libz.so.1 (0x00007f408a6f3000)
libtinfo.so.5 => /usr/lib/libtinfo.so.5 (0x00007f408a68f000)
librt.so.1 => /usr/lib/librt.so.1 (0x00007f408a684000)
libutil.so.1 => /usr/lib/libutil.so.1 (0x00007f408a67f000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f408a678000)
libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007f408a5d6000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f408a40a000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f408a2c6000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f408a768000)
By contrast, a fully dynamic build will link against a bunch of haskell libraries in ~/.cabal/store
and dist-newstyle/
Another option is to statically link against musl
on an alpine image, but this might still run into problems with loading user code (for TH and plugins) linked against mismatching system libraries. If we do take this route, we will have to bundle a whole GHC distribution (including libraries) with HLS releases, and ensure that hie-bios/cabal/stack uses the bundled GHC distribution to compile all the dependencies of the user's project.
This is made more complicated given that cabal
will share the package stores of different compilers as long as they have the same ghc --version
.