about summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/build-support')
-rw-r--r--pkgs/build-support/appimage/default.nix176
-rw-r--r--pkgs/build-support/bintools-wrapper/default.nix4
-rw-r--r--pkgs/build-support/build-bazel-package/default.nix41
-rw-r--r--pkgs/build-support/build-fhs-userenv/env.nix1
-rwxr-xr-xpkgs/build-support/buildenv/builder.pl12
-rw-r--r--pkgs/build-support/buildenv/default.nix12
-rw-r--r--pkgs/build-support/cc-wrapper/default.nix18
-rw-r--r--pkgs/build-support/closure-info.nix2
-rw-r--r--pkgs/build-support/docker/default.nix19
-rw-r--r--pkgs/build-support/fetchsvn/default.nix2
-rw-r--r--pkgs/build-support/nix-prefetch-github/default.nix6
-rw-r--r--pkgs/build-support/release/ant-build.nix2
-rw-r--r--pkgs/build-support/rust/build-rust-crate/build-crate.nix10
-rw-r--r--pkgs/build-support/rust/build-rust-crate/configure-crate.nix24
-rw-r--r--pkgs/build-support/rust/build-rust-crate/default.nix11
-rw-r--r--pkgs/build-support/rust/carnix.nix25
-rw-r--r--pkgs/build-support/rust/crates-io.nix264
-rw-r--r--pkgs/build-support/setup-hooks/fix-darwin-dylib-names.sh9
-rw-r--r--pkgs/build-support/setup-hooks/wrap-gapps-hook.sh28
-rw-r--r--pkgs/build-support/singularity-tools/default.nix3
-rw-r--r--pkgs/build-support/skaware/build-skaware-package.nix42
-rw-r--r--pkgs/build-support/skaware/clean-packaging.nix53
-rw-r--r--pkgs/build-support/substitute-files/substitute-all-files.nix1
-rw-r--r--pkgs/build-support/substitute/substitute-all.nix1
-rw-r--r--pkgs/build-support/trivial-builders.nix14
-rw-r--r--pkgs/build-support/vm/default.nix2
-rw-r--r--pkgs/build-support/vm/windows/controller/default.nix3
27 files changed, 707 insertions, 78 deletions
diff --git a/pkgs/build-support/appimage/default.nix b/pkgs/build-support/appimage/default.nix
new file mode 100644
index 000000000000..ef7da72fda93
--- /dev/null
+++ b/pkgs/build-support/appimage/default.nix
@@ -0,0 +1,176 @@
+{ pkgs, stdenv, libarchive, patchelf, zlib, buildFHSUserEnv, writeScript }:
+
+rec {
+  # Both extraction functions could be unified, but then
+  # it would depend on libmagic to correctly identify ISO 9660s
+
+  extractType1 = { name, src }: stdenv.mkDerivation {
+    name = "${name}-extracted";
+    inherit src;
+
+    nativeBuildInputs = [ libarchive ];
+    buildCommand = ''
+      mkdir $out
+      bsdtar -x -C $out -f $src
+    '';
+  };
+
+  extractType2 = { name, src }: stdenv.mkDerivation {
+    name = "${name}-extracted";
+    inherit src;
+
+    nativeBuildInputs = [ patchelf ];
+    buildCommand = ''
+      install $src ./appimage
+      patchelf \
+        --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
+        --replace-needed libz.so.1 ${zlib}/lib/libz.so.1 \
+        ./appimage
+
+      ./appimage --appimage-extract
+
+      cp -rv squashfs-root $out
+    '';
+  };
+
+  wrapAppImage = { name, src, extraPkgs }: buildFHSUserEnv (defaultFhsEnvArgs // {
+    inherit name;
+
+    targetPkgs = pkgs: defaultFhsEnvArgs.targetPkgs pkgs ++ extraPkgs pkgs;
+
+    runScript = writeScript "run" ''
+      #!${stdenv.shell}
+
+      export APPDIR=${src}
+      export APPIMAGE_SILENT_INSTALL=1
+      cd $APPDIR
+      exec ./AppRun "$@"
+    '';
+  });
+
+  wrapType1 = args@{ name, src, extraPkgs ? pkgs: [] }: wrapAppImage {
+    inherit name extraPkgs;
+    src = extractType1 { inherit name src; };
+  };
+
+  wrapType2 = args@{ name, src, extraPkgs ? pkgs: [] }: wrapAppImage {
+    inherit name extraPkgs;
+    src = extractType2 { inherit name src; };
+  };
+
+  defaultFhsEnvArgs = {
+    name = "appimage-env";
+
+    # Most of the packages were taken from the Steam chroot
+    targetPkgs = pkgs: with pkgs; [
+      gtk3
+      bashInteractive
+      gnome3.zenity
+      python2
+      xorg.xrandr
+      which
+      perl
+      xdg_utils
+      iana-etc
+      krb5
+    ];
+
+    multiPkgs = pkgs: with pkgs; [
+      desktop-file-utils
+      xorg.libXcomposite
+      xorg.libXtst
+      xorg.libXrandr
+      xorg.libXext
+      xorg.libX11
+      xorg.libXfixes
+      libGL
+
+      gst_all_1.gstreamer
+      gst_all_1.gst-plugins-ugly
+      libdrm
+      xorg.xkeyboardconfig
+      xorg.libpciaccess
+
+      glib
+      gtk2
+      bzip2
+      zlib
+      gdk_pixbuf
+
+      xorg.libXinerama
+      xorg.libXdamage
+      xorg.libXcursor
+      xorg.libXrender
+      xorg.libXScrnSaver
+      xorg.libXxf86vm
+      xorg.libXi
+      xorg.libSM
+      xorg.libICE
+      gnome2.GConf
+      freetype
+      (curl.override { gnutlsSupport = true; sslSupport = false; })
+      nspr
+      nss
+      fontconfig
+      cairo
+      pango
+      expat
+      dbus
+      cups
+      libcap
+      SDL2
+      libusb1
+      udev
+      dbus-glib
+      libav
+      atk
+      at-spi2-atk
+      libudev0-shim
+      networkmanager098
+
+      xorg.libXt
+      xorg.libXmu
+      xorg.libxcb
+      libGLU
+      libuuid
+      libogg
+      libvorbis
+      SDL
+      SDL2_image
+      glew110
+      openssl
+      libidn
+      tbb
+      wayland
+      mesa_noglu
+      libxkbcommon
+
+      flac
+      freeglut
+      libjpeg
+      libpng12
+      libsamplerate
+      libmikmod
+      libtheora
+      libtiff
+      pixman
+      speex
+      SDL_image
+      SDL_ttf
+      SDL_mixer
+      SDL2_ttf
+      SDL2_mixer
+      gstreamer
+      gst-plugins-base
+      libappindicator-gtk2
+      libcaca
+      libcanberra
+      libgcrypt
+      libvpx
+      librsvg
+      xorg.libXft
+      libvdpau
+      alsaLib
+    ];
+  };
+}
diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix
index 03ba54525bf7..98d43c01ba06 100644
--- a/pkgs/build-support/bintools-wrapper/default.nix
+++ b/pkgs/build-support/bintools-wrapper/default.nix
@@ -53,6 +53,7 @@ let
     /**/ if libc == null then null
     else if targetPlatform.libc == "musl"             then "${libc_lib}/lib/ld-musl-*"
     else if targetPlatform.libc == "bionic"           then "/system/bin/linker"
+    else if targetPlatform.libc == "nblibc"           then "${libc_lib}/libexec/ld.elf_so"
     else if targetPlatform.system == "i686-linux"     then "${libc_lib}/lib/ld-linux.so.2"
     else if targetPlatform.system == "x86_64-linux"   then "${libc_lib}/lib/ld-linux-x86-64.so.2"
     # ARM with a wildcard, which can be "" or "-armhf".
