Files
postgrest/nix/static.nix
T
Wolfgang WaltherandWolfgang Walther f51090f3d1 nix: Check static executable for /nix/store references
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.
2024-02-06 10:19:31 +01:00

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 { });
}