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:
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.
Currently static HLS binaries for linux are built using
--enable-executable-static. This makes cabal build fully static binaries, but statically linkingglibcis not a supported configuration byglibc. In addition to this, glibc mismatches between the CI images and user environments can lead to many problems, including:Assertion freesize < size failedon a fairly minimal example #2328I 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:
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:
By contrast, a fully dynamic build will link against a bunch of haskell libraries in
~/.cabal/storeanddist-newstyle/Another option is to statically link against
muslon 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
cabalwill share the package stores of different compilers as long as they have the sameghc --version.