@@ -187,7 +188,8 @@ stdenv.mkDerivation {
       else if targetPlatform.isPower then if targetPlatform.isBigEndian then "ppc" else "lppc"
       else if targetPlatform.isSparc then "sparc"
       else if targetPlatform.isAvr then "avr"
-      else throw "unknown emulation for platform: " + targetPlatform.config;
+      else if targetPlatform.isAlpha then "alpha"
+      else throw "unknown emulation for platform: ${targetPlatform.config}";
     in targetPlatform.platform.bfdEmulation or (fmt + sep + arch);
 
   strictDeps = true;
diff --git a/pkgs/build-support/build-bazel-package/default.nix b/pkgs/build-support/build-bazel-package/default.nix
index 931b68c6329f..f39f4e65e454 100644
--- a/pkgs/build-support/build-bazel-package/default.nix
+++ b/pkgs/build-support/build-bazel-package/default.nix
@@ -33,7 +33,9 @@ in stdenv.mkDerivation (fBuildAttrs // {
       # sandbox enabled. Code here
       # https://github.com/bazelbuild/bazel/blob/9323c57607d37f9c949b60e293b573584906da46/src/main/cpp/startup_options.cc#L123-L124
       #
-      USER=homeless-shelter bazel --output_base="$bazelOut" --output_user_root="$bazelUserRoot" fetch $bazelFlags $bazelTarget
+      # On macOS Bazel will use the system installed Xcode or CLT toolchain instead of the one in the PATH unless we pass BAZEL_USE_CPP_ONLY_TOOLCHAIN
+      #
+      BAZEL_USE_CPP_ONLY_TOOLCHAIN=1 USER=homeless-shelter bazel --output_base="$bazelOut" --output_user_root="$bazelUserRoot" fetch $bazelFlags $bazelTarget
 
       runHook postBuild
     '';
@@ -90,7 +92,42 @@ in stdenv.mkDerivation (fBuildAttrs // {
   buildPhase = fBuildAttrs.buildPhase or ''
     runHook preBuild
 
-    bazel --output_base="$bazelOut" --output_user_root="$bazelUserRoot" build -j $NIX_BUILD_CORES $bazelFlags $bazelTarget
+    # Bazel sandboxes the execution of the tools it invokes, so even though we are
+    # calling the correct nix wrappers, the values of the environment variables
+    # the wrappers are expecting will not be set. So instead of relying on the
+    # wrappers picking them up, pass them in explicitly via `--copt`, `--linkopt`
+    # and related flags.
+    #
+    copts=()
+    host_copts=()
+    for flag in $NIX_CFLAGS_COMPILE; do
+      copts+=( "--copt=$flag" )
+      host_copts+=( "--host_copt=$flag" )
+    done
+    for flag in $NIX_CXXSTDLIB_COMPILE; do
+      copts+=( "--copt=$flag" )
+      host_copts+=( "--host_copt=$flag" )
+    done
+    linkopts=()
+    host_linkopts=()
+    for flag in $NIX_LD_FLAGS; do
+      linkopts+=( "--linkopt=$flag" )
+      host_linkopts+=( "--host_linkopt=$flag" )
+    done
+
+    BAZEL_USE_CPP_ONLY_TOOLCHAIN=1 \
+    USER=homeless-shelter \
+    bazel \
+      --output_base="$bazelOut" \
+      --output_user_root="$bazelUserRoot" \
+      build \
+      -j $NIX_BUILD_CORES \
+      "''${copts[@]}" \
+      "''${host_copts[@]}" \
+      "''${linkopts[@]}" \
+      "''${host_linkopts[@]}" \
+      $bazelFlags \
+      $bazelTarget
 
     runHook postBuild
   '';
diff --git a/pkgs/build-support/build-fhs-userenv/env.nix b/pkgs/build-support/build-fhs-userenv/env.nix
index 23568f51b23e..c0f741b62886 100644
--- a/pkgs/build-support/build-fhs-userenv/env.nix
+++ b/pkgs/build-support/build-fhs-userenv/env.nix
@@ -196,4 +196,5 @@ in stdenv.mkDerivation {
     ${if isMultiBuild then extraBuildCommandsMulti else ""}
   '';
   preferLocalBuild = true;
+  allowSubstitutes = false;
 }
diff --git a/pkgs/build-support/buildenv/builder.pl b/pkgs/build-support/buildenv/builder.pl
index 678f5a3fe9e6..b699d762d29c 100755
--- a/pkgs/build-support/buildenv/builder.pl
+++ b/pkgs/build-support/buildenv/builder.pl
@@ -26,6 +26,13 @@ sub isInPathsToLink {
     return 0;
 }
 
+# Similar to `lib.isStorePath`
+sub isStorePath {
+    my $path = shift;
+    my $storePath = "@storeDir@";
+
+    return substr($path, 0, 1) eq "/" && dirname($path) eq $storePath;
+}
 
 # For each activated package, determine what symlinks to create.
 
@@ -84,6 +91,11 @@ sub checkCollision {
 sub findFiles {
     my ($relName, $target, $baseName, $ignoreCollisions, $checkCollisionContents, $priority) = @_;
 
+    # The store path must not be a file
+    if (-f $target && isStorePath $target) {
+        die "The store path $target is a file and can't be merged into an environment using pkgs.buildEnv!";
+    }
+
     # Urgh, hacky...
     return if
         $relName eq "/propagated-build-inputs" ||
diff --git a/pkgs/build-support/buildenv/default.nix b/pkgs/build-support/buildenv/default.nix
index 41a1e67ef428..7f2427777f92 100644
--- a/pkgs/build-support/buildenv/default.nix
+++ b/pkgs/build-support/buildenv/default.nix
@@ -2,7 +2,7 @@
 # a fork of the buildEnv in the Nix distribution.  Most changes should
 # eventually be merged back into the Nix distribution.
 
-{ buildPackages, runCommand, lib }:
+{ buildPackages, runCommand, lib, substituteAll }:
 
 lib.makeOverridable
 ({ name
@@ -43,6 +43,13 @@ lib.makeOverridable
 , meta ? {}
 }:
 
+let
+  builder = substituteAll {
+    src = ./builder.pl;
+    inherit (builtins) storeDir;
+  };
+in
+
 runCommand name
   rec {
     inherit manifest ignoreCollisions checkCollisionContents passthru
@@ -63,10 +70,11 @@ runCommand name
       priority = drv.meta.priority or 5;
     }) paths);
     preferLocalBuild = true;
+    allowSubstitutes = false;
     # XXX: The size is somewhat arbitrary
     passAsFile = if builtins.stringLength pkgs >= 128*1024 then [ "pkgs" ] else null;
   }
   ''
-    ${buildPackages.perl}/bin/perl -w ${./builder.pl}
+    ${buildPackages.perl}/bin/perl -w ${builder}
     eval "$postBuild"
   '')
diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix
index c36181130478..f05b9fb22555 100644
--- a/pkgs/build-support/cc-wrapper/default.nix
+++ b/pkgs/build-support/cc-wrapper/default.nix
@@ -13,6 +13,7 @@
 , extraPackages ? [], extraBuildCommands ? ""
 , isGNU ? false, isClang ? cc.isClang or false, gnugrep ? null
 , buildPackages ? {}
+, libcxx ? null
 }:
 
 with stdenvNoCC.lib;
@@ -44,8 +45,11 @@ let
   # The wrapper scripts use 'cat' and 'grep', so we may need coreutils.
   coreutils_bin = if nativeTools then "" else getBin coreutils;
 
-  default_cxx_stdlib_compile = optionalString (targetPlatform.isLinux && !(cc.isGNU or false) && !nativeTools && cc ? gcc)
-    "-isystem $(echo -n ${cc.gcc}/include/c++/*) -isystem $(echo -n ${cc.gcc}/include/c++/*)/$(${cc.gcc}/bin/gcc -dumpmachine)";
+  default_cxx_stdlib_compile = if (targetPlatform.isLinux && !(cc.isGNU or false) && !nativeTools && cc ? gcc) then
+    "-isystem $(echo -n ${cc.gcc}/include/c++/*) -isystem $(echo -n ${cc.gcc}/include/c++/*)/$(${cc.gcc}/bin/gcc -dumpmachine)"
+  else if targetPlatform.isDarwin && (libcxx != null) && (cc.isClang or false) then
+    "-isystem ${libcxx}/include/c++/v1"
+  else "";
 
   # The "infix salt" is a arbitrary string added in the middle of env vars
   # defined by cc-wrapper's hooks so that multiple cc-wrappers can be used
@@ -256,9 +260,9 @@ stdenv.mkDerivation {
 
       echo "$ccLDFlags" > $out/nix-support/cc-ldflags
       echo "$ccCFlags" > $out/nix-support/cc-cflags
-    ''
-
-    + optionalString propagateDoc ''
+    '' + optionalString (targetPlatform.isDarwin && (libcxx != null) && (cc.isClang or false)) ''
+      echo " -L${libcxx}/lib" >> $out/nix-support/cc-ldflags
+    '' + optionalString propagateDoc ''
       ##
       ## Man page and info support
       ##
@@ -287,6 +291,10 @@ stdenv.mkDerivation {
       hardening_unsupported_flags+=" stackprotector pic"
     ''
 
+    + optionalString targetPlatform.isNetBSD ''
+      hardening_unsupported_flags+=" stackprotector fortify"
+    ''
+
     + optionalString (targetPlatform.libc == "newlib") ''
       hardening_unsupported_flags+=" stackprotector fortify pie pic"
     ''
diff --git a/pkgs/build-support/closure-info.nix b/pkgs/build-support/closure-info.nix
index 28f2802a5bce..24795a724ec8 100644
--- a/pkgs/build-support/closure-info.nix
+++ b/pkgs/build-support/closure-info.nix
@@ -17,6 +17,8 @@ stdenv.mkDerivation {
 
   exportReferencesGraph.closure = rootPaths;
 
+  preferLocalBuild = true;
+
   PATH = "${buildPackages.coreutils}/bin:${buildPackages.jq}/bin";
 
   builder = builtins.toFile "builder"
diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix
index f59900ab7596..011ff3685093 100644
--- a/pkgs/build-support/docker/default.nix
+++ b/pkgs/build-support/docker/default.nix
@@ -22,7 +22,9 @@
   referencesByPopularity,
   writeScript,
   writeText,
-  closureInfo
+  closureInfo,
+  substituteAll,
+  runtimeShell
 }:
 
 # WARNING: this API is unstable and may be subject to backwards-incompatible changes in the future.
@@ -118,7 +120,7 @@ rec {
     export PATH=${shadow}/bin:$PATH
     mkdir -p /etc/pam.d
     if [[ ! -f /etc/passwd ]]; then
-      echo "root:x:0:0::/root:${stdenv.shell}" > /etc/passwd
+      echo "root:x:0:0::/root:${runtimeShell}" > /etc/passwd
       echo "root:!x:::::::" > /etc/shadow
     fi
     if [[ ! -f /etc/group ]]; then
@@ -260,7 +262,7 @@ rec {
   # things like `ls` or `echo` will be missing.
   shellScript = name: text:
     writeScript name ''
-      #!${stdenv.shell}
+      #!${runtimeShell}
       set -e
       export PATH=${coreutils}/bin:/bin
       ${text}
@@ -279,6 +281,13 @@ rec {
     # of room for extension
     maxLayers ? 24
   }:
+    let
+      storePathToLayer = substituteAll
+      { inherit (stdenv) shell;
+        isExecutable = true;
+        src = ./store-path-to-layer.sh;
+      };
+    in
     runCommand "${name}-granular-docker-layers" {
       inherit maxLayers;
       paths = referencesByPopularity closure;
@@ -298,9 +307,9 @@ rec {
       # following head and tail call lines, double-check that your
       # code behaves properly when the number of layers equals:
       #      maxLayers-1, maxLayers, and maxLayers+1
-      head -n $((maxLayers - 1)) $paths | cat -n | xargs -P$NIX_BUILD_CORES -n2 ${./store-path-to-layer.sh}
+      head -n $((maxLayers - 1)) $paths | cat -n | xargs -P$NIX_BUILD_CORES -n2 ${storePathToLayer}
       if [ $(cat $paths | wc -l) -ge $maxLayers ]; then
-        tail -n+$maxLayers $paths | xargs ${./store-path-to-layer.sh} $maxLayers
+        tail -n+$maxLayers $paths | xargs ${storePathToLayer} $maxLayers
       fi
 
       echo "Finished building layer '$name'"
diff --git a/pkgs/build-support/fetchsvn/default.nix b/pkgs/build-support/fetchsvn/default.nix
index 194ce3b39b1d..68433d1471d6 100644
--- a/pkgs/build-support/fetchsvn/default.nix
+++ b/pkgs/build-support/fetchsvn/default.nix
@@ -1,4 +1,4 @@
-{stdenvNoCC, subversion, glibcLocales, sshSupport ? false, openssh ? null}:
+{stdenvNoCC, subversion, glibcLocales, sshSupport ? true, openssh ? null}:
 {url, rev ? "HEAD", md5 ? "", sha256 ? ""
 , ignoreExternals ? false, ignoreKeywords ? false, name ? null
 , preferLocalBuild ? true }:
diff --git a/pkgs/build-support/nix-prefetch-github/default.nix b/pkgs/build-support/nix-prefetch-github/default.nix
index 48297e583afe..acc95eaf993f 100644
--- a/pkgs/build-support/nix-prefetch-github/default.nix
+++ b/pkgs/build-support/nix-prefetch-github/default.nix
@@ -5,13 +5,13 @@
 
 python3.pkgs.buildPythonApplication rec {
   pname = "nix-prefetch-github";
-  version = "1.3";
+  version = "2.2";
 
   src = fetchFromGitHub {
     owner = "seppeljordan";
     repo = "nix-prefetch-github";
-    rev = "${version}";
-    sha256 = "1rinbv1q4q8m27ih6l81w1lsmwn6cz7q3iyjiycklywpi8684dh6";
+    rev = "v${version}";
+    sha256 = "1m1d1fzacvwprfvhxih1hzr1m0y1jjxiznf8p8b3bi5a41yzvrrl";
   };
 
   propagatedBuildInputs = with python3.pkgs; [
diff --git a/pkgs/build-support/release/ant-build.nix b/pkgs/build-support/release/ant-build.nix
index 5ab24132290a..2d24d5bd7041 100644
--- a/pkgs/build-support/release/ant-build.nix
+++ b/pkgs/build-support/release/ant-build.nix
@@ -69,7 +69,7 @@ stdenv.mkDerivation (
 
       mkdir -p $out/bin
       cat >> $out/bin/${w.name} <<EOF
-      #!${stdenv.shell}
+      #!${pkgs.runtimeShell}
       export JAVA_HOME=$jre
       $jre/bin/java ${cp w} ${if w ? mainClass then w.mainClass else "-jar ${w.jar}"} \$@
       EOF
diff --git a/pkgs/build-support/rust/build-rust-crate/build-crate.nix b/pkgs/build-support/rust/build-rust-crate/build-crate.nix
index 252a0ff521fd..0978f7e1756f 100644
--- a/pkgs/build-support/rust/build-rust-crate/build-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate/build-crate.nix
@@ -8,11 +8,11 @@
   let
 
     deps = makeDeps dependencies;
-        rustcOpts =
-          lib.lists.foldl' (opts: opt: opts + " " + opt)
-            (if release then "-C opt-level=3" else "-C debuginfo=2")
-            (["-C codegen-units=1"] ++ extraRustcOpts);
-        rustcMeta = "-C metadata=${metadata} -C extra-filename=-${metadata}";
+    rustcOpts =
+      lib.lists.foldl' (opts: opt: opts + " " + opt)
+        (if release then "-C opt-level=3" else "-C debuginfo=2")
+        (["-C codegen-units=1"] ++ extraRustcOpts);
+    rustcMeta = "-C metadata=${metadata} -C extra-filename=-${metadata}";
 
     # Some platforms have different names for rustc.
     rustPlatform =
diff --git a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
index 7630c6471dcd..9f499e4f5e72 100644
--- a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
@@ -1,9 +1,28 @@
 { lib, stdenv, echo_build_heading, noisily, makeDeps }:
-{ build, buildDependencies, colors, completeBuildDeps, completeDeps, crateAuthors, crateFeatures, crateName, crateVersion, extraLinkFlags, libName, libPath, release, target_os, verbose, workspace_member }:
+{ build
+, buildDependencies
+, colors
+, completeBuildDeps
+, completeDeps
+, crateAuthors
+, crateDescription
+, crateFeatures
+, crateName
+, crateVersion
+, extraLinkFlags
+, extraRustcOpts
+, libName
+, libPath
+, release
+, target_os
+, verbose
+, workspace_member }:
 let version_ = lib.splitString "-" crateVersion;
     versionPre = if lib.tail version_ == [] then "" else builtins.elemAt version_ 1;
     version = lib.splitString "." (lib.head version_);
-    rustcOpts = (if release then "-C opt-level=3" else "-C debuginfo=2");
+    rustcOpts = lib.lists.foldl' (opts: opt: opts + " " + opt)
+        (if release then "-C opt-level=3" else "-C debuginfo=2")
+        (["-C codegen-units=1"] ++ extraRustcOpts);
     buildDeps = makeDeps buildDependencies;
     authors = lib.concatStringsSep ":" crateAuthors;
     optLevel = if release then 3 else 0;
@@ -51,6 +70,7 @@ in ''
   export CARGO_PKG_NAME=${crateName}
   export CARGO_PKG_VERSION=${crateVersion}
   export CARGO_PKG_AUTHORS="${authors}"
+  export CARGO_PKG_DESCRIPTION="${crateDescription}"
 
   export CARGO_CFG_TARGET_ARCH=${stdenv.hostPlatform.parsed.cpu.name}
   export CARGO_CFG_TARGET_OS=${target_os}
diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix
index dbb2f1b80cc9..81e8a7ca0afa 100644
--- a/pkgs/build-support/rust/build-rust-crate/default.nix
+++ b/pkgs/build-support/rust/build-rust-crate/default.nix
@@ -71,7 +71,7 @@ let crate = crate_ // (lib.attrByPath [ crate_.crateName ] (attr: {}) crateOverr
     processedAttrs = [
       "src" "buildInputs" "crateBin" "crateLib" "libName" "libPath"
       "buildDependencies" "dependencies" "features"
-      "crateName" "version" "build" "authors" "colors"
+      "crateName" "version" "build" "authors" "colors" "edition"
     ];
     extraDerivationAttrs = lib.filterAttrs (n: v: ! lib.elem n processedAttrs) crate;
     buildInputs_ = buildInputs;
@@ -129,6 +129,7 @@ stdenv.mkDerivation (rec {
     build = crate.build or "";
     workspace_member = crate.workspace_member or ".";
     crateVersion = crate.version;
+    crateDescription = crate.description or "";
     crateAuthors = if crate ? authors && lib.isList crate.authors then crate.authors else [];
     crateType =
       if lib.attrByPath ["procMacro"] false crate then ["proc-macro"] else
@@ -136,13 +137,15 @@ stdenv.mkDerivation (rec {
         (crate.type or ["lib"]);
     colors = lib.attrByPath [ "colors" ] "always" crate;
     extraLinkFlags = builtins.concatStringsSep " " (crate.extraLinkFlags or []);
+    edition = crate.edition or null;
+    extraRustcOpts = (if crate ? extraRustcOpts then crate.extraRustcOpts else []) ++ extraRustcOpts_ ++ (lib.optional (edition != null) "--edition ${edition}");
+
     configurePhase = configureCrate {
-      inherit crateName buildDependencies completeDeps completeBuildDeps
+      inherit crateName buildDependencies completeDeps completeBuildDeps crateDescription
               crateFeatures libName build workspace_member release libPath crateVersion
-              extraLinkFlags
+              extraLinkFlags extraRustcOpts
               crateAuthors verbose colors target_os;
     };
-    extraRustcOpts = (if crate ? extraRustcOpts then crate.extraRustcOpts else []) ++ extraRustcOpts_;
     buildPhase = buildCrate {
       inherit crateName dependencies
               crateFeatures libName release libPath crateType
diff --git a/pkgs/build-support/rust/carnix.nix b/pkgs/build-support/rust/carnix.nix
index dd44fed623ed..ef69f90c3669 100644
--- a/pkgs/build-support/rust/carnix.nix
+++ b/pkgs/build-support/rust/carnix.nix
@@ -1,12 +1,12 @@
-# Generated by carnix 0.9.1: carnix generate-nix
+# Generated by carnix 0.9.8: carnix generate-nix
 { lib, buildPlatform, buildRustCrate, buildRustCrateHelpers, cratesIO, fetchgit }:
 with buildRustCrateHelpers;
 let inherit (lib.lists) fold;
     inherit (lib.attrsets) recursiveUpdate;
 in
-let crates = cratesIO; in
 rec {
-  carnix = crates.crates.carnix."0.9.2" deps;
+  crates = cratesIO;
+  carnix = crates.crates.carnix."0.9.8" deps;
   __all = [ (carnix {}) ];
   deps.aho_corasick."0.6.8" = {
     memchr = "2.1.0";
@@ -42,7 +42,7 @@ rec {
     arrayvec = "0.4.7";
     constant_time_eq = "0.1.3";
   };
-  deps.carnix."0.9.2" = {
+  deps.carnix."0.9.8" = {
     clap = "2.32.0";
     dirs = "1.0.4";
     env_logger = "0.5.13";
@@ -56,6 +56,7 @@ rec {
     serde_json = "1.0.32";
     tempdir = "0.3.7";
     toml = "0.4.8";
+    url = "1.7.2";
   };
   deps.cc."1.0.25" = {};
   deps.cfg_if."0.1.6" = {};
@@ -103,6 +104,11 @@ rec {
   deps.humantime."1.1.1" = {
     quick_error = "1.2.2";
   };
+  deps.idna."0.1.5" = {
+    matches = "0.1.8";
+    unicode_bidi = "0.3.4";
+    unicode_normalization = "0.1.7";
+  };
   deps.itertools."0.7.8" = {
     either = "1.5.0";
   };
@@ -114,6 +120,7 @@ rec {
   deps.log."0.4.5" = {
     cfg_if = "0.1.6";
   };
+  deps.matches."0.1.8" = {};
   deps.memchr."1.0.2" = {
     libc = "0.2.43";
   };
@@ -126,6 +133,7 @@ rec {
   deps.nom."3.2.1" = {
     memchr = "1.0.2";
   };
+  deps.percent_encoding."1.0.1" = {};
   deps.proc_macro2."0.4.20" = {
     unicode_xid = "0.1.0";
   };
@@ -209,8 +217,17 @@ rec {
     serde = "1.0.80";
   };
   deps.ucd_util."0.1.1" = {};
+  deps.unicode_bidi."0.3.4" = {
+    matches = "0.1.8";
+  };
+  deps.unicode_normalization."0.1.7" = {};
   deps.unicode_width."0.1.5" = {};
   deps.unicode_xid."0.1.0" = {};
+  deps.url."1.7.2" = {
+    idna = "0.1.5";
+    matches = "0.1.8";
+    percent_encoding = "1.0.1";
+  };
   deps.utf8_ranges."1.0.1" = {};
   deps.vec_map."0.8.1" = {};
   deps.version_check."0.1.5" = {};
diff --git a/pkgs/build-support/rust/crates-io.nix b/pkgs/build-support/rust/crates-io.nix
index f312cd6e4903..3521f0997bd3 100644
--- a/pkgs/build-support/rust/crates-io.nix
+++ b/pkgs/build-support/rust/crates-io.nix
@@ -338,6 +338,65 @@ rec {
 
 
 # end
+# carnix-0.9.1
+
+  crates.carnix."0.9.1" = deps: { features?(features_.carnix."0.9.1" deps {}) }: buildRustCrate {
+    crateName = "carnix";
+    version = "0.9.1";
+    authors = [ "pe@pijul.org <pe@pijul.org>" ];
+    sha256 = "0dn292d4mjlxif0kclrljzff8rm35cd9d92vycjbzklyhz5d62wi";
+    crateBin =
+      [{  name = "cargo-generate-nixfile";  path = "src/cargo-generate-nixfile.rs"; }] ++
+      [{  name = "carnix";  path = "src/main.rs"; }];
+    dependencies = mapFeatures features ([
+      (crates."clap"."${deps."carnix"."0.9.1"."clap"}" deps)
+      (crates."dirs"."${deps."carnix"."0.9.1"."dirs"}" deps)
+      (crates."env_logger"."${deps."carnix"."0.9.1"."env_logger"}" deps)
+      (crates."error_chain"."${deps."carnix"."0.9.1"."error_chain"}" deps)
+      (crates."itertools"."${deps."carnix"."0.9.1"."itertools"}" deps)
+      (crates."log"."${deps."carnix"."0.9.1"."log"}" deps)
+      (crates."nom"."${deps."carnix"."0.9.1"."nom"}" deps)
+      (crates."regex"."${deps."carnix"."0.9.1"."regex"}" deps)
+      (crates."serde"."${deps."carnix"."0.9.1"."serde"}" deps)
+      (crates."serde_derive"."${deps."carnix"."0.9.1"."serde_derive"}" deps)
+      (crates."serde_json"."${deps."carnix"."0.9.1"."serde_json"}" deps)
+      (crates."tempdir"."${deps."carnix"."0.9.1"."tempdir"}" deps)
+      (crates."toml"."${deps."carnix"."0.9.1"."toml"}" deps)
+    ]);
+  };
+  features_.carnix."0.9.1" = deps: f: updateFeatures f (rec {
+    carnix."0.9.1".default = (f.carnix."0.9.1".default or true);
+    clap."${deps.carnix."0.9.1".clap}".default = true;
+    dirs."${deps.carnix."0.9.1".dirs}".default = true;
+    env_logger."${deps.carnix."0.9.1".env_logger}".default = true;
+    error_chain."${deps.carnix."0.9.1".error_chain}".default = true;
+    itertools."${deps.carnix."0.9.1".itertools}".default = true;
+    log."${deps.carnix."0.9.1".log}".default = true;
+    nom."${deps.carnix."0.9.1".nom}".default = true;
+    regex."${deps.carnix."0.9.1".regex}".default = true;
+    serde."${deps.carnix."0.9.1".serde}".default = true;
+    serde_derive."${deps.carnix."0.9.1".serde_derive}".default = true;
+    serde_json."${deps.carnix."0.9.1".serde_json}".default = true;
+    tempdir."${deps.carnix."0.9.1".tempdir}".default = true;
+    toml."${deps.carnix."0.9.1".toml}".default = true;
+  }) [
+    (features_.clap."${deps."carnix"."0.9.1"."clap"}" deps)
+    (features_.dirs."${deps."carnix"."0.9.1"."dirs"}" deps)
+    (features_.env_logger."${deps."carnix"."0.9.1"."env_logger"}" deps)
+    (features_.error_chain."${deps."carnix"."0.9.1"."error_chain"}" deps)
+    (features_.itertools."${deps."carnix"."0.9.1"."itertools"}" deps)
+    (features_.log."${deps."carnix"."0.9.1"."log"}" deps)
+    (features_.nom."${deps."carnix"."0.9.1"."nom"}" deps)
+    (features_.regex."${deps."carnix"."0.9.1"."regex"}" deps)
+    (features_.serde."${deps."carnix"."0.9.1"."serde"}" deps)
+    (features_.serde_derive."${deps."carnix"."0.9.1"."serde_derive"}" deps)
+    (features_.serde_json."${deps."carnix"."0.9.1"."serde_json"}" deps)
+    (features_.tempdir."${deps."carnix"."0.9.1"."tempdir"}" deps)
+    (features_.toml."${deps."carnix"."0.9.1"."toml"}" deps)
+  ];
+
+
+# end
 # carnix-0.9.2
 
   crates.carnix."0.9.2" = deps: { features?(features_.carnix."0.9.2" deps {}) }: buildRustCrate {
@@ -397,6 +456,68 @@ rec {
 
 
 # end
+# carnix-0.9.8
+
+  crates.carnix."0.9.8" = deps: { features?(features_.carnix."0.9.8" deps {}) }: buildRustCrate {
+    crateName = "carnix";
+    version = "0.9.8";
+    authors = [ "pe@pijul.org <pe@pijul.org>" ];
+    sha256 = "0c2k98qjm1yyx5wl0wqs0rrjczp6h62ri1x8a99442clxsyvp4n9";
+    crateBin =
+      [{  name = "cargo-generate-nixfile";  path = "src/cargo-generate-nixfile.rs"; }] ++
+      [{  name = "carnix";  path = "src/main.rs"; }];
+    dependencies = mapFeatures features ([
+      (crates."clap"."${deps."carnix"."0.9.8"."clap"}" deps)
+      (crates."dirs"."${deps."carnix"."0.9.8"."dirs"}" deps)
+      (crates."env_logger"."${deps."carnix"."0.9.8"."env_logger"}" deps)
+      (crates."error_chain"."${deps."carnix"."0.9.8"."error_chain"}" deps)
+      (crates."itertools"."${deps."carnix"."0.9.8"."itertools"}" deps)
+      (crates."log"."${deps."carnix"."0.9.8"."log"}" deps)
+      (crates."nom"."${deps."carnix"."0.9.8"."nom"}" deps)
+      (crates."regex"."${deps."carnix"."0.9.8"."regex"}" deps)
+      (crates."serde"."${deps."carnix"."0.9.8"."serde"}" deps)
+      (crates."serde_derive"."${deps."carnix"."0.9.8"."serde_derive"}" deps)
+      (crates."serde_json"."${deps."carnix"."0.9.8"."serde_json"}" deps)
+      (crates."tempdir"."${deps."carnix"."0.9.8"."tempdir"}" deps)
+      (crates."toml"."${deps."carnix"."0.9.8"."toml"}" deps)
+      (crates."url"."${deps."carnix"."0.9.8"."url"}" deps)
+    ]);
+  };
+  features_.carnix."0.9.8" = deps: f: updateFeatures f (rec {
+    carnix."0.9.8".default = (f.carnix."0.9.8".default or true);
+    clap."${deps.carnix."0.9.8".clap}".default = true;
+    dirs."${deps.carnix."0.9.8".dirs}".default = true;
+    env_logger."${deps.carnix."0.9.8".env_logger}".default = true;
+    error_chain."${deps.carnix."0.9.8".error_chain}".default = true;
+    itertools."${deps.carnix."0.9.8".itertools}".default = true;
+    log."${deps.carnix."0.9.8".log}".default = true;
+    nom."${deps.carnix."0.9.8".nom}".default = true;
+    regex."${deps.carnix."0.9.8".regex}".default = true;
+    serde."${deps.carnix."0.9.8".serde}".default = true;
+    serde_derive."${deps.carnix."0.9.8".serde_derive}".default = true;
+    serde_json."${deps.carnix."0.9.8".serde_json}".default = true;
+    tempdir."${deps.carnix."0.9.8".tempdir}".default = true;
+    toml."${deps.carnix."0.9.8".toml}".default = true;
+    url."${deps.carnix."0.9.8".url}".default = true;
+  }) [
+    (features_.clap."${deps."carnix"."0.9.8"."clap"}" deps)
+    (features_.dirs."${deps."carnix"."0.9.8"."dirs"}" deps)
+    (features_.env_logger."${deps."carnix"."0.9.8"."env_logger"}" deps)
+    (features_.error_chain."${deps."carnix"."0.9.8"."error_chain"}" deps)
+    (features_.itertools."${deps."carnix"."0.9.8"."itertools"}" deps)
+    (features_.log."${deps."carnix"."0.9.8"."log"}" deps)
+    (features_.nom."${deps."carnix"."0.9.8"."nom"}" deps)
+    (features_.regex."${deps."carnix"."0.9.8"."regex"}" deps)
+    (features_.serde."${deps."carnix"."0.9.8"."serde"}" deps)
+    (features_.serde_derive."${deps."carnix"."0.9.8"."serde_derive"}" deps)
+    (features_.serde_json."${deps."carnix"."0.9.8"."serde_json"}" deps)
+    (features_.tempdir."${deps."carnix"."0.9.8"."tempdir"}" deps)
+    (features_.toml."${deps."carnix"."0.9.8"."toml"}" deps)
+    (features_.url."${deps."carnix"."0.9.8"."url"}" deps)
+  ];
+
+
+# end
 # cc-1.0.25
 
   crates.cc."1.0.25" = deps: { features?(features_.cc."1.0.25" deps {}) }: buildRustCrate {
@@ -802,6 +923,32 @@ rec {
 
 
 # end
+# idna-0.1.5
+
+  crates.idna."0.1.5" = deps: { features?(features_.idna."0.1.5" deps {}) }: buildRustCrate {
+    crateName = "idna";
+    version = "0.1.5";
+    authors = [ "The rust-url developers" ];
+    sha256 = "1gwgl19rz5vzi67rrhamczhxy050f5ynx4ybabfapyalv7z1qmjy";
+    dependencies = mapFeatures features ([
+      (crates."matches"."${deps."idna"."0.1.5"."matches"}" deps)
+      (crates."unicode_bidi"."${deps."idna"."0.1.5"."unicode_bidi"}" deps)
+      (crates."unicode_normalization"."${deps."idna"."0.1.5"."unicode_normalization"}" deps)
+    ]);
+  };
+  features_.idna."0.1.5" = deps: f: updateFeatures f (rec {
+    idna."0.1.5".default = (f.idna."0.1.5".default or true);
+    matches."${deps.idna."0.1.5".matches}".default = true;
+    unicode_bidi."${deps.idna."0.1.5".unicode_bidi}".default = true;
+    unicode_normalization."${deps.idna."0.1.5".unicode_normalization}".default = true;
+  }) [
+    (features_.matches."${deps."idna"."0.1.5"."matches"}" deps)
+    (features_.unicode_bidi."${deps."idna"."0.1.5"."unicode_bidi"}" deps)
+    (features_.unicode_normalization."${deps."idna"."0.1.5"."unicode_normalization"}" deps)
+  ];
+
+
+# end
 # itertools-0.7.8
 
   crates.itertools."0.7.8" = deps: { features?(features_.itertools."0.7.8" deps {}) }: buildRustCrate {
@@ -927,6 +1074,21 @@ rec {
 
 
 # end
+# matches-0.1.8
+
+  crates.matches."0.1.8" = deps: { features?(features_.matches."0.1.8" deps {}) }: buildRustCrate {
+    crateName = "matches";
+    version = "0.1.8";
+    authors = [ "Simon Sapin <simon.sapin@exyr.org>" ];
+    sha256 = "03hl636fg6xggy0a26200xs74amk3k9n0908rga2szn68agyz3cv";
+    libPath = "lib.rs";
+  };
+  features_.matches."0.1.8" = deps: f: updateFeatures f (rec {
+    matches."0.1.8".default = (f.matches."0.1.8".default or true);
+  }) [];
+
+
+# end
 # memchr-1.0.2
 
   crates.memchr."1.0.2" = deps: { features?(features_.memchr."1.0.2" deps {}) }: buildRustCrate {
@@ -1094,6 +1256,21 @@ rec {
 
 
 # end
+# percent-encoding-1.0.1
+
+  crates.percent_encoding."1.0.1" = deps: { features?(features_.percent_encoding."1.0.1" deps {}) }: buildRustCrate {
+    crateName = "percent-encoding";
+    version = "1.0.1";
+    authors = [ "The rust-url developers" ];
+    sha256 = "04ahrp7aw4ip7fmadb0bknybmkfav0kk0gw4ps3ydq5w6hr0ib5i";
+    libPath = "lib.rs";
+  };
+  features_.percent_encoding."1.0.1" = deps: f: updateFeatures f (rec {
+    percent_encoding."1.0.1".default = (f.percent_encoding."1.0.1".default or true);
+  }) [];
+
+
+# end
 # proc-macro2-0.4.20
 
   crates.proc_macro2."0.4.20" = deps: { features?(features_.proc_macro2."0.4.20" deps {}) }: buildRustCrate {
@@ -1850,6 +2027,56 @@ rec {
 
 
 # end
+# unicode-bidi-0.3.4
+
+  crates.unicode_bidi."0.3.4" = deps: { features?(features_.unicode_bidi."0.3.4" deps {}) }: buildRustCrate {
+    crateName = "unicode-bidi";
+    version = "0.3.4";
+    authors = [ "The Servo Project Developers" ];
+    sha256 = "0lcd6jasrf8p9p0q20qyf10c6xhvw40m2c4rr105hbk6zy26nj1q";
+    libName = "unicode_bidi";
+    dependencies = mapFeatures features ([
+      (crates."matches"."${deps."unicode_bidi"."0.3.4"."matches"}" deps)
+    ]);
+    features = mkFeatures (features."unicode_bidi"."0.3.4" or {});
+  };
+  features_.unicode_bidi."0.3.4" = deps: f: updateFeatures f (rec {
+    matches."${deps.unicode_bidi."0.3.4".matches}".default = true;
+    unicode_bidi = fold recursiveUpdate {} [
+      { "0.3.4".default = (f.unicode_bidi."0.3.4".default or true); }
+      { "0.3.4".flame =
+        (f.unicode_bidi."0.3.4".flame or false) ||
+        (f.unicode_bidi."0.3.4".flame_it or false) ||
+        (unicode_bidi."0.3.4"."flame_it" or false); }
+      { "0.3.4".flamer =
+        (f.unicode_bidi."0.3.4".flamer or false) ||
+        (f.unicode_bidi."0.3.4".flame_it or false) ||
+        (unicode_bidi."0.3.4"."flame_it" or false); }
+      { "0.3.4".serde =
+        (f.unicode_bidi."0.3.4".serde or false) ||
+        (f.unicode_bidi."0.3.4".with_serde or false) ||
+        (unicode_bidi."0.3.4"."with_serde" or false); }
+    ];
+  }) [
+    (features_.matches."${deps."unicode_bidi"."0.3.4"."matches"}" deps)
+  ];
+
+
+# end
+# unicode-normalization-0.1.7
+
+  crates.unicode_normalization."0.1.7" = deps: { features?(features_.unicode_normalization."0.1.7" deps {}) }: buildRustCrate {
+    crateName = "unicode-normalization";
+    version = "0.1.7";
+    authors = [ "kwantam <kwantam@gmail.com>" ];
+    sha256 = "1da2hv800pd0wilmn4idwpgv5p510hjxizjcfv6xzb40xcsjd8gs";
+  };
+  features_.unicode_normalization."0.1.7" = deps: f: updateFeatures f (rec {
+    unicode_normalization."0.1.7".default = (f.unicode_normalization."0.1.7".default or true);
+  }) [];
+
+
+# end
 # unicode-width-0.1.5
 
   crates.unicode_width."0.1.5" = deps: { features?(features_.unicode_width."0.1.5" deps {}) }: buildRustCrate {
@@ -1880,6 +2107,43 @@ rec {
 
 
 # end
+# url-1.7.2
+
+  crates.url."1.7.2" = deps: { features?(features_.url."1.7.2" deps {}) }: buildRustCrate {
+    crateName = "url";
+    version = "1.7.2";
+    authors = [ "The rust-url developers" ];
+    sha256 = "0qzrjzd9r1niv7037x4cgnv98fs1vj0k18lpxx890ipc47x5gc09";
+    dependencies = mapFeatures features ([
+      (crates."idna"."${deps."url"."1.7.2"."idna"}" deps)
+      (crates."matches"."${deps."url"."1.7.2"."matches"}" deps)
+      (crates."percent_encoding"."${deps."url"."1.7.2"."percent_encoding"}" deps)
+    ]);
+    features = mkFeatures (features."url"."1.7.2" or {});
+  };
+  features_.url."1.7.2" = deps: f: updateFeatures f (rec {
+    idna."${deps.url."1.7.2".idna}".default = true;
+    matches."${deps.url."1.7.2".matches}".default = true;
+    percent_encoding."${deps.url."1.7.2".percent_encoding}".default = true;
+    url = fold recursiveUpdate {} [
+      { "1.7.2".default = (f.url."1.7.2".default or true); }
+      { "1.7.2".encoding =
+        (f.url."1.7.2".encoding or false) ||
+        (f.url."1.7.2".query_encoding or false) ||
+        (url."1.7.2"."query_encoding" or false); }
+      { "1.7.2".heapsize =
+        (f.url."1.7.2".heapsize or false) ||
+        (f.url."1.7.2".heap_size or false) ||
+        (url."1.7.2"."heap_size" or false); }
+    ];
+  }) [
+    (features_.idna."${deps."url"."1.7.2"."idna"}" deps)
+    (features_.matches."${deps."url"."1.7.2"."matches"}" deps)
+    (features_.percent_encoding."${deps."url"."1.7.2"."percent_encoding"}" deps)
+  ];
+
+
+# end
 # utf8-ranges-1.0.1
 
   crates.utf8_ranges."1.0.1" = deps: { features?(features_.utf8_ranges."1.0.1" deps {}) }: buildRustCrate {
diff --git a/pkgs/build-support/setup-hooks/fix-darwin-dylib-names.sh b/pkgs/build-support/setup-hooks/fix-darwin-dylib-names.sh
index 1b36f5f555da..af2ff0cc9662 100644
--- a/pkgs/build-support/setup-hooks/fix-darwin-dylib-names.sh
+++ b/pkgs/build-support/setup-hooks/fix-darwin-dylib-names.sh
@@ -23,7 +23,14 @@ fixDarwinDylibNames() {
     for fn in "$@"; do
         if [ -L "$fn" ]; then continue; fi
         echo "$fn: fixing dylib"
-        install_name_tool -id "$fn" "${flags[@]}" "$fn"
+        int_out=$(install_name_tool -id "$fn" "${flags[@]}" "$fn" 2>&1)
+        result=$?
+        if [ "$result" -ne 0 ] &&
+            ! grep "shared library stub file and can't be changed" <<< "$out"
+        then
+            echo "$int_out" >&2
+            exit "$result"
+        fi
     done
 }
 
diff --git a/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh b/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh
index 25ac12996cc1..b5ceb4a13d85 100644
--- a/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh
+++ b/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh
@@ -36,16 +36,40 @@ wrapGAppsHook() {
   done
 
   if [[ -z "$dontWrapGApps" ]]; then
+    targetDirsThatExist=()
+    targetDirsRealPath=()
+
+    # wrap binaries
     targetDirs=( "${prefix}/bin" "${prefix}/libexec" )
     for targetDir in "${targetDirs[@]}"; do
       if [[ -d "${targetDir}" ]]; then
-        find -L "${targetDir}" -type f -executable -print0 \
+        targetDirsThatExist+=("${targetDir}")
+        targetDirsRealPath+=("$(realpath "${targetDir}")/")
+        find "${targetDir}" -type f -executable -print0 \
           | while IFS= read -r -d '' file; do
-          echo "Wrapping program ${file}"
+          echo "Wrapping program '${file}'"
           wrapProgram "${file}" "${gappsWrapperArgs[@]}"
         done
       fi
     done
+
+    # wrap links to binaries that point outside targetDirs
+    # Note: links to binaries within targetDirs do not need
+    #       to be wrapped as the binaries have already been wrapped
+    if [[ ${#targetDirsThatExist[@]} -ne 0 ]]; then
+      find "${targetDirsThatExist[@]}" -type l -xtype f -executable -print0 \
+        | while IFS= read -r -d '' linkPath; do
+        linkPathReal=$(realpath "${linkPath}")
+        for targetPath in "${targetDirsRealPath[@]}"; do
+          if [[ "$linkPathReal" == "$targetPath"* ]]; then
+            echo "Not wrapping link: '$linkPath' (already wrapped)"
+            continue 2
+          fi
+        done
+        echo "Wrapping link: '$linkPath'"
+        wrapProgram "${linkPath}" "${gappsWrapperArgs[@]}"
+      done
+    fi
   fi
 }
 
diff --git a/pkgs/build-support/singularity-tools/default.nix b/pkgs/build-support/singularity-tools/default.nix
index 4206b0f33ff9..3fc10c8b0b4b 100644
--- a/pkgs/build-support/singularity-tools/default.nix
+++ b/pkgs/build-support/singularity-tools/default.nix
@@ -8,12 +8,13 @@
 , vmTools
 , gawk
 , utillinux
+, runtimeShell
 , e2fsprogs }:
 
 rec {
   shellScript = name: text:
     writeScript name ''
-      #!${stdenv.shell}
+      #!${runtimeShell}
       set -e
       ${text}
     '';
diff --git a/pkgs/build-support/skaware/build-skaware-package.nix b/pkgs/build-support/skaware/build-skaware-package.nix
index 51921fdfbdc7..e4712a5ef22c 100644
--- a/pkgs/build-support/skaware/build-skaware-package.nix
+++ b/pkgs/build-support/skaware/build-skaware-package.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchurl, writeScript, file }:
+{ stdenv, callPackage, cleanPackaging, fetchurl, writeScript, file }:
 let lib = stdenv.lib;
 in {
   # : string
@@ -19,6 +19,10 @@ in {
   # mostly for moving and deleting files from the build directory
   # : lines
 , postInstall
+  # packages with setup hooks that should be run
+  # (see definition of `makeSetupHook`)
+  # : list drv
+, setupHooks ? []
   # : list Maintainer
 , maintainers ? []
 
@@ -50,25 +54,6 @@ let
     "README.*"
   ];
 
-  globWith = stdenv.lib.concatMapStringsSep "\n";
-  rmNoise = globWith (f:
-    ''rm -rf ${f}'') commonNoiseFiles;
-  mvMeta = globWith
-    (f: ''mv ${f} "$DOCDIR" 2>/dev/null || true'')
-    commonMetaFiles;
-
-  # Move & remove actions, taking the package doc directory
-  commonFileActions = writeScript "common-file-actions.sh" ''
-    #!${stdenv.shell}
-    set -e
-    DOCDIR="$1"
-    shopt -s globstar extglob nullglob
-    ${rmNoise}
-    mkdir -p "$DOCDIR"
-    ${mvMeta}
-  '';
-
-
 in stdenv.mkDerivation {
   name = "${pname}-${version}";
 
@@ -82,6 +67,8 @@ in stdenv.mkDerivation {
   dontDisableStatic = true;
   enableParallelBuilding = true;
 
+  nativeBuildInputs = setupHooks;
+
   configureFlags = configureFlags ++ [
     "--enable-absolute-paths"
     (if stdenv.isDarwin
@@ -99,21 +86,16 @@ in stdenv.mkDerivation {
   # TODO(Profpatsch): ensure that there is always a $doc output!
   postInstall = ''
     echo "Cleaning & moving common files"
-    mkdir -p $doc/share/doc/${pname}
-    ${commonFileActions} $doc/share/doc/${pname}
+    ${cleanPackaging.commonFileActions {
+       noiseFiles = commonNoiseFiles;
+       docFiles = commonMetaFiles;
+     }} $doc/share/doc/${pname}
 
     ${postInstall}
   '';
 
   postFixup = ''
-    echo "Checking for remaining source files"
-    rem=$(find -mindepth 1 -xtype f -print0 \
-           | tee $TMP/remaining-files)
-    if [[ "$rem" != "" ]]; then
-      echo "ERROR: These files should be either moved or deleted:"
-      cat $TMP/remaining-files | xargs -0 ${file}/bin/file
-      exit 1
-    fi
+    ${cleanPackaging.checkForRemainingFiles}
   '';
 
   meta = {
diff --git a/pkgs/build-support/skaware/clean-packaging.nix b/pkgs/build-support/skaware/clean-packaging.nix
new file mode 100644
index 000000000000..16bae04b21e2
--- /dev/null
+++ b/pkgs/build-support/skaware/clean-packaging.nix
@@ -0,0 +1,53 @@
+# set of utilities that assure the cwd of a build
+# is completely clean after the build, meaning all
+# files were either discarded or moved to outputs.
+# This ensures nothing is forgotten and new files
+# are correctly handled on update.
+{ stdenv, file, writeScript }:
+
+let
+  globWith = stdenv.lib.concatMapStringsSep "\n";
+  rmNoise = noiseGlobs: globWith (f:
+    ''rm -rf ${f}'') noiseGlobs;
+  mvDoc = docGlobs: globWith
+    (f: ''mv ${f} "$DOCDIR" 2>/dev/null || true'')
+    docGlobs;
+
+  # Shell script that implements common move & remove actions
+  # $1 is the doc directory (will be created).
+  # Best used in conjunction with checkForRemainingFiles
+  commonFileActions =
+    { # list of fileglobs that are removed from the source dir
+      noiseFiles
+      # files that are moved to the doc directory ($1)
+      # TODO(Profpatsch): allow to set target dir with
+      # { glob = …; to = "html" } (relative to docdir)
+    , docFiles }:
+    writeScript "common-file-actions.sh" ''
+      #!${stdenv.shell}
+      set -e
+      DOCDIR="$1"
+      shopt -s globstar extglob nullglob
+      ${rmNoise noiseFiles}
+      mkdir -p "$DOCDIR"
+      ${mvDoc docFiles}
+    '';
+
+  # Shell script to check whether the build directory is empty.
+  # If there are still files remaining, exit 1 with a helpful
+  # listing of all remaining files and their types.
+  checkForRemainingFiles = writeScript "check-for-remaining-files.sh" ''
+    #!${stdenv.shell}
+    echo "Checking for remaining source files"
+    rem=$(find -mindepth 1 -xtype f -print0 \
+           | tee $TMP/remaining-files)
+    if [[ "$rem" != "" ]]; then
+      echo "ERROR: These files should be either moved or deleted:"
+      cat $TMP/remaining-files | xargs -0 ${file}/bin/file
+      exit 1
+    fi
+  '';
+
+in {
+  inherit commonFileActions checkForRemainingFiles;
+}
diff --git a/pkgs/build-support/substitute-files/substitute-all-files.nix b/pkgs/build-support/substitute-files/substitute-all-files.nix
index aa600a76650c..66feb695c418 100644
--- a/pkgs/build-support/substitute-files/substitute-all-files.nix
+++ b/pkgs/build-support/substitute-files/substitute-all-files.nix
@@ -22,4 +22,5 @@ stdenv.mkDerivation ({
     eval "$postInstall"
   '';
   preferLocalBuild = true;
+  allowSubstitutes = false;
 } // args)
diff --git a/pkgs/build-support/substitute/substitute-all.nix b/pkgs/build-support/substitute/substitute-all.nix
index 7fd46f95f998..57b160bbe901 100644
--- a/pkgs/build-support/substitute/substitute-all.nix
+++ b/pkgs/build-support/substitute/substitute-all.nix
@@ -8,4 +8,5 @@ stdenvNoCC.mkDerivation ({
   builder = ./substitute-all.sh;
   inherit (args) src;
   preferLocalBuild = true;
+  allowSubstitutes = false;
 } // args)
diff --git a/pkgs/build-support/trivial-builders.nix b/pkgs/build-support/trivial-builders.nix
index 454ef8912b3b..58bc7147ede4 100644
--- a/pkgs/build-support/trivial-builders.nix
+++ b/pkgs/build-support/trivial-builders.nix
@@ -1,4 +1,4 @@
-{ lib, stdenv, stdenvNoCC, lndir }:
+{ lib, stdenv, stdenvNoCC, lndir, runtimeShell }:
 
 let
 
@@ -15,12 +15,12 @@ rec {
   /* Run the shell command `buildCommand' to produce a store path named
   * `name'.  The attributes in `env' are added to the environment
   * prior to running the command. By default `runCommand' runs using
-  * stdenv with no compiler environment. `runCommandCC` 
+  * stdenv with no compiler environment. `runCommandCC`
   *
   * Examples:
   * runCommand "name" {envVariable = true;} ''echo hello''
   * runCommandNoCC "name" {envVariable = true;} ''echo hello'' # equivalent to prior
-  * runCommandCC "name" {} ''gcc -o myfile myfile.c; cp myfile $out''; 
+  * runCommandCC "name" {} ''gcc -o myfile myfile.c; cp myfile $out'';
   */
   runCommand = runCommandNoCC;
   runCommandNoCC = runCommand' stdenvNoCC;
@@ -145,11 +145,11 @@ rec {
       executable = true;
       destination = "/bin/${name}";
       text = ''
-        #!${stdenv.shell}
+        #!${runtimeShell}
         ${text}
         '';
       checkPhase = ''
-        ${stdenv.shell} -n $out/bin/${name}
+        ${runtimeShell} -n $out/bin/${name}
       '';
     };
 
@@ -215,7 +215,7 @@ rec {
    * myhellohook = makeSetupHook { deps = [ hello ]; } ./myscript.sh;
    *
    * # wrotes a setup hook where @bash@ myscript.sh is substituted for the
-   * # bash interpreter. 
+   * # bash interpreter.
    * myhellohookSub = makeSetupHook {
    *                 deps = [ hello ];
    *                 substitutions = { bash = "${pkgs.bash}/bin/bash"; };
@@ -278,7 +278,7 @@ rec {
    * packages that cannot be built automatically.
    *
    * Examples:
-   * 
+   *
    * requireFile {
    *   name = "my-file";
    *   url = "http://example.com/download/";
diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix
index 3612be1120ca..de6a5e3b62f9 100644
--- a/pkgs/build-support/vm/default.nix
+++ b/pkgs/build-support/vm/default.nix
@@ -164,7 +164,7 @@ rec {
     # Set up automatic kernel module loading.
     export MODULE_DIR=${kernel}/lib/modules/
     ${coreutils}/bin/cat <<EOF > /run/modprobe
-    #! /bin/sh
+    #! ${bash}/bin/sh
     export MODULE_DIR=$MODULE_DIR
     exec ${kmod}/bin/modprobe "\$@"
     EOF
diff --git a/pkgs/build-support/vm/windows/controller/default.nix b/pkgs/build-support/vm/windows/controller/default.nix
index e000308bed8f..08b93aaf1174 100644
--- a/pkgs/build-support/vm/windows/controller/default.nix
+++ b/pkgs/build-support/vm/windows/controller/default.nix
@@ -1,5 +1,6 @@
 { stdenv, writeScript, vmTools, makeInitrd
 , samba, vde2, openssh, socat, netcat-gnu, coreutils, gnugrep, gzip
+, runtimeShell
 }:
 
 { sshKey
@@ -74,7 +75,7 @@ let
   loopForever = "while :; do ${coreutils}/bin/sleep 1; done";
 
   initScript = writeScript "init.sh" (''
-    #!${stdenv.shell}
+    #!${runtimeShell}
     ${coreutils}/bin/cp -L "${sshKey}" /ssh.key
     ${coreutils}/bin/chmod 600 /ssh.key
   '' + (if installMode then ''