This makes the static build fail in case any references to the nix store are left over. Those will increase the closure size of the nix derivation massively and lead to a huge docker image. At the same time, those references will not be functional on non-nix systems, to which the static executable is distributed, anyway.
88 lines
3.3 KiB
Nix
88 lines
3.3 KiB
Nix
{ compiler
|
|
, name
|
|
, pkgs
|
|
, src
|
|
}:
|
|
let
|
|
# This builds a static PostgREST exectuable based on pkgsStatic.
|
|
# pkgsStatic is based on musl, so is a kind of cross-compilation.
|
|
# We still make this explicit here via pkgsCross, because we need
|
|
# to get postgresql/libpq for musl, too.
|
|
pkgsCross = pkgs.pkgsCross.musl64;
|
|
inherit (pkgsCross) pkgsStatic;
|
|
inherit (pkgsStatic.haskell) lib;
|
|
|
|
packagesStatic =
|
|
pkgsStatic.haskell.packages."${compiler}".override (old: {
|
|
ghc = pkgsStatic.pkgsBuildHost.haskell.compiler."${compiler}".override {
|
|
# Using the bundled libffi generally works better for cross-compiling
|
|
libffi = null;
|
|
# Building sphinx fails on some platforms
|
|
enableDocs = false;
|
|
# Cross compiling with native bignum works better than with gmp
|
|
enableNativeBignum = true;
|
|
};
|
|
|
|
overrides = pkgs.lib.composeExtensions old.overrides (final: prev: {
|
|
postgresql-libpq = (prev.postgresql-libpq.override {
|
|
# postgresql doesn't build in the fully static overlay - but the default
|
|
# derivation is built with static libraries anyway.
|
|
postgresql = pkgsCross.libpq;
|
|
}).overrideAttrs (finalAttrs: prevAttrs: {
|
|
# Using use-pkg-config flag, because pg_config won't work when cross-compiling
|
|
configureFlags = prevAttrs.configureFlags ++ [ "-fuse-pkg-config" ];
|
|
# Using pkg-config without pkgsCross, because "pkg-config" is hardcoded in
|
|
# postgresql-libpq's Setup.hs. Using pkgsStatic to make pkg-config return the
|
|
# static libs for libpq.
|
|
nativeBuildInputs = prevAttrs.nativeBuildInputs ++ [ pkgs.pkgsStatic.pkg-config ];
|
|
|
|
buildInputs = prevAttrs.buildInputs ++ [
|
|
(pkgsStatic.libkrb5.overrideAttrs (finalAttrs: prevAttrs: {
|
|
# disable keyutils dependency, to avoid linking errors
|
|
configureFlags = prevAttrs.configureFlags ++ [ "--without-keyutils" ];
|
|
}))
|
|
];
|
|
});
|
|
});
|
|
});
|
|
|
|
makeExecutableStatic = drv: pkgs.lib.pipe drv [
|
|
(lib.compose.appendConfigureFlags [ "--enable-executable-static" ])
|
|
lib.compose.justStaticExecutables
|
|
|
|
# To successfully compile a redistributable, fully static executable we need to:
|
|
# 1. make executable really statically linked.
|
|
# 2. avoid any references to /nix/store to prevent blowing up the closure size.
|
|
# 3. be able to run the executable.
|
|
# When checking for references, we ignore the following:
|
|
# - eeee... are removed references which don't actually exist
|
|
# - openssl-etc references are purposely designed to be very small
|
|
(lib.compose.overrideCabal (drv: {
|
|
postFixup = drv.postFixup + ''
|
|
exe="$out/bin/postgrest"
|
|
|
|
if ! (file "$exe" | grep 'statically linked') then
|
|
echo "not a static executable, ldd output:"
|
|
ldd "$exe"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Checking for references to /nix/store..."
|
|
(${pkgsStatic.binutils}/bin/strings "$exe" \
|
|
| grep -v /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee \
|
|
| grep -v -etc/etc/ssl \
|
|
| grep /nix/store || exit 0 && exit 1)
|
|
echo "No references to /nix/store found"
|
|
|
|
"$exe" --help
|
|
'';
|
|
}))
|
|
];
|
|
|
|
in
|
|
{
|
|
inherit packagesStatic;
|
|
|
|
postgrestStatic = makeExecutableStatic (packagesStatic.callCabal2nix name src { });
|
|
}
|