From 3c36dccd7ca4bcc3a3899e794864780dc7a4ce8c Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 4 Dec 2018 21:17:22 -0600 Subject: [PATCH 1/2] top-level/stage.nix: add static overlay 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. (cherry picked from commit 6d90a8b8948185a3118faf183f29f4b8de294675) --- pkgs/stdenv/darwin/portable-libsystem.sh | 10 ++ pkgs/top-level/stage.nix | 17 +++ pkgs/top-level/static.nix | 150 +++++++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 pkgs/stdenv/darwin/portable-libsystem.sh create mode 100644 pkgs/top-level/static.nix diff --git a/pkgs/stdenv/darwin/portable-libsystem.sh b/pkgs/stdenv/darwin/portable-libsystem.sh new file mode 100644 index 00000000000..27ae790fb5a --- /dev/null +++ b/pkgs/stdenv/darwin/portable-libsystem.sh @@ -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 {} \; +} diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index ff09fa5ad1f..69c87114318 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -160,6 +160,23 @@ let }; }; }; + + # 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. diff --git a/pkgs/top-level/static.nix b/pkgs/top-level/static.nix new file mode 100644 index 00000000000..687e38dcc3a --- /dev/null +++ b/pkgs/top-level/static.nix @@ -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; + }; + }; + +} From af2cebe78fd185d1bbabd071f85f74654602d042 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Wed, 5 Dec 2018 12:51:44 -0600 Subject: [PATCH 2/2] stdenv/darwin: fix portable libsystem hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some packages don’t have /bin directories. We should only run install_name_tool if that directory exists. (cherry picked from commit 0b8574540b8691924a8dac6dc4d03004d8b25efa) --- pkgs/stdenv/darwin/portable-libsystem.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/stdenv/darwin/portable-libsystem.sh b/pkgs/stdenv/darwin/portable-libsystem.sh index 27ae790fb5a..f50ccc8d32e 100644 --- a/pkgs/stdenv/darwin/portable-libsystem.sh +++ b/pkgs/stdenv/darwin/portable-libsystem.sh @@ -5,6 +5,8 @@ fixupOutputHooks+=('fixLibsystemRefs $prefix') fixLibsystemRefs() { - find "$1/bin" \ - -exec install_name_tool -change @libsystem@ /usr/lib/libSystem.B.dylib {} \; + if [ -d "$1/bin" ]; then + find "$1/bin" -exec \ + install_name_tool -change @libsystem@ /usr/lib/libSystem.B.dylib {} \; + fi }