4

On Arch Linux, installed Haskell libraries are dynamically linked by default. So to make anything compile in ghc, I have to use the -dynamic flag, otherwise it doesn't even discover the libraries. However, I would like to produce statically linked binaries that I can distribute to other systems.

Is there any way to produce a statically linked binary from dynamic/shared libraries with ghc?

I tried -optl-static from this related post but that led to countless "undefined reference" errors.

Ari Fordsham
  • 2,437
  • 7
  • 28
xeruf
  • 2,602
  • 1
  • 25
  • 48
  • Isn't `cabal v2-build` default to static linking? – arrowd Apr 14 '21 at 06:33
  • It seems this question is not GHC/Haskell specific - the question is, how to statically link against a dynamic library? My default answer would be that this is not possible. A solution would be to embed the dylibs in the executable, using something like AppImage on Linux or `windres` on Windows, but I don't know how you'd tell `cabal`/the linker to find them there. – Ari Fordsham Apr 15 '21 at 11:42

2 Answers2

1

Libraries compiled for dynamic linking are missing information needed for static linking (and vice versa). For details, see:

This is intrinsic in the design of the OS linker, and beyond any limitation of cabal or GHC. For example, this cannot be simply done in C either.

To achieve single-file redistributable binaries, you could try bundling the dynamic libs into the executable, using a format such as AppImage on Linux, or the windres resource scheme on Windows, but you would have to manually set up your code and cabal to find the libraries in the right place.

Ari Fordsham
  • 2,437
  • 7
  • 28
0

If you use The Stack build system, it will automatically download and manage a fixed version of GHC and all libraries per project (and store them in a hidden folder in your project directory), so if you get it set up right, the whole lot will be static. Stack doesn't have amazing static support right now, but it can be made to work. Some resources:

greybeard
  • 2,249
  • 8
  • 30
  • 66
Ari Fordsham
  • 2,437
  • 7
  • 28
  • well the whole idea was to not depend on another build system. In that case I'd use nix since I already have that installed anyways ^^ – xeruf Apr 15 '21 at 08:56
  • You might be able to do something similar with cabal sandboxes, and setting the right GHC options.. I'm curious as to why you insist on keeping cabal - you can convert an existing cabal project to stack using `stack init` (or to nix using `cabal2nix`) – Ari Fordsham Apr 15 '21 at 11:26
  • because I already have a working nix setup. I was curious whether there was a possibility to work with the bare-bones tooling. – xeruf Apr 16 '21 at 14:26
  • You might want to look at [cabal sandboxes](https://www.haskell.org/cabal/release/cabal-1.20.0.2/doc/users-guide/installing-packages.html#developing-with-sandboxes). All these approaches only work by re-downloading and building all dependencies in a static format - see my other answer. – Ari Fordsham Apr 18 '21 at 11:05