Skip to content

User interface for fully statically linked Haskell binaries #1408

Open
@aherrmann

Description

@aherrmann

#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:

  1. 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).
  2. Let the user configure fully static linking per target using Bazel's fully_static_link feature flag.
  3. 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:

  1. 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 on libtinfo of ncurses which is only available dynamically in the static-haskell-nix configuration. Trying to switch to a static libtinfo fails due to missing symbols such as __memcpy_chk. IIUC this is means that libtinfo depends on glibc and is incompatible with musl. 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.
  2. 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 the fully_static_link feature flag on cc_binary. However, these shouldn't affect a Haskell binary with that feature flag enabled.
  3. 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 forwarding cabalopts 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 as features 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.

@mboes @lunaris WDYT?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions