Description
#1390 added support for fully statically linked Haskell binaries. As of that implementation users need to configure the GHC toolchain for fully static linking by setting static_runtime = True
and fully_static_link = True
on the toolchain and they need to configure compiler_flags = ["-optl-static"]
on the haskell_binary
targets that they want to have fully statically linked. @mboes raised whether this flag is necessary and whether we could build on Bazel precedent and use the fully_static_link
feature flag instead. I figured it's best to have that discussion on this issue tracker.
A related question was previously discussed to decide on the interface of the GHC toolchain, see #1390 (comment). As I argued in that discussion it is a property of the GHC distribution whether it is capable of fully static linking, so it makes sense to have a corresponding switch on the GHC toolchain rule. The remaining question is whether and how users control fully static linking on individual targets. These are the options I see:
- Always link fully statically when the toolchain is configured with
fully_static_link = True
. I.e. always pass-optl-static
to GHC (or--ghc-option=-optl-static
to Cabal). - Let the user configure fully static linking per target using Bazel's
fully_static_link
feature flag. - Let the user configure fully static linking per target by passing
-optl-static
to GHC (or--ghc-option=-optl-static
to Cabal).
Here's my view on each of these options:
- I think this would be the ideal option if it was feasible, but I don't think that it is feasible in practice at this point. E.g. I tried this approach on
minirepo
but noticed that it then fails to build@ghcide-exe//ghcide
. The reason is that it depends onlibtinfo
ofncurses
which is only available dynamically in thestatic-haskell-nix
configuration. Trying to switch to a staticlibtinfo
fails due to missing symbols such as__memcpy_chk
. IIUC this is means thatlibtinfo
depends onglibc
and is incompatible withmusl
. This indicates that it is necessary to give users per target control of whether they want to link fully statically or not and rules this option out. - The advantage of this approach is that it follows Bazel precedent and can be configured per package or even globally on the command-line. To allow users to enable fully statically linking particular binaries of
stack_snapshot
we'd need to add a new attribute to enable forwarding feature flags to the generated targets (that's something that we may need at some point anyway). Note, as pointed out by @lunaris there are issues with thefully_static_link
feature flag oncc_binary
. However, these shouldn't affect a Haskell binary with that feature flag enabled. - This is the status-quo. To allow users to enable fully statically linking particular binaries of
stack_snapshot
we'd need to add a new attribute to enable forwardingcabalopts
to the generated targets (that's also something that we may need at some point anyway). The advantage of this approach is that it's very simple and straight-forward. However, it doesn't allow for easy global or per package configuration asfeatures
does.
I don't see a clear winner between 2 and 3. But, 2 seems preferable as it follows Bazel precedent and allows for convenient global or per package configuration.