Open nh2 opened 6 years ago
Related:
stack
support to make static linking easy https://github.com/commercialhaskell/stack/issues/3420ld-options
https://github.com/haskell/cabal/issues/4925cabal-install
itself https://github.com/haskell/cabal/issues/4941I know NixOS is careful about licenses and distribution. I'm thinking about libgmp, which is LGPL:
https://www.gnu.org/licenses/gpl-faq.en.html#LGPLStaticVsDynamic
(1) If you statically link against an LGPL'd library, you must also provide your application in an object (not necessarily source) format, so that a user has the opportunity to modify the library and relink the application.
(2) If you dynamically link against an LGPL'd library already present on the user's computer, you need not convey the library's source. On the other hand, if you yourself convey the executable LGPL'd library along with your application, whether linked with statically or dynamically, you must also convey the library's sources, in one of the ways for which the LGPL provides.
Can we ensure either one of these if we enable caching of static Haskell executables?
@puffnfresh: Or you could use a version of GHC with simple-integer
to avoid the GMP dependency
@Gabriel439 yeah, is that what we'll do for redistributing static Haskell executables?
This is great, thanks so much for working on this and creating this issue @nh2!
Before doing more of this https://github.com/NixOS/nixpkgs/pull/43524 -style fixing of individual package builds, could someone give a try of https://github.com/endrazine/wcc (which has been packaged in https://github.com/NixOS/nixpkgs/pull/43014) in converting shared objects to static objects?
@puffnfresh Every Haskell package already has a license
field (upstream and it's available as a field in nixpkgs).
The best solution seems to be to traverse the licenses of all things linked and ensure that Hydra does not build statically linked exes where one of the dependencies is LGPL or stronger (unless the final project itself is also LGPL or stronger anyway).
For executables blocked that way, a fallback should happen where it's checked if the issue goes away if integer-simple
was used instead; then Hydra can build it that way.
Before doing more of this #43524 -style fixing of individual package builds, could someone give a try of https://github.com/endrazine/wcc (which has been packaged in #43014) in converting shared objects to static objects?
@dezgeg It sounds interesting and may be worth a try but there may be the independent questions whether I want "binary black magic" (as wcc calls it) in my production binaries.
Nix is already pretty custom in its build process, I wouldn't want an upstream library author reject my bug report about a segfault with "well you use totally custom tools, if you just used our normally built static libs we would be more eager to look into that". It's a good feature if nix's builds still essentially are a series of "normal" build steps (compiler and linker invocations).
I haven't looked into wcc in detail so I cannot judge its safety, but my intuition tells me I'd rather sponsor Hydra some build servers and HDs than turn dynamic libs into static ones and have the risk of unexpected behaviour.
We already provide fully static builds of pandoc with each release, using docker and alpine.
The build process can be found in the linux/
directory in pandoc's repository.
Thank you for CCing me into this. Could Aura be added to the list of projects above? I haven't yet been able to decipher the instructions for testing it myself, apologies.
I just want to thank you @nh2 this is excellent work :)
@fosskers Does aura
have a nix derivation in hackage-packages
that I could use as a base?
Currently most executables I'm trying are already in nixpkgs and then I just override them with statify
function to build statically.
I haven't yet been able to decipher the instructions for testing it myself, apologies.
Conceptually very simple, for example for dhall
I just added 1 line here:
and then built with
NIX_PATH=nixpkgs=https://github.com/nh2/nixpkgs/archive/925aac04f4ca58aceb83beef18cb7dae0715421b.tar.gz nix-build --no-link survey/default.nix -A working
For some packages it works immediately, for others I have to make some small overrides of their dependencies (see a bit further up in the file), usually to give static libraries for system dependencies.
Having discussed it on IRC, here's a way of building all Haskell executables: https://gist.github.com/Infinisil/3bdb01689b5f84b71f8538f467159692
Just nix-build that file. This includes broken packages by default, because if you want to see which new packages your change breaks, you need to know which ones were broken already (so you should build this once before your change and once after, then compare).
Having discussed it on IRC, here's a way of building all Haskell executables
I have incorporated (a large part of) that into https://github.com/nh2/static-haskell-nix/blob/09d0eaa605111ea516dfaa0e7341a71ff1a63042/survey/default.nix#L47-L124 now.
So now we can build survey/default.nix -A allStackageExecutables
and see (with --keep-going
) how many of those build.
If some binary doesn't build because of dependent libraries making problems, those libraries are supposed to be patched here.
Contributors are welcome to help make as many of those build as possible.
@nh2 Aura isn't yet connected to Nix infrastructure in any way. I suppose I'll pull up my old notes about getting a project set up with Nix and try to build Aura that way at first.
It sounds interesting and may be worth a try but there may be the independent questions whether I want "binary black magic" (as wcc calls it) in my production binaries.
Nix is already pretty custom in its build process, I wouldn't want an upstream library author reject my bug report about a segfault with "well you use totally custom tools, if you just used our normally built static libs we would be more eager to look into that". It's a good feature if nix's builds still essentially are a series of "normal" build steps (compiler and linker invocations).
I understand the concern, yes.
my intuition tells me I'd rather sponsor Hydra some build servers and HDs than turn dynamic libs into static ones and have the risk of unexpected behaviour.
The problem isn't the disk space or resource usage but rather the effort of fixing packages one-by-one to support static linking and the cost of maintaining that. But maybe Haskell packages don't use too many native dependencies.
I have given a first run at building all executables on Stackage, statically.
See this post for full build outputs.
It took around 3 hours to get there (I built with 5 machines).
The final status line, [2/961/963 built (49 failed), 4245 copied (19215.1 MiB), 210.7 MiB DL]
already gives us some information on the success.
The program didn't terminate; right now it's
building darcs-2.14.1
dist/build/test-courier/test-courier
from the courier
package is stuck on a 100% CPU loop for the last 11 hoursInsights:
Cabal = Cabal_patched;
into the haskellPackagesWithLibsReadyForStaticLinking
overrides
(I would like to avoid it that unpatched Cabal can be used for most packages)useFixedCabal
on all the dependencies used in Setup.hs
of those 6 packages (as described in the linked ticket, it can be very cumbersome to figure out which are those dependencies)cannot find -l*
, so static libs are missing for those libraries. These are:
bz2
crypto
curl
expat
girepository-1.0
glib-2.0
gobject-2.0
mpfr
nettle
pcre
pq
ssl
xml2
But maybe Haskell packages don't use too many native dependencies.
@dezgeg Yes, I think that is accurate.
From what I posted a just above, it looks like most of Stackage's executables will be buildable as long as a set of 15 native libs (13 above and sqlite
and lzma
which I already have done) are overridden with static support.
Great work!
My rule of thumb for static vs shared is:
We pretty much need to support both in Nixpkgs. I can see some of the benefits of always building statically but I think the advantages to shared linking is much greater.
I've found and PRd a fix for another cabal issue that needs to be merged to make static linking reasonable:
https://github.com/haskell/cabal/pull/5451
This passes --ld-option
through to GHC so that we can specify extra options in configureFlags
that are needed only for static linking.
I've also added it to the overview in the issue description.
My rule of thumb for static vs shared is:
If you're targeting something outside of a Nix store - build static If you're targeting inside of a Nix store - build shared
This makes sense.
We pretty much need to support both in Nixpkgs
Yes. One of my goals is that nixpkgs becomes the building environment which makes it really easy to build any program so that it works on any Linux distribution, forever.
Other Linux distributions make it really hard to build things statically.
I can see some of the benefits of always building statically but I think the advantages to shared linking is much greater.
I guess I agree in general but there are some exceptions / other points, like
.so
dependencies take up to 2 seconds to show their --help
textI'd find it very cool if somebody could build a typical NixOS with only static exes and compare what the size difference (and perhaps resident memory difference) is.
Update:
darcs
libcurl
which itself has many dependencies, and had to fix a cabal issue for it, but it's working now.Update:
pandoc
hslua
test case segfault might mean some functionality will crashI've played with this a bit and here are sizes for cachix:
And using UPX:
Seems like using UPX and not (re?)compressing is the best way to go for distributing static execs :)
@domenkozar: What's the difference in startup times?
Niklas Hambüchen notifications@github.com writes:
Update:
* [x] `pandoc` (CC @jgm) * [working](https://github.com/nh2/static-haskell-nix/blob/master/survey/default.nix#L335) but this [`hslua` test case segfault](https://github.com/hslua/hslua/issues/67) might mean some functionality will crash
Another known limitation with the statically compiled pandoc is that lua filters it runs can't load binary lua modules (e.g. lpeg.so).
@Gabriel439
$ bench './cachix --version'
benchmarking ./cachix --version
time 52.99 ms (49.53 ms .. 56.51 ms)
0.982 R² (0.954 R² .. 0.996 R²)
mean 51.37 ms (49.28 ms .. 53.97 ms)
std dev 4.183 ms (3.210 ms .. 5.326 ms)
variance introduced by outliers: 29% (moderately inflated)
$ bench './cachix-upx --version'
benchmarking ./cachix-upx --version
time 88.26 ms (82.51 ms .. 92.93 ms)
0.996 R² (0.989 R² .. 0.999 R²)
mean 93.80 ms (91.46 ms .. 98.58 ms)
std dev 5.019 ms (2.032 ms .. 8.197 ms)
variance introduced by outliers: 10% (moderately inflated)
I have further reduced the number of build errors as of https://github.com/nh2/static-haskell-nix/commit/7e41d26eb7403806d6be5f7046efcea3b05442ab.
I also added functionality to inform nix Haskell packages to dontCheck
when Stackage says that the test is known to spuriously fail.
17
of 311
Stackage executables don't easily compile staticallyBy specifying some more dependencies, the remaining failures can probably be removed. But I think this is good enough for now.
This approach works.
There is a very high chance you can link any Haskell executable you want statically with this tooling.
And it is easy. At worst you have to pass a couple linker flags for your final link (example), and perhaps we can automate that away entirely with pkg-config
.
I consider this a success.
To link your exe statically, the simplest way to get started is to add it to survey/default.nix
, get it to build, and then perhaps strip away everything you don't need (as the file is, well, a survey of all the packages and contains more than you need).
There are a couple upstream fixes I had to make to get this far but I expect those to be merged soon so the file will shrink significantly.
I was interested in whether the produced binaries are byte-reproducible across builds.
Wth a miniscule modification to build non-parallelly because GHC current isn't deterministic when building in parallel:
dhall = appendConfigureFlag super.dhall "--ghc-option=-j1";
Using Nix's --check
functionality that tests that:
$ NIX_PATH=nixpkgs=https://github.com/nh2/nixpkgs/archive/50677e46.tar.gz nix-build survey/default.nix -A haskellPackages.dhall
/nix/store/69879zd79xxfm0p04fkvz1sdk5rjkda3-dhall-1.15.1
$ nix-store --realise --check $(NIX_PATH=nixpkgs=https://github.com/nh2/nixpkgs/archive/50677e46.tar.gz nix-instantiate survey/default.nix -A haskellPackages.dhall) -K
...
note: keeping build directory '/tmp/nix-build-dhall-1.15.1.drv-1'
error: derivation '/nix/store/005xjwn36wy3lv04rs0bqazr70hmkpjd-dhall-1.15.1.drv' may not be deterministic: output '/nix/store/69879zd79xxfm0p04fkvz1sdk5rjkda3-dhall-1.15.1' differs from '/nix/store/69879zd79xxfm0p04fkvz1sdk5rjkda3-dhall-1.15.1.check'
CC @Gabriel439
.hi
files but ...diff -u <(/nix/store/hfi080vzqqzfip6bd6x4cxc2jgj56xn3-ghc-8.4.3/lib/ghc-8.4.3/bin/ghc -B/nix/store/hfi080vzqqzfip6bd6x4cxc2jgj56xn3-ghc-8.4.3/lib/ghc-8.4.3 --show-iface /nix/store/69879zd79xxfm0p04fkvz1sdk5rjkda3-dhall-1.15.1/ghc-8.4.3/dhall-1.15.1/Dhall/Main.dyn_hi) <(/nix/store/hfi080vzqqzfip6bd6x4cxc2jgj56xn3-ghc-8.4.3/lib/ghc-8.4.3/bin/ghc -B/nix/store/hfi080vzqqzfip6bd6x4cxc2jgj56xn3-ghc-8.4.3/lib/ghc-8.4.3 --show-iface /nix/store/69879zd79xxfm0p04fkvz1sdk5rjkda3-dhall-1.15.1.check/ghc-8.4.3/dhall-1.15.1/Dhall/Main.dyn_hi)
--- /proc/self/fd/11 2018-07-22 20:49:24.335131983 +0200
+++ /proc/self/fd/13 2018-07-22 20:49:24.335131983 +0200
@@ -5,7 +5,7 @@
Way: Wanted [],
got [d, y, n]
interface Dhall.Main 8043
- interface hash: 0a05064b054e655b52f1017487829234
+ interface hash: c1f16b2ba4b2cfc8a9e78ef9bd952e61
ABI hash: 415f06e049531325866e9ad64e625758
export-list hash: 11282f31ed241c062825f667c7342544
orphan hash: ced52be674fb2cac8ebaf6fe6391f669
@@ -223,7 +223,7 @@
TypeError df38e2333b1a033fa152979879d95590
X e963e1c8e00353569b8d10b0b8014dd8
typeOf 3ada20aba4eb03cf4e83458e9e74865e
-import -/ Paths_dhall f274db0756d0d9c06011b6b2909c416a
+import -/ Paths_dhall 1840d1baae0db0a2a6b8788056d462a6
exports: 1dc0dfdfd07302caa8953ea30539b0b6
version 0911ed4004691170ff7c1c42f11d0fb7
import -/ GHC.Classes 122abfcd7450c6c11602933c9ca5f80d
So there's a little bit of work to do to ensure that this one Paths_dhall
import is reproducible across builds.
The other bit (interface hash
) actually depends on that and will be right automatically as soon as we fix Paths_dhall
.
Despite the .hi
files being minimally different, the final binary is byte-identical:
% sha256sum /nix/store/69879zd79xxfm0p04fkvz1sdk5rjkda3-dhall-1.15.1/bin/dhall /nix/store/69879zd79xxfm0p04fkvz1sdk5rjkda3-dhall-1.15.1.check/bin/dhall
970dc00e0711a89c8c52c889e62743e084625ce66476300a6ad83a8f08ee6827 /nix/store/69879zd79xxfm0p04fkvz1sdk5rjkda3-dhall-1.15.1/bin/dhall
970dc00e0711a89c8c52c889e62743e084625ce66476300a6ad83a8f08ee6827 /nix/store/69879zd79xxfm0p04fkvz1sdk5rjkda3-dhall-1.15.1.check/bin/dhall
Note here I built only dhall
repeatedly , not all of its dependencies; that would be another task with more chance for things being different. Maybe somebody else can try that!
@nh2: In can confirm that in my CI build (which is derived from your code), I have justStaticExecutables
set and once you do that then the build passes --check
(since it doesn't generate any library code or interface files):
$ nix-store --realise --check /nix/store/vr213i033l681p4is3c2l3729kacwfsf-dhall-1.16.1.drv
...
warning: rewriting hashes in '/nix/store/vhdpfa4dmi4n9j8pqfz61n1lrr7wcv62-dhall-1.16.1'; cross fingers
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
/nix/store/vhdpfa4dmi4n9j8pqfz61n1lrr7wcv62-dhall-1.16.1
$ nix-store --realise --check /nix/store/s33rwklhbilijccdzgq9i5gbr60y0j1w-dhall-json-1.2.2.drv
...
warning: rewriting hashes in '/nix/store/h79vgw9d9dn4m3jicbnhs96gm90hhsdd-dhall-json-1.2.2'; cross fingers
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
/nix/store/h79vgw9d9dn4m3jicbnhs96gm90hhsdd-dhall-json-1.2.2
Relevant code here in case anybody wants to reproduce on their end:
For the record, here is some evidence that fully dynamic linking of Haskell library dependencies is not a good idea (nixpkgs already doesn't do this any more by default):
ldd /nix/store/6rdybwykb7lj9f6451hz7n54pijhhfdc-stack-1.8.0/bin/stack
Output:
% time /nix/store/6rdybwykb7lj9f6451hz7n54pijhhfdc-stack-1.8.0/bin/stack --help
1.57s user 0.05s system 17% cpu 9.048 total
Static version:
% time /nix/store/2yzcb3idkrgpia8xcpwkr39x61vvvzh5-stack-1.7.1/bin/stack --help
0.01s user 0.01s system 18% cpu 0.089 total
That's a 100x startup difference, and 9 seconds are brutal.
@matthewbauer
We pretty much need to support both in Nixpkgs. I can see some of the benefits of always building statically but I think the advantages to shared linking is much greater.
Could you (re)explain what those are? I can see:
Are there others?
For me, I like being able to see what dependencies a package is using at runtime. With static builds, tools like nix why-depends
won’t show your dependencies.
The startup time issue is very concerning though.
The startup time issue is due to quadratic R(UN)PATH lookup. If we could stop relying on R(UN)PATHs and use absolute paths it would go away. @sphalerite was working on this; Darwin already does it; we could rip a bunch of fragile junk out of ld-wrapper or we did.
For the record I'm for separate all-dynamic and all-static nixpkgs. I don't think Haskell should be a special case, but yes the status quo is untenable.
For the record I'm for separate all-dynamic and all-static nixpkgs. I don't think Haskell should be a special case, but yes the status quo is untenable.
I feel this is a good example why nixpkgs needs use-flags (#12877).
All-static nixpkgs isn't viable because a metric ton of packages won't support static-only linkage.
For me, I like being able to see what dependencies a package is using at runtime. With static builds, tools like nix why-depends won’t show your dependencies.
I always thought that's exactly why Nix is so cool with static linking, you can always check build time dependency graph and see what were all the inputs for the final executable.
why-depends you can still use if you recompile dynamically, but I don't see how this could be useful for statically linked executables that get stripped down due to code elimination during linking. If the executable does end up depending on something due to Nix, then you'll see it with why-depends
anyway.
I always thought that's exactly why Nix is so cool with static linking, you can always check build time dependency graph and see what were all the inputs for the final executable.
That would include build tools though. But it's probably a good estimation
I feel this is a good example why nixpkgs needs use-flags (#12877).
I think overlays can give us everything that use flags could. I originally thought use flags would be the solution but coordinating between packages seems to be too complicated. Instead, we can just have an official static overlay that knows all of the individual package flags. This gives us a lot more power in what we build.
All-static nixpkgs isn't viable because a metric ton of packages won't support static-only linkage.
Maybe a subset of nixpkgs though? I am mainly thinking of "core" libraries here - things that would take a really long time to rebuild if you did it yourself. It could be the equivalent of release-small.nix.
Yeah that's enough packages so Alpine Linux can exist, so that will do.
Really? The first package I checked on their package list (python2) depends on: https://pkgs.alpinelinux.org/contents?branch=edge&name=sqlite-libs&arch=x86&repo=main which contains /usr/lib/libsqlite3.so.0
. Doesn't sound very statically linked to me.
Yeah, Alpine is musl-based but uses dynamic linking.
Seems like using UPX and not (re?)compressing is the best way to go for distributing static execs :)
@domenkozar
Since you're using Haskell for everything else, you should definitely look at packaging with Arx. It's an alternative to UPX that is written in Haskell.
Oh my bad. I thought it was also statically linked. I guess I was thinking of stali Linux or something.
All-static nixpkgs isn't viable because a metric ton of packages won't support static-only linkage.
@dezgeg Would static-only be required? For me, "all-static nixpkgs" means "libraries provide .a files and executables are statically linked"; if some packages also supply .so
files because their build systems don't allow us to turn that off, that seems acceptable to me (sure it bumps closure size unnecessarily a bit but perhaps that can be come by by just deleting the unnecessary files manually?).
Instead, we can just have an official static overlay that knows all of the individual package flags.
@matthewbauer From what I've seen so far, that seems quite reasonable and achievable. Even easier if most/many individual packages can supply a static ? false
option (as many already do), as even in normal nixpkgs that is sometimes useful to have.
Yes, I think "all-static nixpkgs" even in that form is impossible (or annoyingly hard) to achieve. It's a combination of 1. Some build systems (like CMake) not allowing to compile both static and shared libs at the same time, you only get to choose one. 2. Lots of packages simply not supporting static linking. E.g. native extensions in Python and all those scripting languages will need dlopen()
. I checked the Buildroot distribution for numbers, and like 15% of their packages don't support static linkage (I grepped for the following:)
<... etc ...>
package/libgsm/Config.in:comment "libgsm needs a toolchain w/ dynamic library"
package/libhdhomerun/Config.in:comment "libhdhomerun needs a toolchain w/ threads, dynamic library"
package/libhttpparser/Config.in:comment "libhttpparser needs a toolchain w/ dynamic library"
package/libical/Config.in:comment "libical needs a toolchain w/ C++, dynamic library, wchar"
package/libkcapi/Config.in:comment "hasher application needs a toolchain w/ dynamic library"
package/libkrb5/Config.in:comment "libkrb5 needs a toolchain w/ dynamic library"
package/libmicrohttpd/Config.in:comment "libmicrohttpd https support needs a toolchain w/ wchar, dynamic library"
package/libminiupnpc/Config.in:comment "libminiupnpc needs a toolchain w/ dynamic library"
<... etc. for 300 lines ...>
15% of their packages don't support static linkage (I grepped for the following:)
@dezgeg Can you elaborate a bit more on what that grep / needs a toolchain w/ dynamic library
exactly means?
I am confused because libkrb5 needs a toolchain w/ dynamic library
-- in https://github.com/NixOS/nixpkgs/pull/43870/files#diff-ec356e56a00da46032d5dfbd16326bd6R30 I pass "--enable-static" "--disable-shared"
to krb5
to build static libs and that seems to work fine.
Does the message refer to the build toolchain needing to provide dynlib facilities, but after the build is done, that's not needed any more? If yes, that seems OK to me: It would be annoying but acceptable to have to provide a dynlib capable build toolchain, as long as we can eventually produce static libs/exes for things that build on top of them.
Even less nicely, for the dlopen()
so could provide the SOs but patch ld from resolving them for regular DT_NEEDED entries.
To be honest, the notion of all-static Nixpkgs fills me with dread, since the number of packages that will need patches or other special handling is likely to be significant (I would guess much worse than say musl support).
If you just want to build static Haskell executables right now, follow these instructions.
This issue collects/links all issues and ongoing work to make fully-static building of Haskell executables an excellently-working feature in nixpkgs.
I will update here regularly the progress we are making, and sub-goals we encounter on the way that need to be fulfilled to tick off the parent goal.
Obviously contributions to this list are welcome.
stack
based projects with their ownresolver
should be really easystack
based example should be added (here)survey
directory of https://github.com/nh2/static-haskell-nixconfiguration-hackage2nix.yaml
to be able to filter for Stackage packages (thanks @domenkozar for the tip)stack
stack
builds withcrossSystem = { config = "x86_64-unknown-linux-musl"; };
stack
builds withpkgsMusl
stack
builds with its own Stackage snapshot viastack2nix
stack
1.9 official release uses this toolchain for its static buildintray-web-server
(which includes, amongst others,servant
) (CC @NorfairKing)dhall
(CC @Gabriel439)cachix
(CC @domenkozar)xmonad
libgmp.so.3
errorlibgmp
error is gone since https://github.com/NixOS/nixpkgs/issues/43795#issuecomment-495035217pandoc
(CC @jgm)hslua
test case segfault might mean some functionality will crashdarcs
libcurl
which itself has many dependencies, and had to fix a cabal issue for it, but it's working now.aura
static-haskell-nix
CI build that tracks nixpkgsmaster
to find breakage early (done)crossSystem = { config = "x86_64-unknown-linux-musl"; };
support is working (done by @dtzWill)pkgsMusl
support has landed in nixpkgs master (done by @dtzWill)master
Argument list too long
when linkingCabal
--enable-executable-static
feature is available in nixpkgshaskellPackages
where all exes are statically linkedCabal
release is available that includes itCabal
--ld-option
GHC passthrough feature is available in nixpkgs.a
files) only at the linker stageCabal
release is available that includes it.a
files)ncurses
.a
andtinfo
fix has been merged tostaging
(done by (@shlevy).a
andtinfo
fix has been merged tomaster
(this is a mass-rebuild PR) (merged)staging
has landed inmaster
(only.a
fix, nottinfo
part, because it's not a mass-rebuild PRpkgsStatic
- a fully static overlaypkgsStatic
to nixpkgsmaster
(@matthewbauer)static-haskell-nix
on top of it (move system dependency overrides that add static libs there)pkgsStatic
can be used as a base.pkgsStatic
(https://github.com/NixOS/nixpkgs/issues/61575), then drop commitpkgsStatic: Don't disable .so files.
from forked nixpkgsmaster
static-haskell-nix
's Haskell functionality over as well-ffunction-sections
can make final executables even smaller (results)integer-simple
instead ofinteger-gmp
, aslibgmp
is the biggest LGPL dependency of all Haskell programs (see here)integer-openssl
to be ready for use (CC @ch1bo)Why is static linking desirable?
Static linking means your executable depends on as few things running on the target system as possible.
For Linux, it means that an executable you build will work on any Linux distribution, with essentially infinite forwards-compatibility (because Linux in general does not change its system call interface).
Statically linked executables do not depend on the target system's
libc
.Statically linked executable are incredibly easy to deploy (many Go executables are statically linked, which gave them the reputation of being easy to deploy in the devops world).
Statically linked executables can start faster than dynamically linked ones where dynamic linking has to be performed at startup (of course the startup time depends on the number of libraries to link and the amount of symbols contained within).
Statically linked executables are smaller (up to 4x in our mesurements), mostly because GHC's
-split-sections
has way more effects with them (for unknown reason for now).Who is working on or contributing to this
Feel free to add yourself!