Skip to content

Commit

Permalink
top-level/stage.nix: add static overlay
Browse files Browse the repository at this point in the history
Adds the static overlay that can be used to build Nixpkgs statically.
Can be used like:

  nix build pkgsStatic.hello

Not all packages build, as some rely on dynamic linking.
  • Loading branch information
matthewbauer committed Dec 5, 2018
1 parent 53a6789 commit 6d90a8b
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 0 deletions.
10 changes: 10 additions & 0 deletions pkgs/stdenv/darwin/portable-libsystem.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Make /nix/store/...-libSystem “portable” for static built binaries.
# This just rewrites everything in $1/bin to use the
# /usr/lib/libSystem.B.dylib that is provided on every macOS system.

fixupOutputHooks+=('fixLibsystemRefs $prefix')

fixLibsystemRefs() {
find "$1/bin" \
-exec install_name_tool -change @libsystem@ /usr/lib/libSystem.B.dylib {} \;
}
16 changes: 16 additions & 0 deletions pkgs/top-level/stage.nix
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,22 @@ let
# Prefer appendOverlays if used repeatedly.
extend = f: self.appendOverlays [f];

# Fully static packages.
# Currently uses Musl on Linux (couldn’t get static glibc to work).
pkgsStatic = nixpkgsFun ({
crossOverlays = [ (import ./static.nix) ];
} // lib.optionalAttrs stdenv.hostPlatform.isLinux {
crossSystem = {
parsed = stdenv.hostPlatform.parsed // {
abi = {
"gnu" = lib.systems.parse.abis.musl;
"gnueabi" = lib.systems.parse.abis.musleabi;
"gnueabihf" = lib.systems.parse.abis.musleabihf;
}.${stdenv.hostPlatform.parsed.abi.name}
or lib.systems.parse.abis.musl;
};
};
});
};

# The complete chain of package set builders, applied from top to bottom.
Expand Down
150 changes: 150 additions & 0 deletions pkgs/top-level/static.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# Overlay that builds static packages.

# Not all packages will build but support is done on a
# best effort basic.
#
# Note on Darwin/macOS: Apple does not provide a static libc
# so any attempts at static binaries are going to be very
# unsupported.
#
# Basic things like pkgsStatic.hello should work out of the box. More
# complicated things will need to be fixed with overrides.

self: super: let
inherit (super.stdenvAdapters) makeStaticBinaries
overrideInStdenv
makeStaticLibraries;
inherit (super.lib) foldl optional flip id optionalAttrs composeExtensions;
inherit (super) makeSetupHook;

# Best effort static binaries. Will still be linked to libSystem,
# but more portable than Nix store binaries.
makeStaticDarwin = stdenv: stdenv // {
mkDerivation = args: stdenv.mkDerivation (args // {
NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "")
+ " -static-libgcc";
nativeBuildInputs = (args.nativeBuildInputs or []) ++ [ (makeSetupHook {
substitutions = {
libsystem = "${stdenv.cc.libc}/lib/libSystem.B.dylib";
};
} ../stdenv/darwin/portable-libsystem.sh) ];
});
};

staticAdapters = [ makeStaticLibraries ]

# Apple does not provide a static version of libSystem or crt0.o
# So we can’t build static binaries without extensive hacks.
++ optional (!super.stdenv.hostPlatform.isDarwin) makeStaticBinaries

++ optional super.stdenv.hostPlatform.isDarwin makeStaticDarwin

# Glibc doesn’t come with static runtimes by default.
# ++ optional (super.stdenv.hostPlatform.libc == "glibc") ((flip overrideInStdenv) [ self.stdenv.glibc.static ])
;

# Force everything to link statically.
haskellStaticAdapter = self: super: {
mkDerivation = attrs: super.mkDerivation (attrs // {
enableSharedLibraries = false;
enableSharedExecutables = false;
enableStaticLibraries = true;
});
};

in {
stdenv = foldl (flip id) super.stdenv staticAdapters;

haskell = super.haskell // {
packageOverrides = composeExtensions
(super.haskell.packageOverrides or (_: _: {}))
haskellStaticAdapter;
};

ncurses = super.ncurses.override {
enableStatic = true;
};
libxml2 = super.libxml2.override {
enableShared = false;
enableStatic = true;
};
zlib = super.zlib.override {
static = true;
shared = false;

# Don’t use new stdenv zlib because
# it doesn’t like the --disable-shared flag
stdenv = super.stdenv;
};
xz = super.xz.override {
enableStatic = true;
};
busybox = super.busybox.override {
enableStatic = true;
};
v8 = super.v8.override {
static = true;
};
libiberty = super.libiberty.override {
staticBuild = true;
};
ipmitool = super.ipmitool.override {
static = true;
};
neon = super.neon.override {
static = true;
shared = false;
};
libjpeg = super.libjpeg.override {
static = true;
};
gifsicle = super.gifsicle.override {
static = true;
};
bzip2 = super.bzip2.override {
linkStatic = true;
};
optipng = super.optipng.override {
static = true;
};
openssl = super.openssl.override {
static = true;

# Don’t use new stdenv for openssl because it doesn’t like the
# --disable-shared flag
stdenv = super.stdenv;
};
boost = super.boost.override {
enableStatic = true;
enableShared = false;
};
gmp = super.gmp.override {
withStatic = true;
};
cdo = super.cdo.override {
enable_all_static = true;
};
gsm = super.gsm.override {
staticSupport = true;
};
parted = super.parted.override {
enableStatic = true;
};
libiconvReal = super.libiconvReal.override {
enableShared = false;
enableStatic = true;
};
perl = super.perl.override {
# Don’t use new stdenv zlib because
# it doesn’t like the --disable-shared flag
stdenv = super.stdenv;
};

darwin = super.darwin // {
libiconv = super.darwin.libiconv.override {
enableShared = false;
enableStatic = true;
};
};

}

0 comments on commit 6d90a8b

Please sign in to comment.