about summary refs log tree commit diff
path: root/nixpkgs/pkgs/build-support
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-01-15 10:30:44 +0000
committerAlyssa Ross <hi@alyssa.is>2021-01-15 10:30:44 +0000
commite0794be8a0d11e90461e5a9c85012a36b93ec976 (patch)
treeefd9cbc55ea3322867bf601c4d536758a3dd5fcc /nixpkgs/pkgs/build-support
parent3538874082ded7647b1ccec0343c7c1e882cfef3 (diff)
parent1a57d96edd156958b12782e8c8b6a374142a7248 (diff)
downloadnixlib-e0794be8a0d11e90461e5a9c85012a36b93ec976.tar
nixlib-e0794be8a0d11e90461e5a9c85012a36b93ec976.tar.gz
nixlib-e0794be8a0d11e90461e5a9c85012a36b93ec976.tar.bz2
nixlib-e0794be8a0d11e90461e5a9c85012a36b93ec976.tar.lz
nixlib-e0794be8a0d11e90461e5a9c85012a36b93ec976.tar.xz
nixlib-e0794be8a0d11e90461e5a9c85012a36b93ec976.tar.zst
nixlib-e0794be8a0d11e90461e5a9c85012a36b93ec976.zip
Merge commit '1a57d96edd156958b12782e8c8b6a374142a7248'
Diffstat (limited to 'nixpkgs/pkgs/build-support')
-rwxr-xr-xnixpkgs/pkgs/build-support/appimage/appimage-exec.sh10
-rw-r--r--nixpkgs/pkgs/build-support/bintools-wrapper/default.nix7
-rw-r--r--nixpkgs/pkgs/build-support/build-bazel-package/default.nix2
-rw-r--r--nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix72
-rw-r--r--nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c16
-rw-r--r--nixpkgs/pkgs/build-support/cc-wrapper/default.nix8
-rw-r--r--nixpkgs/pkgs/build-support/docker/default.nix72
-rw-r--r--nixpkgs/pkgs/build-support/docker/detjson.py2
-rw-r--r--nixpkgs/pkgs/build-support/docker/examples.nix29
-rwxr-xr-xnixpkgs/pkgs/build-support/docker/nix-prefetch-docker14
-rw-r--r--nixpkgs/pkgs/build-support/emacs/elpa.nix11
-rw-r--r--nixpkgs/pkgs/build-support/emacs/generic.nix7
-rw-r--r--nixpkgs/pkgs/build-support/emacs/melpa.nix2
-rw-r--r--nixpkgs/pkgs/build-support/emacs/setup-hook.sh11
-rw-r--r--nixpkgs/pkgs/build-support/emacs/wrapper.nix37
-rw-r--r--nixpkgs/pkgs/build-support/emacs/wrapper.sh32
-rw-r--r--nixpkgs/pkgs/build-support/fetchfirefoxaddon/default.nix41
-rw-r--r--nixpkgs/pkgs/build-support/fetchfossil/default.nix4
-rw-r--r--nixpkgs/pkgs/build-support/fetchmavenartifact/default.nix14
-rw-r--r--nixpkgs/pkgs/build-support/fetchsvnrevision/default.nix2
-rw-r--r--nixpkgs/pkgs/build-support/fetchurl/mirrors.nix6
-rw-r--r--nixpkgs/pkgs/build-support/fetchzip/default.nix16
-rw-r--r--nixpkgs/pkgs/build-support/install-shell-files/default.nix12
-rw-r--r--nixpkgs/pkgs/build-support/kernel/initrd-compressor-meta.nix53
-rw-r--r--nixpkgs/pkgs/build-support/kernel/make-initrd.nix93
-rw-r--r--nixpkgs/pkgs/build-support/kernel/make-initrd.sh11
-rw-r--r--nixpkgs/pkgs/build-support/libredirect/libredirect.c7
-rw-r--r--nixpkgs/pkgs/build-support/make-desktopitem/default.nix77
-rw-r--r--nixpkgs/pkgs/build-support/nix-gitignore/default.nix4
-rw-r--r--nixpkgs/pkgs/build-support/ocaml/dune.nix4
-rw-r--r--nixpkgs/pkgs/build-support/rust/build-rust-crate/build-crate.nix2
-rw-r--r--nixpkgs/pkgs/build-support/rust/build-rust-crate/configure-crate.nix6
-rw-r--r--nixpkgs/pkgs/build-support/rust/build-rust-crate/default.nix18
-rw-r--r--nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix71
-rw-r--r--nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix30
-rw-r--r--nixpkgs/pkgs/build-support/rust/default.nix53
-rw-r--r--nixpkgs/pkgs/build-support/rust/fetchCargoTarball.nix15
-rw-r--r--nixpkgs/pkgs/build-support/rust/sysroot/Cargo.lock29
-rw-r--r--nixpkgs/pkgs/build-support/rust/sysroot/cargo.py45
-rw-r--r--nixpkgs/pkgs/build-support/rust/sysroot/default.nix41
-rwxr-xr-xnixpkgs/pkgs/build-support/rust/sysroot/update-lockfile.sh21
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.sh92
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/compress-man-pages.sh1
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/copy-desktop-items.sh42
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/install-shell-files.sh125
-rwxr-xr-xnixpkgs/pkgs/build-support/setup-hooks/move-systemd-user-units.sh25
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/reproducible-builds.sh4
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/strip.sh2
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/validate-pkg-config.sh3
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix4
-rw-r--r--nixpkgs/pkgs/build-support/singularity-tools/default.nix4
-rw-r--r--nixpkgs/pkgs/build-support/vm/default.nix34
-rw-r--r--nixpkgs/pkgs/build-support/vm/windows/bootstrap.nix83
-rw-r--r--nixpkgs/pkgs/build-support/vm/windows/controller/default.nix263
-rw-r--r--nixpkgs/pkgs/build-support/vm/windows/cygwin-iso/default.nix56
-rw-r--r--nixpkgs/pkgs/build-support/vm/windows/cygwin-iso/mkclosure.py78
-rw-r--r--nixpkgs/pkgs/build-support/vm/windows/default.nix44
-rw-r--r--nixpkgs/pkgs/build-support/vm/windows/install/default.nix74
-rw-r--r--nixpkgs/pkgs/build-support/vm/windows/install/unattended-image.nix123
-rw-r--r--nixpkgs/pkgs/build-support/wrapper-common/utils.bash10
-rw-r--r--nixpkgs/pkgs/build-support/writers/default.nix7
61 files changed, 1051 insertions, 1030 deletions
diff --git a/nixpkgs/pkgs/build-support/appimage/appimage-exec.sh b/nixpkgs/pkgs/build-support/appimage/appimage-exec.sh
index 82ebdd0bbe4a..7986c589667b 100755
--- a/nixpkgs/pkgs/build-support/appimage/appimage-exec.sh
+++ b/nixpkgs/pkgs/build-support/appimage/appimage-exec.sh
@@ -1,4 +1,6 @@
 #!@shell@
+# shellcheck shell=bash
+
 if [ -n "$DEBUG" ] ; then
   set -x
 fi
@@ -13,8 +15,10 @@ unpack() {
   local out="$2"
 
   # https://github.com/AppImage/libappimage/blob/ca8d4b53bed5cbc0f3d0398e30806e0d3adeaaab/src/libappimage/utils/MagicBytesChecker.cpp#L45-L63
-  local appimageSignature=$(readelf -h "$src" | awk 'NR==2{print $10$11;}')
-  local appimageType=$(readelf -h "$src" | awk 'NR==2{print $12;}')
+  local appimageSignature;
+  appimageSignature="$(LC_ALL=C readelf -h "$src" | awk 'NR==2{print $10$11;}')"
+  local appimageType;
+  appimageType="$(LC_ALL=C readelf -h "$src" | awk 'NR==2{print $12;}')"
 
   # check AppImage signature
   if [ "$appimageSignature" != "4149" ]; then
@@ -35,7 +39,7 @@ unpack() {
 
       # multiarch offset one-liner using same method as AppImage
       # see https://gist.github.com/probonopd/a490ba3401b5ef7b881d5e603fa20c93
-      offset=$(readelf -h "$src" | awk 'NR==13{e_shoff=$5} NR==18{e_shentsize=$5} NR==19{e_shnum=$5} END{print e_shoff+e_shentsize*e_shnum}')
+      offset=$(LC_ALL=C readelf -h "$src" | awk 'NR==13{e_shoff=$5} NR==18{e_shentsize=$5} NR==19{e_shnum=$5} END{print e_shoff+e_shentsize*e_shnum}')
       echo "Uncompress $(basename "$src") of type $appimageType @ offset $offset"
       unsquashfs -q -d "$out" -o "$offset" "$src"
       chmod go-w "$out"
diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix
index 786f0f9c5983..6da0e58436d0 100644
--- a/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix
+++ b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix
@@ -167,7 +167,7 @@ stdenv.mkDerivation {
       else if targetPlatform.isWindows then "pe"
       else "elf" + toString targetPlatform.parsed.cpu.bits;
     endianPrefix = if targetPlatform.isBigEndian then "big" else "little";
-    sep = optionalString (!targetPlatform.isMips && !targetPlatform.isPower) "-";
+    sep = optionalString (!targetPlatform.isMips && !targetPlatform.isPower && !targetPlatform.isRiscV) "-";
     arch =
       /**/ if targetPlatform.isAarch64 then endianPrefix + "aarch64"
       else if targetPlatform.isAarch32     then endianPrefix + "arm"
@@ -179,12 +179,15 @@ stdenv.mkDerivation {
           mips64   = "btsmip";
           mips64el = "ltsmip";
         }.${targetPlatform.parsed.cpu.name}
+      else if targetPlatform.isMmix then "mmix"
       else if targetPlatform.isPower then if targetPlatform.isBigEndian then "ppc" else "lppc"
       else if targetPlatform.isSparc then "sparc"
       else if targetPlatform.isMsp430 then "msp430"
       else if targetPlatform.isAvr then "avr"
       else if targetPlatform.isAlpha then "alpha"
       else if targetPlatform.isVc4 then "vc4"
+      else if targetPlatform.isOr1k then "or1k"
+      else if targetPlatform.isRiscV then "lriscv"
       else throw "unknown emulation for platform: ${targetPlatform.config}";
     in if targetPlatform.useLLVM or false then ""
        else targetPlatform.platform.bfdEmulation or (fmt + sep + arch);
@@ -252,7 +255,7 @@ stdenv.mkDerivation {
 
     # Ensure consistent LC_VERSION_MIN_MACOSX and remove LC_UUID.
     + optionalString stdenv.targetPlatform.isMacOS ''
-      echo "-macosx_version_min 10.12 -sdk_version 10.12 -no_uuid" >> $out/nix-support/libc-ldflags-before
+      echo "-sdk_version 10.12 -no_uuid" >> $out/nix-support/libc-ldflags-before
     ''
 
     ##
diff --git a/nixpkgs/pkgs/build-support/build-bazel-package/default.nix b/nixpkgs/pkgs/build-support/build-bazel-package/default.nix
index 4d22a329e416..10a331bcc9e7 100644
--- a/nixpkgs/pkgs/build-support/build-bazel-package/default.nix
+++ b/nixpkgs/pkgs/build-support/build-bazel-package/default.nix
@@ -9,7 +9,7 @@ let
 in
 
 args@{
-  name
+  name ? "${args.pname}-${args.version}"
 , bazel ? bazelPkg
 , bazelFlags ? []
 , bazelBuildFlags ? []
diff --git a/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix b/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix
index c7cfd27d3faa..b40569a479bc 100644
--- a/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix
+++ b/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix
@@ -1,20 +1,27 @@
-{ callPackage, runCommandLocal, writeShellScriptBin, stdenv, coreutils, bubblewrap }:
-
-let buildFHSEnv = callPackage ./env.nix { }; in
+{ lib, callPackage, runCommandLocal, writeShellScriptBin, stdenv, coreutils, bubblewrap }:
 
 args @ {
-  name,
-  runScript ? "bash",
-  extraInstallCommands ? "",
-  meta ? {},
-  passthru ? {},
-  ...
+  name
+, runScript ? "bash"
+, extraInstallCommands ? ""
+, meta ? {}
+, passthru ? {}
+, unshareUser ? true
+, unshareIpc ? true
+, unsharePid ? true
+, unshareNet ? false
+, unshareUts ? true
+, unshareCgroup ? true
+, ...
 }:
 
 with builtins;
 let
+  buildFHSEnv = callPackage ./env.nix { };
+
   env = buildFHSEnv (removeAttrs args [
     "runScript" "extraInstallCommands" "meta" "passthru"
+    "unshareUser" "unshareCgroup" "unshareUts" "unshareNet" "unsharePid" "unshareIpc"
   ]);
 
   chrootenv = callPackage ./chrootenv {};
@@ -50,7 +57,7 @@ let
       "ssl/certs"
       "pki"
     ];
-  in concatStringsSep " \\\n  "
+  in concatStringsSep "\n  "
   (map (file: "--ro-bind-try /etc/${file} /etc/${file}") files);
 
   init = run: writeShellScriptBin "${name}-init" ''
@@ -59,46 +66,53 @@ let
   '';
 
   bwrapCmd = { initArgs ? "" }: ''
-    blacklist="/nix /dev /proc /etc"
-    ro_mounts=""
+    blacklist=(/nix /dev /proc /etc)
+    ro_mounts=()
     for i in ${env}/*; do
       path="/''${i##*/}"
       if [[ $path == '/etc' ]]; then
         continue
       fi
-      ro_mounts="$ro_mounts --ro-bind $i $path"
-      blacklist="$blacklist $path"
+      ro_mounts+=(--ro-bind "$i" "$path")
+      blacklist+=("$path")
     done
 
     if [[ -d ${env}/etc ]]; then
       for i in ${env}/etc/*; do
         path="/''${i##*/}"
-        ro_mounts="$ro_mounts --ro-bind $i /etc$path"
+        ro_mounts+=(--ro-bind "$i" "/etc$path")
       done
     fi
 
-    auto_mounts=""
+    declare -a auto_mounts
     # loop through all directories in the root
     for dir in /*; do
       # if it is a directory and it is not in the blacklist
-      if [[ -d "$dir" ]] && grep -v "$dir" <<< "$blacklist" >/dev/null; then
+      if [[ -d "$dir" ]] && [[ ! "''${blacklist[@]}" =~ "$dir" ]]; then
         # add it to the mount list
-        auto_mounts="$auto_mounts --bind $dir $dir"
+        auto_mounts+=(--bind "$dir" "$dir")
       fi
     done
 
-    exec ${bubblewrap}/bin/bwrap \
-      --dev-bind /dev /dev \
-      --proc /proc \
-      --chdir "$(pwd)" \
-      --unshare-all \
-      --share-net \
-      --die-with-parent \
-      --ro-bind /nix /nix \
-      ${etcBindFlags} \
-      $ro_mounts \
-      $auto_mounts \
+    cmd=(
+      ${bubblewrap}/bin/bwrap
+      --dev-bind /dev /dev
+      --proc /proc
+      --chdir "$(pwd)"
+      ${lib.optionalString unshareUser "--unshare-user"}
+      ${lib.optionalString unshareIpc "--unshare-ipc"}
+      ${lib.optionalString unsharePid "--unshare-pid"}
+      ${lib.optionalString unshareNet "--unshare-net"}
+      ${lib.optionalString unshareUts "--unshare-uts"}
+      ${lib.optionalString unshareCgroup "--unshare-cgroup"}
+      --die-with-parent
+      --ro-bind /nix /nix
+      ${etcBindFlags}
+      "''${ro_mounts[@]}"
+      "''${auto_mounts[@]}"
       ${init runScript}/bin/${name}-init ${initArgs}
+    )
+    exec "''${cmd[@]}"
   '';
 
   bin = writeShellScriptBin name (bwrapCmd { initArgs = ''"$@"''; });
diff --git a/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c b/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c
index dcb2e97aa932..a438b80e1829 100644
--- a/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c
+++ b/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c
@@ -43,6 +43,7 @@ const gchar *create_tmpdir() {
 void pivot_host(const gchar *guest) {
   g_autofree gchar *point = g_build_filename(guest, "host", NULL);
   fail_if(g_mkdir(point, 0755));
+  fail_if(mount(0, "/", 0, MS_PRIVATE | MS_REC, 0));
   fail_if(pivot_root(guest, point));
 }
 
@@ -56,6 +57,7 @@ void bind_mount_item(const gchar *host, const gchar *guest, const gchar *name) {
 
 void bind(const gchar *host, const gchar *guest) {
   mount_tmpfs(guest);
+
   pivot_host(guest);
 
   g_autofree gchar *host_dir = g_build_filename("/host", host, NULL);
@@ -105,7 +107,11 @@ int main(gint argc, gchar **argv) {
     uid_t uid = getuid();
     gid_t gid = getgid();
 
-    if (unshare(CLONE_NEWNS | CLONE_NEWUSER) < 0) {
+    int namespaces = CLONE_NEWNS;
+    if (uid != 0) {
+      namespaces |= CLONE_NEWUSER;
+    }
+    if (unshare(namespaces) < 0) {
       int unshare_errno = errno;
 
       g_message("Requires Linux version >= 3.19 built with CONFIG_USER_NS");
@@ -116,9 +122,11 @@ int main(gint argc, gchar **argv) {
       fail("unshare", unshare_errno);
     }
 
-    spit("/proc/self/setgroups", "deny");
-    spit("/proc/self/uid_map", "%d %d 1", uid, uid);
-    spit("/proc/self/gid_map", "%d %d 1", gid, gid);
+    if (uid != 0) {
+      spit("/proc/self/setgroups", "deny");
+      spit("/proc/self/uid_map", "%d %d 1", uid, uid);
+      spit("/proc/self/gid_map", "%d %d 1", gid, gid);
+    }
 
     // If there is a /host directory, assume this is nested chrootenv and use it as host instead.
     gboolean nested_host = g_file_test("/host", G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR);
diff --git a/nixpkgs/pkgs/build-support/cc-wrapper/default.nix b/nixpkgs/pkgs/build-support/cc-wrapper/default.nix
index 0e4e76d72843..0855c27eff49 100644
--- a/nixpkgs/pkgs/build-support/cc-wrapper/default.nix
+++ b/nixpkgs/pkgs/build-support/cc-wrapper/default.nix
@@ -57,7 +57,7 @@ let
   suffixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
 
   expand-response-params =
-    if buildPackages.stdenv.hasCC && buildPackages.stdenv.cc != "/dev/null"
+    if (buildPackages.stdenv.hasCC or false) && buildPackages.stdenv.cc != "/dev/null"
     then import ../expand-response-params { inherit (buildPackages) stdenv; }
     else "";
 
@@ -76,10 +76,14 @@ let
         cannonlake     = versionAtLeast ccVersion "8.0";
         icelake-client = versionAtLeast ccVersion "8.0";
         icelake-server = versionAtLeast ccVersion "8.0";
+        cascadelake    = versionAtLeast ccVersion "9.0";
+        cooperlake     = versionAtLeast ccVersion "10.0";
+        tigerlake      = versionAtLeast ccVersion "10.0";
         knm            = versionAtLeast ccVersion "8.0";
         # AMD
         znver1         = versionAtLeast ccVersion "6.0";
         znver2         = versionAtLeast ccVersion "9.0";
+        znver3         = versionAtLeast ccVersion "11.0";
       }.${arch} or true
     else if isClang then
       { # Intel
@@ -437,7 +441,7 @@ stdenv.mkDerivation {
     '' + optionalString targetPlatform.isNetBSD ''
       hardening_unsupported_flags+=" stackprotector fortify"
     '' + optionalString cc.langAda or false ''
-      hardening_unsupported_flags+=" stackprotector strictoverflow"
+      hardening_unsupported_flags+=" format stackprotector strictoverflow"
     '' + optionalString cc.langD or false ''
       hardening_unsupported_flags+=" format"
     '' + optionalString targetPlatform.isWasm ''
diff --git a/nixpkgs/pkgs/build-support/docker/default.nix b/nixpkgs/pkgs/build-support/docker/default.nix
index b2c132afd741..276c7cd1bdb8 100644
--- a/nixpkgs/pkgs/build-support/docker/default.nix
+++ b/nixpkgs/pkgs/build-support/docker/default.nix
@@ -1,4 +1,5 @@
 {
+  bashInteractive,
   buildPackages,
   cacert,
   callPackage,
@@ -15,7 +16,6 @@
   moreutils,
   nix,
   pigz,
-  referencesByPopularity,
   rsync,
   runCommand,
   runtimeShell,
@@ -25,12 +25,14 @@
   storeDir ? builtins.storeDir,
   substituteAll,
   symlinkJoin,
-  utillinux,
+  util-linux,
   vmTools,
   writeReferencesToFile,
   writeScript,
   writeText,
+  writeTextDir,
   writePython3,
+  system,  # Note: This is the cross system we're compiling for
 }:
 
 # WARNING: this API is unstable and may be subject to backwards-incompatible changes in the future.
@@ -48,7 +50,7 @@ let
     # A user is required by nix
     # https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478
     export USER=nobody
-    ${nix}/bin/nix-store --load-db < ${closureInfo {rootPaths = contentsList;}}/registration
+    ${buildPackages.nix}/bin/nix-store --load-db < ${closureInfo {rootPaths = contentsList;}}/registration
 
     mkdir -p nix/var/nix/gcroots/docker/
     for i in ${lib.concatStringsSep " " contentsList}; do
@@ -56,11 +58,18 @@ let
     done;
   '';
 
+  # The OCI Image specification recommends that configurations use values listed
+  # in the Go Language document for GOARCH.
+  # Reference: https://github.com/opencontainers/image-spec/blob/master/config.md#properties
+  # For the mapping from Nixpkgs system parameters to GOARCH, we can reuse the
+  # mapping from the go package.
+  defaultArch = go.GOARCH;
+
 in
 rec {
 
   examples = callPackage ./examples.nix {
-    inherit buildImage pullImage shadowSetup buildImageWithNixDb;
+    inherit buildImage buildLayeredImage fakeNss pullImage shadowSetup buildImageWithNixDb;
   };
 
   pullImage = let
@@ -72,7 +81,7 @@ rec {
     , imageDigest
     , sha256
     , os ? "linux"
-    , arch ? buildPackages.go.GOARCH
+    , arch ? defaultArch
 
       # This is used to set name to the pulled image
     , finalImageName ? imageName
@@ -194,7 +203,7 @@ rec {
         };
         inherit fromImage fromImageName fromImageTag;
 
-        nativeBuildInputs = [ utillinux e2fsprogs jshon rsync jq ];
+        nativeBuildInputs = [ util-linux e2fsprogs jshon rsync jq ];
       } ''
       mkdir disk
       mkfs /dev/${vmTools.hd}
@@ -340,7 +349,7 @@ rec {
       # Tar up the layer and throw it into 'layer.tar'.
       echo "Packing layer..."
       mkdir $out
-      tarhash=$(tar -C layer --hard-dereference --sort=name --mtime="@$SOURCE_DATE_EPOCH" --owner=${toString uid} --group=${toString gid} -cf - . | tee $out/layer.tar | tarsum)
+      tarhash=$(tar -C layer --hard-dereference --sort=name --mtime="@$SOURCE_DATE_EPOCH" --owner=${toString uid} --group=${toString gid} -cf - . | tee -p $out/layer.tar | tarsum)
 
       # Add a 'checksum' field to the JSON, with the value set to the
       # checksum of the tarball.
@@ -425,7 +434,7 @@ rec {
         echo "Packing layer..."
         mkdir -p $out
         tarhash=$(tar -C layer --hard-dereference --sort=name --mtime="@$SOURCE_DATE_EPOCH" -cf - . |
-                    tee $out/layer.tar |
+                    tee -p $out/layer.tar |
                     ${tarsum}/bin/tarsum)
 
         cat ${baseJson} | jshon -s "$tarhash" -i checksum > $out/json
@@ -443,7 +452,7 @@ rec {
       runCommand "${name}.tar.gz" {
         inherit (stream) imageName;
         passthru = { inherit (stream) imageTag; };
-        buildInputs = [ pigz ];
+        nativeBuildInputs = [ pigz ];
       } "${stream} | pigz -nT > $out";
 
   # 1. extract the base image
@@ -488,7 +497,7 @@ rec {
       baseJson = let
           pure = writeText "${baseName}-config.json" (builtins.toJSON {
             inherit created config;
-            architecture = buildPackages.go.GOARCH;
+            architecture = defaultArch;
             os = "linux";
           });
           impure = runCommand "${baseName}-config.json"
@@ -674,6 +683,33 @@ rec {
     in
     result;
 
+  # Provide a /etc/passwd and /etc/group that contain root and nobody.
+  # Useful when packaging binaries that insist on using nss to look up
+  # username/groups (like nginx).
+  # /bin/sh is fine to not exist, and provided by another shim.
+  fakeNss = symlinkJoin {
+    name = "fake-nss";
+    paths = [
+      (writeTextDir "etc/passwd" ''
+        root:x:0:0:root user:/var/empty:/bin/sh
+        nobody:x:65534:65534:nobody:/var/empty:/bin/sh
+      '')
+      (writeTextDir "etc/group" ''
+        root:x:0:
+        nobody:x:65534:
+      '')
+      (runCommand "var-empty" {} ''
+        mkdir -p $out/var/empty
+      '')
+    ];
+  };
+
+  # This provides /bin/sh, pointing to bashInteractive.
+  binSh = runCommand "bin-sh" {} ''
+    mkdir -p $out/bin
+    ln -s ${bashInteractive}/bin/bash $out/bin/sh
+  '';
+
   # Build an image and populate its nix database with the provided
   # contents. The main purpose is to be able to use nix commands in
   # the container.
@@ -715,7 +751,7 @@ rec {
       streamScript = writePython3 "stream" {} ./stream_layered_image.py;
       baseJson = writeText "${name}-base.json" (builtins.toJSON {
          inherit config;
-         architecture = buildPackages.go.GOARCH;
+         architecture = defaultArch;
          os = "linux";
       });
 
@@ -761,8 +797,8 @@ rec {
             then tag
             else
               lib.head (lib.strings.splitString "-" (baseNameOf conf.outPath));
-        paths = referencesByPopularity overallClosure;
-        buildInputs = [ jq ];
+        paths = buildPackages.referencesByPopularity overallClosure;
+        nativeBuildInputs = [ jq ];
       } ''
         ${if (tag == null) then ''
           outName="$(basename "$out")"
@@ -819,8 +855,14 @@ rec {
       '';
       result = runCommand "stream-${name}" {
         inherit (conf) imageName;
-        passthru = { inherit (conf) imageTag; };
-        buildInputs = [ makeWrapper ];
+        passthru = {
+          inherit (conf) imageTag;
+
+          # Distinguish tarballs and exes at the Nix level so functions that
+          # take images can know in advance how the image is supposed to be used.
+          isExe = true;
+        };
+        nativeBuildInputs = [ makeWrapper ];
       } ''
         makeWrapper ${streamScript} $out --add-flags ${conf}
       '';
diff --git a/nixpkgs/pkgs/build-support/docker/detjson.py b/nixpkgs/pkgs/build-support/docker/detjson.py
index 439c21313878..fe82cbea11bb 100644
--- a/nixpkgs/pkgs/build-support/docker/detjson.py
+++ b/nixpkgs/pkgs/build-support/docker/detjson.py
@@ -37,4 +37,4 @@ def main():
     json.dump(j, sys.stdout, sort_keys=True)
 
 if __name__ == '__main__':
-    main()
\ No newline at end of file
+    main()
diff --git a/nixpkgs/pkgs/build-support/docker/examples.nix b/nixpkgs/pkgs/build-support/docker/examples.nix
index 4a611add8a12..85ddeb257405 100644
--- a/nixpkgs/pkgs/build-support/docker/examples.nix
+++ b/nixpkgs/pkgs/build-support/docker/examples.nix
@@ -7,7 +7,7 @@
 #  $ nix-build '<nixpkgs>' -A dockerTools.examples.redis
 #  $ docker load < result
 
-{ pkgs, buildImage, pullImage, shadowSetup, buildImageWithNixDb }:
+{ pkgs, buildImage, buildLayeredImage, fakeNss, pullImage, shadowSetup, buildImageWithNixDb, pkgsCross }:
 
 rec {
   # 1. basic example
@@ -44,7 +44,7 @@ rec {
   nginx = let
     nginxPort = "80";
     nginxConf = pkgs.writeText "nginx.conf" ''
-      user nginx nginx;
+      user nobody nobody;
       daemon off;
       error_log /dev/stdout info;
       pid /dev/null;
@@ -64,10 +64,13 @@ rec {
       <html><body><h1>Hello from NGINX</h1></body></html>
     '';
   in
-  buildImage {
+  buildLayeredImage {
     name = "nginx-container";
     tag = "latest";
-    contents = pkgs.nginx;
+    contents = [
+      fakeNss
+      pkgs.nginx
+    ];
 
     extraCommands = ''
       # nginx still tries to read this directory even if error_log
@@ -75,12 +78,6 @@ rec {
       mkdir -p var/log/nginx
       mkdir -p var/cache/nginx
     '';
-    runAsRoot = ''
-      #!${pkgs.stdenv.shell}
-      ${shadowSetup}
-      groupadd --system nginx
-      useradd --system --gid nginx nginx
-    '';
 
     config = {
       Cmd = [ "nginx" "-c" nginxConf ];
@@ -407,4 +404,16 @@ rec {
       contents = [ pkgs.bash pkgs.coreutils ] ++ nonRootShadowSetup { uid = 999; user = "somebody"; };
     };
 
+  # basic example, with cross compilation
+  cross = let
+    # Cross compile for x86_64 if on aarch64
+    crossPkgs =
+      if pkgs.system == "aarch64-linux" then pkgsCross.gnu64
+      else pkgsCross.aarch64-multiplatform;
+  in crossPkgs.dockerTools.buildImage {
+    name = "hello-cross";
+    tag = "latest";
+    contents = crossPkgs.hello;
+  };
+
 }
diff --git a/nixpkgs/pkgs/build-support/docker/nix-prefetch-docker b/nixpkgs/pkgs/build-support/docker/nix-prefetch-docker
index 1b6785189c28..5798ab5984f1 100755
--- a/nixpkgs/pkgs/build-support/docker/nix-prefetch-docker
+++ b/nixpkgs/pkgs/build-support/docker/nix-prefetch-docker
@@ -127,7 +127,7 @@ trap "rm -rf \"$tmpPath\"" EXIT
 tmpFile="$tmpPath/$(get_name $finalImageName $finalImageTag)"
 
 if test -z "$QUIET"; then
-    skopeo --insecure-policy --tmpdir=$TMPDIR --override-os ${os} --override-arch ${arch} copy "$sourceUrl" "docker-archive://$tmpFile:$finalImageName:$finalImageTag"
+    skopeo --insecure-policy --tmpdir=$TMPDIR --override-os ${os} --override-arch ${arch} copy "$sourceUrl" "docker-archive://$tmpFile:$finalImageName:$finalImageTag" >&2
 else
     skopeo --insecure-policy --tmpdir=$TMPDIR --override-os ${os} --override-arch ${arch} copy "$sourceUrl" "docker-archive://$tmpFile:$finalImageName:$finalImageTag" > /dev/null
 fi
@@ -139,12 +139,12 @@ imageHash=$(nix-hash --flat --type $hashType --base32 "$tmpFile")
 finalPath=$(nix-store --add-fixed "$hashType" "$tmpFile")
 
 if test -z "$QUIET"; then
-    echo "-> ImageName: $imageName"
-    echo "-> ImageDigest: $imageDigest"
-    echo "-> FinalImageName: $finalImageName"
-    echo "-> FinalImageTag: $finalImageTag"
-    echo "-> ImagePath: $finalPath"
-    echo "-> ImageHash: $imageHash"
+    echo "-> ImageName: $imageName" >&2
+    echo "-> ImageDigest: $imageDigest" >&2
+    echo "-> FinalImageName: $finalImageName" >&2
+    echo "-> FinalImageTag: $finalImageTag" >&2
+    echo "-> ImagePath: $finalPath" >&2
+    echo "-> ImageHash: $imageHash" >&2
 fi
 
 if [ "$format" == "nix" ]; then
diff --git a/nixpkgs/pkgs/build-support/emacs/elpa.nix b/nixpkgs/pkgs/build-support/emacs/elpa.nix
index e6f6c23e449f..214aed9c3f9c 100644
--- a/nixpkgs/pkgs/build-support/emacs/elpa.nix
+++ b/nixpkgs/pkgs/build-support/emacs/elpa.nix
@@ -7,9 +7,18 @@ with lib;
 { pname
 , version
 , src
+, meta ? {}
 , ...
 }@args:
 
+let
+
+  defaultMeta = {
+    homepage = args.src.meta.homepage or "https://elpa.gnu.org/packages/${pname}.html";
+  };
+
+in
+
 import ./generic.nix { inherit lib stdenv emacs texinfo; } ({
 
   phases = "installPhase fixupPhase distPhase";
@@ -23,6 +32,8 @@ import ./generic.nix { inherit lib stdenv emacs texinfo; } ({
 
     runHook postInstall
   '';
+
+  meta = defaultMeta // meta;
 }
 
 // removeAttrs args [ "files" "fileSpecs"
diff --git a/nixpkgs/pkgs/build-support/emacs/generic.nix b/nixpkgs/pkgs/build-support/emacs/generic.nix
index 956787ad59e4..588699517baf 100644
--- a/nixpkgs/pkgs/build-support/emacs/generic.nix
+++ b/nixpkgs/pkgs/build-support/emacs/generic.nix
@@ -60,10 +60,13 @@ stdenv.mkDerivation ({
 
   LIBRARY_PATH = "${lib.getLib stdenv.cc.libc}/lib";
 
+  addEmacsNativeLoadPath = true;
+
   postInstall = ''
-    find $out/share/emacs -type f -name '*.el' -print0 | xargs -0 -n 1 -I {} -P $NIX_BUILD_CORES sh -c "emacs --batch -f batch-native-compile {} || true"
+    find $out/share/emacs -type f -name '*.el' -print0 \
+      | xargs -0 -n 1 -I {} -P $NIX_BUILD_CORES sh -c \
+          "emacs --batch --eval=\"(add-to-list 'comp-eln-load-path \\\"$out/share/emacs/native-lisp/\\\")\" -f batch-native-compile {} || true"
   '';
-
 }
 
 // removeAttrs args [ "buildInputs" "packageRequires"
diff --git a/nixpkgs/pkgs/build-support/emacs/melpa.nix b/nixpkgs/pkgs/build-support/emacs/melpa.nix
index e2ec84c75e66..d6fe3085837e 100644
--- a/nixpkgs/pkgs/build-support/emacs/melpa.nix
+++ b/nixpkgs/pkgs/build-support/emacs/melpa.nix
@@ -23,7 +23,7 @@ with lib;
 let
 
   defaultMeta = {
-    homepage = args.src.meta.homepage or "http://melpa.org/#/${pname}";
+    homepage = args.src.meta.homepage or "https://melpa.org/#/${pname}";
   };
 
 in
diff --git a/nixpkgs/pkgs/build-support/emacs/setup-hook.sh b/nixpkgs/pkgs/build-support/emacs/setup-hook.sh
index 83e995631b3e..f6f2331b8e02 100644
--- a/nixpkgs/pkgs/build-support/emacs/setup-hook.sh
+++ b/nixpkgs/pkgs/build-support/emacs/setup-hook.sh
@@ -7,9 +7,20 @@ addToEmacsLoadPath() {
   fi
 }
 
+addToEmacsNativeLoadPath() {
+  local nativeDir="$1"
+  if [[ -d $nativeDir && ${EMACSNATIVELOADPATH-} != *"$nativeDir":* ]]; then
+    export EMACSNATIVELOADPATH="$nativeDir:${EMACSNATIVELOADPATH-}"
+  fi
+}
+
 addEmacsVars () {
   addToEmacsLoadPath "$1/share/emacs/site-lisp"
 
+  if [ -n "${addEmacsNativeLoadPath:-}" ]; then
+    addToEmacsNativeLoadPath "$1/share/emacs/native-lisp"
+  fi
+
   # Add sub paths to the Emacs load path if it is a directory
   # containing .el files. This is necessary to build some packages,
   # e.g., using trivialBuild.
diff --git a/nixpkgs/pkgs/build-support/emacs/wrapper.nix b/nixpkgs/pkgs/build-support/emacs/wrapper.nix
index a3ab30afc632..a3136839122d 100644
--- a/nixpkgs/pkgs/build-support/emacs/wrapper.nix
+++ b/nixpkgs/pkgs/build-support/emacs/wrapper.nix
@@ -34,7 +34,15 @@ in customEmacsPackages.emacsWithPackages (epkgs: [ epkgs.evil epkgs.magit ])
 
 { lib, lndir, makeWrapper, runCommand }: self:
 
-with lib; let inherit (self) emacs; in
+with lib;
+
+let
+
+  inherit (self) emacs;
+
+  nativeComp = emacs.nativeComp or false;
+
+in
 
 packagesFun: # packages explicitly requested by the user
 
@@ -95,6 +103,9 @@ runCommand
         }
         mkdir -p $out/bin
         mkdir -p $out/share/emacs/site-lisp
+        ${optionalString nativeComp ''
+          mkdir -p $out/share/emacs/native-lisp
+        ''}
 
         local requires
         for pkg in $explicitRequires; do
@@ -116,6 +127,9 @@ runCommand
         linkEmacsPackage() {
           linkPath "$1" "bin" "bin"
           linkPath "$1" "share/emacs/site-lisp" "share/emacs/site-lisp"
+          ${optionalString nativeComp ''
+            linkPath "$1" "share/emacs/native-lisp" "share/emacs/native-lisp"
+          ''}
         }
 
         # Iterate over the array of inputs (avoiding nix's own interpolation)
@@ -138,12 +152,21 @@ runCommand
         (load-file "$emacs/share/emacs/site-lisp/site-start.el")
         (add-to-list 'load-path "$out/share/emacs/site-lisp")
         (add-to-list 'exec-path "$out/bin")
+        ${optionalString nativeComp ''
+          (add-to-list 'comp-eln-load-path "$out/share/emacs/native-lisp/")
+        ''}
         EOF
         # Link subdirs.el from the emacs distribution
         ln -s $emacs/share/emacs/site-lisp/subdirs.el -T $subdirs
 
         # Byte-compiling improves start-up time only slightly, but costs nothing.
         $emacs/bin/emacs --batch -f batch-byte-compile "$siteStart" "$subdirs"
+
+        ${optionalString nativeComp ''
+          $emacs/bin/emacs --batch \
+            --eval "(add-to-list 'comp-eln-load-path \"$out/share/emacs/native-lisp/\")" \
+            -f batch-native-compile "$siteStart" "$subdirs"
+        ''}
       '';
 
     inherit (emacs) meta;
@@ -159,6 +182,7 @@ runCommand
       substitute ${./wrapper.sh} $out/bin/$progname \
         --subst-var-by bash ${emacs.stdenv.shell} \
         --subst-var-by wrapperSiteLisp "$deps/share/emacs/site-lisp" \
+        --subst-var-by wrapperSiteLispNative "$deps/share/emacs/native-lisp:" \
         --subst-var prog
       chmod +x $out/bin/$progname
     done
@@ -173,11 +197,16 @@ runCommand
             $emacs/Applications/Emacs.app/Contents/Resources \
             $out/Applications/Emacs.app/Contents
 
+
       substitute ${./wrapper.sh} $out/Applications/Emacs.app/Contents/MacOS/Emacs \
         --subst-var-by bash ${emacs.stdenv.shell} \
-        --subst-var-by wrapperSiteLisp "$emacs/Applications/Emacs.app/Contents/MacOS/Emacs" \
-        --subst-var prog
-      chmod +x $out/bin/$progname
+        --subst-var-by wrapperSiteLisp "$deps/share/emacs/site-lisp" \
+        --subst-var-by prog "$emacs/Applications/Emacs.app/Contents/MacOS/Emacs"
+      chmod +x $out/Applications/Emacs.app/Contents/MacOS/Emacs
+
+      makeWrapper $emacs/Applications/Emacs.app/Contents/MacOS/Emacs $out/Applications/Emacs.app/Contents/MacOS/Emacs \
+        --suffix EMACSLOADPATH ":" "$deps/share/emacs/site-lisp:" \
+        --suffix EMACSNATIVELOADPATH ":" "$deps/share/emacs/native-lisp:"
     fi
 
     mkdir -p $out/share
diff --git a/nixpkgs/pkgs/build-support/emacs/wrapper.sh b/nixpkgs/pkgs/build-support/emacs/wrapper.sh
index 6e0451fc1d4f..e8eecb8c8696 100644
--- a/nixpkgs/pkgs/build-support/emacs/wrapper.sh
+++ b/nixpkgs/pkgs/build-support/emacs/wrapper.sh
@@ -3,25 +3,45 @@
 IFS=:
 
 newLoadPath=()
+newNativeLoadPath=()
 added=
 
 if [[ -n $EMACSLOADPATH ]]
 then
     while read -rd: entry
     do
-	if [[ -z $entry && -z $added ]]
-	then
-	    newLoadPath+=(@wrapperSiteLisp@)
-	    added=1
-	fi
-	newLoadPath+=("$entry")
+        if [[ -z $entry && -z $added ]]
+        then
+            newLoadPath+=(@wrapperSiteLisp@)
+            added=1
+        fi
+        newLoadPath+=("$entry")
     done <<< "$EMACSLOADPATH:"
 else
     newLoadPath+=(@wrapperSiteLisp@)
     newLoadPath+=("")
 fi
 
+if [[ -n $EMACSNATIVELOADPATH ]]
+then
+    while read -rd: entry
+    do
+        if [[ -z $entry && -z $added ]]
+        then
+            newNativeLoadPath+=(@wrapperSiteLispNative@)
+            added=1
+        fi
+        newNativeLoadPath+=("$entry")
+    done <<< "$EMACSNATIVELOADPATH:"
+else
+    newNativeLoadPath+=(@wrapperSiteLispNative@)
+    newNativeLoadPath+=("")
+fi
+
 export EMACSLOADPATH="${newLoadPath[*]}"
 export emacsWithPackages_siteLisp=@wrapperSiteLisp@
 
+export EMACSNATIVELOADPATH="${newNativeLoadPath[*]}"
+export emacsWithPackages_siteLispNative=@wrapperSiteLispNative@
+
 exec @prog@ "$@"
diff --git a/nixpkgs/pkgs/build-support/fetchfirefoxaddon/default.nix b/nixpkgs/pkgs/build-support/fetchfirefoxaddon/default.nix
new file mode 100644
index 000000000000..9efe9197d687
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/fetchfirefoxaddon/default.nix
@@ -0,0 +1,41 @@
+{stdenv, lib, coreutils, unzip, jq, zip, fetchurl,writeScript,  ...}:
+
+{
+  name
+, url
+, md5 ? ""
+, sha1 ? ""
+, sha256 ? ""
+, sha512 ? ""
+, fixedExtid ? null
+, hash ? ""
+}:
+
+stdenv.mkDerivation rec {
+
+  inherit name;
+  extid = if fixedExtid == null then "nixos@${name}" else fixedExtid;
+  passthru = {
+    exitd=extid;
+  };
+
+  builder = writeScript "xpibuilder" ''
+    source $stdenv/setup
+
+    header "firefox addon $name into $out"
+
+    UUID="${extid}"
+    mkdir -p "$out/$UUID"
+    unzip -q ${src} -d "$out/$UUID"
+    NEW_MANIFEST=$(jq '. + {"applications": { "gecko": { "id": "${extid}" }}, "browser_specific_settings":{"gecko":{"id": "${extid}"}}}' "$out/$UUID/manifest.json")
+    echo "$NEW_MANIFEST" > "$out/$UUID/manifest.json"
+    cd "$out/$UUID"
+    zip -r -q -FS "$out/$UUID.xpi" *
+    rm -r "$out/$UUID"
+  '';
+  src = fetchurl {
+    url = url;
+    inherit md5 sha1 sha256 sha512 hash;
+  };
+  nativeBuildInputs = [ coreutils unzip zip jq  ];
+}
diff --git a/nixpkgs/pkgs/build-support/fetchfossil/default.nix b/nixpkgs/pkgs/build-support/fetchfossil/default.nix
index 27933b47178a..3a4876bc5de3 100644
--- a/nixpkgs/pkgs/build-support/fetchfossil/default.nix
+++ b/nixpkgs/pkgs/build-support/fetchfossil/default.nix
@@ -1,11 +1,11 @@
-{stdenv, fossil}:
+{stdenv, fossil, cacert}:
 
 {name ? null, url, rev, sha256}:
 
 stdenv.mkDerivation {
   name = "fossil-archive" + (if name != null then "-${name}" else "");
   builder = ./builder.sh;
-  nativeBuildInputs = [fossil];
+  nativeBuildInputs = [fossil cacert];
 
   # Envvar docs are hard to find. A link for the future:
   # https://www.fossil-scm.org/index.html/doc/trunk/www/env-opts.md
diff --git a/nixpkgs/pkgs/build-support/fetchmavenartifact/default.nix b/nixpkgs/pkgs/build-support/fetchmavenartifact/default.nix
index 583a9ea396cf..42162638e72d 100644
--- a/nixpkgs/pkgs/build-support/fetchmavenartifact/default.nix
+++ b/nixpkgs/pkgs/build-support/fetchmavenartifact/default.nix
@@ -3,10 +3,10 @@
 { fetchurl, stdenv }:
 let
   defaultRepos = [
-    "http://repo1.maven.org/maven2"
-    "http://oss.sonatype.org/content/repositories/releases"
-    "http://oss.sonatype.org/content/repositories/public"
-    "http://repo.typesafe.com/typesafe/releases"
+    "https://repo1.maven.org/maven2"
+    "https://oss.sonatype.org/content/repositories/releases"
+    "https://oss.sonatype.org/content/repositories/public"
+    "https://repo.typesafe.com/typesafe/releases"
   ];
 in
 
@@ -17,6 +17,8 @@ args@
   artifactId
 , # Example: "4.3.6"
   version
+, # Example: "jdk11"
+  classifier ? null
 , # List of maven repositories from where to fetch the artifact.
   # Example: [ http://oss.sonatype.org/content/repositories/public ].
   repos ? defaultRepos
@@ -48,7 +50,7 @@ let
       (replaceChars ["."] ["/"] groupId)
       artifactId
       version
-      "${artifactId}-${version}.jar"
+      "${artifactId}-${version}${optionalString (!isNull classifier) "-${classifier}"}.jar"
     ];
   urls_ =
     if url != "" then [url]
@@ -56,7 +58,7 @@ let
     else map mkJarUrl repos;
   jar =
     fetchurl (
-      builtins.removeAttrs args ["groupId" "artifactId" "version" "repos" "url" ]
+      builtins.removeAttrs args ["groupId" "artifactId" "version" "classifier" "repos" "url" ]
         // { urls = urls_; name = "${name_}.jar"; }
     );
 in
diff --git a/nixpkgs/pkgs/build-support/fetchsvnrevision/default.nix b/nixpkgs/pkgs/build-support/fetchsvnrevision/default.nix
index 288451a225c7..f2e2a11da8d5 100644
--- a/nixpkgs/pkgs/build-support/fetchsvnrevision/default.nix
+++ b/nixpkgs/pkgs/build-support/fetchsvnrevision/default.nix
@@ -7,4 +7,4 @@ runCommand: subversion: repository:
       rev=$(echo p | svn ls -v --depth empty  ${repository} |awk '{ print $1 }')
       echo "[ \"$rev\" ]" > $out
       echo Latest revision is $rev
-    '')
\ No newline at end of file
+    '')
diff --git a/nixpkgs/pkgs/build-support/fetchurl/mirrors.nix b/nixpkgs/pkgs/build-support/fetchurl/mirrors.nix
index 0eba8816b638..b61cd9a0d902 100644
--- a/nixpkgs/pkgs/build-support/fetchurl/mirrors.nix
+++ b/nixpkgs/pkgs/build-support/fetchurl/mirrors.nix
@@ -9,10 +9,10 @@
   # "sourceforge", "gnu", etc.
 
   luarocks = [
-    "https://luarocks.org"
+    "https://luarocks.org/"
     "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/"
-    "http://luafr.org/moonrocks"
-    "http://luarocks.logiceditor.com/rocks"
+    "http://luafr.org/moonrocks/"
+    "http://luarocks.logiceditor.com/rocks/"
   ];
 
   # SourceForge.
diff --git a/nixpkgs/pkgs/build-support/fetchzip/default.nix b/nixpkgs/pkgs/build-support/fetchzip/default.nix
index c61df8ceb001..a1744b48deb9 100644
--- a/nixpkgs/pkgs/build-support/fetchzip/default.nix
+++ b/nixpkgs/pkgs/build-support/fetchzip/default.nix
@@ -44,8 +44,20 @@
       mv "$unpackDir/$fn" "$out"
     '' else ''
       mv "$unpackDir" "$out"
-    '') #*/
-    + extraPostFetch;
+    '')
+    + extraPostFetch
+    # Remove write permissions for files unpacked with write bits set
+    # Fixes https://github.com/NixOS/nixpkgs/issues/38649
+    #
+    # However, we should (for the moment) retain write permission on the directory
+    # itself, to avoid tickling https://github.com/NixOS/nix/issues/4295 in
+    # single-user Nix installations. This is because in sandbox mode we'll try to
+    # move the path, and if we don't have write permissions on the directory,
+    # then we can't update the ".." entry.
+    + ''
+      chmod -R a-w "$out"
+      chmod u+w "$out"
+    '';
 } // removeAttrs args [ "stripRoot" "extraPostFetch" ])).overrideAttrs (x: {
   # Hackety-hack: we actually need unzip hooks, too
   nativeBuildInputs = x.nativeBuildInputs ++ [ unzip ];
diff --git a/nixpkgs/pkgs/build-support/install-shell-files/default.nix b/nixpkgs/pkgs/build-support/install-shell-files/default.nix
index e1f2e24dd875..d50661ddc65d 100644
--- a/nixpkgs/pkgs/build-support/install-shell-files/default.nix
+++ b/nixpkgs/pkgs/build-support/install-shell-files/default.nix
@@ -1,4 +1,12 @@
-{ makeSetupHook }:
+{ makeSetupHook, tests }:
 
 # See the header comment in ../setup-hooks/install-shell-files.sh for example usage.
-makeSetupHook { name = "install-shell-files"; } ../setup-hooks/install-shell-files.sh
+let
+  setupHook = makeSetupHook { name = "install-shell-files"; } ../setup-hooks/install-shell-files.sh;
+in
+
+setupHook.overrideAttrs (oldAttrs: {
+  passthru = (oldAttrs.passthru or {}) // {
+    tests = tests.install-shell-files;
+  };
+})
diff --git a/nixpkgs/pkgs/build-support/kernel/initrd-compressor-meta.nix b/nixpkgs/pkgs/build-support/kernel/initrd-compressor-meta.nix
new file mode 100644
index 000000000000..443e599a239e
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/kernel/initrd-compressor-meta.nix
@@ -0,0 +1,53 @@
+rec {
+  cat = {
+    executable = pkgs: "cat";
+    ubootName = "none";
+    extension = ".cpio";
+  };
+  gzip = {
+    executable = pkgs: "${pkgs.gzip}/bin/gzip";
+    defaultArgs = ["-9n"];
+    ubootName = "gzip";
+    extension = ".gz";
+  };
+  bzip2 = {
+    executable = pkgs: "${pkgs.bzip2}/bin/bzip2";
+    ubootName = "bzip2";
+    extension = ".bz2";
+  };
+  xz = {
+    executable = pkgs: "${pkgs.xz}/bin/xz";
+    defaultArgs = ["--check=crc32" "--lzma2=dict=512KiB"];
+    extension = ".xz";
+  };
+  lzma = {
+    executable = pkgs: "${pkgs.xz}/bin/lzma";
+    defaultArgs = ["--check=crc32" "--lzma1=dict=512KiB"];
+    ubootName = "lzma";
+    extension = ".lzma";
+  };
+  lz4 = {
+    executable = pkgs: "${pkgs.lz4}/bin/lz4";
+    defaultArgs = ["-l"];
+    ubootName = "lz4";
+    extension = ".lz4";
+  };
+  lzop = {
+    executable = pkgs: "${pkgs.lzop}/bin/lzop";
+    ubootName = "lzo";
+    extension = ".lzo";
+  };
+  zstd = {
+    executable = pkgs: "${pkgs.zstd}/bin/zstd";
+    defaultArgs = ["-10"];
+    ubootName = "zstd";
+    extension = ".zst";
+  };
+  pigz = gzip // {
+    executable = pkgs: "${pkgs.pigz}/bin/pigz";
+  };
+  pixz = xz // {
+    executable = pkgs: "${pkgs.pixz}/bin/pixz";
+    defaultArgs = [];
+  };
+}
diff --git a/nixpkgs/pkgs/build-support/kernel/make-initrd.nix b/nixpkgs/pkgs/build-support/kernel/make-initrd.nix
index ed5dbdaee171..901eb311a883 100644
--- a/nixpkgs/pkgs/build-support/kernel/make-initrd.nix
+++ b/nixpkgs/pkgs/build-support/kernel/make-initrd.nix
@@ -1,22 +1,74 @@
-# Create an initial ramdisk containing the closure of the specified
-# file system objects.  An initial ramdisk is used during the initial
+# Create an initramfs containing the closure of the specified
+# file system objects.  An initramfs is used during the initial
 # stages of booting a Linux system.  It is loaded by the boot loader
 # along with the kernel image.  It's supposed to contain everything
 # (such as kernel modules) necessary to allow us to mount the root
 # file system.  Once the root file system is mounted, the `real' boot
 # script can be called.
 #
-# An initrd is really just a gzipped cpio archive.
-#
-# Symlinks are created for each top-level file system object.  E.g.,
-# `contents = {object = ...; symlink = /init;}' is a typical
-# argument.
-
-{ stdenvNoCC, perl, cpio, contents, ubootTools
+# An initramfs is a cpio archive, and may be compressed with a number
+# of algorithms.
+let
+  # Some metadata on various compression programs, relevant to naming
+  # the initramfs file and, if applicable, generating a u-boot image
+  # from it.
+  compressors = import ./initrd-compressor-meta.nix;
+  # Get the basename of the actual compression program from the whole
+  # compression command, for the purpose of guessing the u-boot
+  # compression type and filename extension.
+  compressorName = fullCommand: builtins.elemAt (builtins.match "([^ ]*/)?([^ ]+).*" fullCommand) 1;
+in
+{ stdenvNoCC, perl, cpio, ubootTools, lib, pkgsBuildHost
+# Name of the derivation (not of the resulting file!)
 , name ? "initrd"
-, compressor ? "gzip -9n"
+
+# Program used to compress the cpio archive; use "cat" for no compression.
+# This can also be a function which takes a package set and returns the path to the compressor,
+# such as `pkgs: "${pkgs.lzop}/bin/lzop"`.
+, compressor ? "gzip"
+, _compressorFunction ?
+  if lib.isFunction compressor then compressor
+  else if ! builtins.hasContext compressor && builtins.hasAttr compressor compressors then compressors.${compressor}.executable
+  else _: compressor
+, _compressorExecutable ? _compressorFunction pkgsBuildHost
+, _compressorName ? compressorName _compressorExecutable
+, _compressorMeta ? compressors.${_compressorName} or {}
+
+# List of arguments to pass to the compressor program, or null to use its defaults
+, compressorArgs ? null
+, _compressorArgsReal ? if compressorArgs == null then _compressorMeta.defaultArgs or [] else compressorArgs
+
+# Filename extension to use for the compressed initramfs. This is
+# included for clarity, but $out/initrd will always be a symlink to
+# the final image.
+# If this isn't guessed, you may want to complete the metadata above and send a PR :)
+, extension ? _compressorMeta.extension or
+    (throw "Unrecognised compressor ${_compressorName}, please specify filename extension")
+
+# List of { object = path_or_derivation; symlink = "/path"; }
+# The paths are copied into the initramfs in their nix store path
+# form, then linked at the root according to `symlink`.
+, contents
+
+# List of uncompressed cpio files to prepend to the initramfs. This
+# can be used to add files in specified paths without them becoming
+# symlinks to store paths.
 , prepend ? []
-, lib
+
+# Whether to wrap the initramfs in a u-boot image.
+, makeUInitrd ? stdenvNoCC.hostPlatform.platform.kernelTarget == "uImage"
+
+# If generating a u-boot image, the architecture to use. The default
+# guess may not align with u-boot's nomenclature correctly, so it can
+# be overridden.
+# See https://gitlab.denx.de/u-boot/u-boot/-/blob/9bfb567e5f1bfe7de8eb41f8c6d00f49d2b9a426/common/image.c#L81-106 for a list.
+, uInitrdArch ? stdenvNoCC.hostPlatform.kernelArch
+
+# The name of the compression, as recognised by u-boot.
+# See https://gitlab.denx.de/u-boot/u-boot/-/blob/9bfb567e5f1bfe7de8eb41f8c6d00f49d2b9a426/common/image.c#L195-204 for a list.
+# If this isn't guessed, you may want to complete the metadata above and send a PR :)
+, uInitrdCompression ? _compressorMeta.ubootName or
+    (throw "Unrecognised compressor ${_compressorName}, please specify uInitrdCompression")
 }:
 let
   # !!! Move this into a public lib function, it is probably useful for others
@@ -24,15 +76,26 @@ let
     lib.concatStringsSep "-" (filter (x: !(isList x)) (split "[^a-zA-Z0-9_=.?-]+" x));
 
 in stdenvNoCC.mkDerivation rec {
-  inherit name;
+  inherit name makeUInitrd extension uInitrdArch prepend;
 
-  builder = ./make-initrd.sh;
+  ${if makeUInitrd then "uinitrdCompression" else null} = uInitrdCompression;
 
-  makeUInitrd = stdenvNoCC.hostPlatform.platform.kernelTarget == "uImage";
+  builder = ./make-initrd.sh;
 
   nativeBuildInputs = [ perl cpio ]
     ++ stdenvNoCC.lib.optional makeUInitrd ubootTools;
 
+  compress = "${_compressorExecutable} ${lib.escapeShellArgs _compressorArgsReal}";
+
+  # Pass the function through, for reuse in append-initrd-secrets. The
+  # function is used instead of the string, in order to support
+  # cross-compilation (append-initrd-secrets running on a different
+  # architecture than what the main initramfs is built on).
+  passthru = {
+    compressorExecutableFunction = _compressorFunction;
+    compressorArgs = _compressorArgsReal;
+  };
+
   # !!! should use XML.
   objects = map (x: x.object) contents;
   symlinks = map (x: x.symlink) contents;
@@ -47,6 +110,4 @@ in stdenvNoCC.mkDerivation rec {
       contents
       (lib.range 0 (lib.length contents - 1));
   pathsFromGraph = ./paths-from-graph.pl;
-
-  inherit compressor prepend;
 }
diff --git a/nixpkgs/pkgs/build-support/kernel/make-initrd.sh b/nixpkgs/pkgs/build-support/kernel/make-initrd.sh
index 0aeaedeb3724..c0619ef14ae0 100644
--- a/nixpkgs/pkgs/build-support/kernel/make-initrd.sh
+++ b/nixpkgs/pkgs/build-support/kernel/make-initrd.sh
@@ -39,10 +39,13 @@ mkdir -p $out
 for PREP in $prepend; do
   cat $PREP >> $out/initrd
 done
-(cd root && find * -print0 | xargs -0r touch -h -d '@1')
-(cd root && find * -print0 | sort -z | cpio -o -H newc -R +0:+0 --reproducible --null | $compressor >> $out/initrd)
+(cd root && find * .[^.*] -exec touch -h -d '@1' '{}' +)
+(cd root && find * .[^.*] -print0 | sort -z | cpio -o -H newc -R +0:+0 --reproducible --null | eval -- $compress >> "$out/initrd")
 
 if [ -n "$makeUInitrd" ]; then
-    mv $out/initrd $out/initrd.gz
-    mkimage -A arm -O linux -T ramdisk -C gzip -d $out/initrd.gz $out/initrd
+    mkimage -A $uInitrdArch -O linux -T ramdisk -C "$uInitrdCompression" -d $out/initrd"$extension" $out/initrd.img
+    # Compatibility symlink
+    ln -s "initrd.img" "$out/initrd"
+else
+    ln -s "initrd" "$out/initrd$extension"
 fi
diff --git a/nixpkgs/pkgs/build-support/libredirect/libredirect.c b/nixpkgs/pkgs/build-support/libredirect/libredirect.c
index e7f74c736ab0..c8d6956a6bfe 100644
--- a/nixpkgs/pkgs/build-support/libredirect/libredirect.c
+++ b/nixpkgs/pkgs/build-support/libredirect/libredirect.c
@@ -121,6 +121,13 @@ FILE * fopen(const char * path, const char * mode)
     return fopen_real(rewrite(path, buf), mode);
 }
 
+FILE * __nss_files_fopen(const char * path)
+{
+    FILE * (*__nss_files_fopen_real) (const char *) = dlsym(RTLD_NEXT, "__nss_files_fopen");
+    char buf[PATH_MAX];
+    return __nss_files_fopen_real(rewrite(path, buf));
+}
+
 FILE * fopen64(const char * path, const char * mode)
 {
     FILE * (*fopen64_real) (const char *, const char *) = dlsym(RTLD_NEXT, "fopen64");
diff --git a/nixpkgs/pkgs/build-support/make-desktopitem/default.nix b/nixpkgs/pkgs/build-support/make-desktopitem/default.nix
index 8355a5ad29bc..329286bd3628 100644
--- a/nixpkgs/pkgs/build-support/make-desktopitem/default.nix
+++ b/nixpkgs/pkgs/build-support/make-desktopitem/default.nix
@@ -1,50 +1,63 @@
 { lib, runCommandLocal, desktop-file-utils }:
 
-{ name
+# See https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
+{ name # The name of the desktop file
 , type ? "Application"
 , exec
 , icon ? null
 , comment ? null
-, terminal ? "false"
-, desktopName
+, terminal ? false
+, desktopName # The name of the application
 , genericName ? null
 , mimeType ? null
 , categories ? null
 , startupNotify ? null
-, extraEntries ? null
+, extraDesktopEntries ? { } # Extra key-value pairs to add to the [Desktop Entry] section. This may override other values
+, extraEntries ? "" # Extra configuration. Will be appended to the end of the file and may thus contain extra sections
 , fileValidation ? true # whether to validate resulting desktop file.
 }:
-
 let
-  optionalEntriesList = [{k="Icon";          v=icon;}
-                         {k="Comment";       v=comment;}
-                         {k="GenericName";   v=genericName;}
-                         {k="MimeType";      v=mimeType;}
-                         {k="Categories";    v=categories;}
-                         {k="StartupNotify"; v=startupNotify;}];
+  # like builtins.toString, but null -> null instead of null -> ""
+  nullableToString = value:
+    if value == null then null
+    else if builtins.isBool value then lib.boolToString value
+    else builtins.toString value;
 
-  valueNotNull = {k, v}: v != null;
-  entriesToKeep = builtins.filter valueNotNull optionalEntriesList;
+  # The [Desktop entry] section of the desktop file, as attribute set.
+  mainSection = {
+    "Type" = toString type;
+    "Exec" = nullableToString exec;
+    "Icon" = nullableToString icon;
+    "Comment" = nullableToString comment;
+    "Terminal" = nullableToString terminal;
+    "Name" = toString desktopName;
+    "GenericName" = nullableToString genericName;
+    "MimeType" = nullableToString mimeType;
+    "Categories" = nullableToString categories;
+    "StartupNotify" = nullableToString startupNotify;
+  } // extraDesktopEntries;
 
-  mkEntry = {k, v}:  k + "=" + v;
-  optionalEntriesString  = lib.concatMapStringsSep "\n" mkEntry entriesToKeep;
+  # Map all entries to a list of lines
+  desktopFileStrings =
+    [ "[Desktop Entry]" ]
+    ++ builtins.filter
+      (v: v != null)
+      (lib.mapAttrsToList
+        (name: value: if value != null then "${name}=${value}" else null)
+        mainSection
+      )
+    ++ (if extraEntries == "" then [ ] else [ "${extraEntries}" ]);
 in
-runCommandLocal "${name}.desktop" {}
-  ''
+runCommandLocal "${name}.desktop"
+{
+  nativeBuildInputs = [ desktop-file-utils ];
+}
+  (''
     mkdir -p "$out/share/applications"
     cat > "$out/share/applications/${name}.desktop" <<EOF
-    [Desktop Entry]
-    Type=${type}
-    Exec=${exec}
-    Terminal=${terminal}
-    Name=${desktopName}
-    ${optionalEntriesString}
-    ${if extraEntries == null then ''EOF'' else ''
-    ${extraEntries}
-    EOF''}
-
-    ${lib.optionalString fileValidation ''
-      echo "Running desktop-file validation"
-      ${desktop-file-utils}/bin/desktop-file-validate "$out/share/applications/${name}.desktop"
-    ''}
-  ''
+    ${builtins.concatStringsSep "\n" desktopFileStrings}
+    EOF
+  '' + lib.optionalString fileValidation ''
+    echo "Running desktop-file validation"
+    desktop-file-validate "$out/share/applications/${name}.desktop"
+  '')
diff --git a/nixpkgs/pkgs/build-support/nix-gitignore/default.nix b/nixpkgs/pkgs/build-support/nix-gitignore/default.nix
index 28ee6bad5540..5d7b945bf1b1 100644
--- a/nixpkgs/pkgs/build-support/nix-gitignore/default.nix
+++ b/nixpkgs/pkgs/build-support/nix-gitignore/default.nix
@@ -148,10 +148,10 @@ in rec {
       '');
 
   withGitignoreFile = patterns: root:
-    lib.toList patterns ++ [(root + "/.gitignore")];
+    lib.toList patterns ++ [ ".git" ] ++ [(root + "/.gitignore")];
 
   withRecursiveGitignoreFile = patterns: root:
-    lib.toList patterns ++ [(compileRecursiveGitignore root)];
+    lib.toList patterns ++ [ ".git" ] ++ [(compileRecursiveGitignore root)];
 
   # filterSource derivatives
 
diff --git a/nixpkgs/pkgs/build-support/ocaml/dune.nix b/nixpkgs/pkgs/build-support/ocaml/dune.nix
index b134effab8ac..fce0096c83d5 100644
--- a/nixpkgs/pkgs/build-support/ocaml/dune.nix
+++ b/nixpkgs/pkgs/build-support/ocaml/dune.nix
@@ -1,4 +1,4 @@
-{ stdenv, ocaml, findlib, dune, dune_2, opaline }:
+{ stdenv, ocaml, findlib, dune, dune_2 }:
 
 { pname, version, buildInputs ? [], enableParallelBuilding ? true, ... }@args:
 
@@ -25,7 +25,7 @@ stdenv.mkDerivation ({
   '';
   installPhase = ''
     runHook preInstall
-    ${opaline}/bin/opaline -prefix $out -libdir $OCAMLFIND_DESTDIR
+    dune install --prefix $out --libdir $OCAMLFIND_DESTDIR ${pname}
     runHook postInstall
   '';
 
diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/build-crate.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/build-crate.nix
index 142109cef49f..84d1b2300f14 100644
--- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/build-crate.nix
+++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/build-crate.nix
@@ -15,7 +15,7 @@
       ++ [(mkRustcDepArgs dependencies crateRenames)]
       ++ [(mkRustcFeatureArgs crateFeatures)]
       ++ extraRustcOpts
-      ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) "--target ${rust.toRustTarget stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc"
+      ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) "--target ${rust.toRustTargetSpec stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc"
       # since rustc 1.42 the "proc_macro" crate is part of the default crate prelude
       # https://github.com/rust-lang/cargo/commit/4d64eb99a4#diff-7f98585dbf9d30aa100c8318e2c77e79R1021-R1022
       ++ lib.optional (lib.elem "proc-macro" crateType) "--extern proc_macro"
diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/configure-crate.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
index 18587f7047c4..d1010ac1adb3 100644
--- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
+++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
@@ -135,8 +135,8 @@ in ''
   export CARGO_MANIFEST_DIR=$(pwd)
   export DEBUG="${toString (!release)}"
   export OPT_LEVEL="${toString optLevel}"
-  export TARGET="${rust.toRustTarget stdenv.hostPlatform}"
-  export HOST="${rust.toRustTarget stdenv.buildPlatform}"
+  export TARGET="${rust.toRustTargetSpec stdenv.hostPlatform}"
+  export HOST="${rust.toRustTargetSpec stdenv.buildPlatform}"
   export PROFILE=${if release then "release" else "debug"}
   export OUT_DIR=$(pwd)/target/build/${crateName}.out
   export CARGO_PKG_VERSION_MAJOR=${lib.elemAt version 0}
@@ -144,7 +144,7 @@ in ''
   export CARGO_PKG_VERSION_PATCH=${lib.elemAt version 2}
   export CARGO_PKG_VERSION_PRE="${versionPre}"
   export CARGO_PKG_HOMEPAGE="${crateHomepage}"
-  export NUM_JOBS=1
+  export NUM_JOBS=$NIX_BUILD_CORES
   export RUSTC="rustc"
   export RUSTDOC="rustdoc"
 
diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/default.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/default.nix
index 1d8cd555523b..e605c9550e53 100644
--- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/default.nix
+++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/default.nix
@@ -4,7 +4,8 @@
 # This can be useful for deploying packages with NixOps, and to share
 # binary dependencies between projects.
 
-{ lib, stdenv, defaultCrateOverrides, fetchCrate, rustc, rust, cargo, jq }:
+{ lib, stdenv, defaultCrateOverrides, fetchCrate, pkgsBuildBuild, rustc, rust
+, cargo, jq }:
 
 let
     # Create rustc arguments to link against the given list of dependencies
@@ -53,6 +54,10 @@ let
    };
 
    installCrate = import ./install-crate.nix { inherit stdenv; };
+
+   # Allow access to the rust attribute set from inside buildRustCrate, which
+   # has a parameter that shadows the name.
+   rustAttrs = rust;
 in
 
 /* The overridable pkgs.buildRustCrate function.
@@ -77,6 +82,8 @@ in
    # A list of rust/cargo features to enable while building the crate.
    # Example: [ "std" "async" ]
    , features
+   # Additional native build inputs for building this crate.
+   , nativeBuildInputs
    # Additional build inputs for building this crate.
    #
    # Example: [ pkgs.openssl ]
@@ -182,12 +189,13 @@ let crate = crate_ // (lib.attrByPath [ crate_.crateName ] (attr: {}) crateOverr
     dependencies_ = dependencies;
     buildDependencies_ = buildDependencies;
     processedAttrs = [
-      "src" "buildInputs" "crateBin" "crateLib" "libName" "libPath"
+      "src" "nativeBuildInputs" "buildInputs" "crateBin" "crateLib" "libName" "libPath"
       "buildDependencies" "dependencies" "features" "crateRenames"
       "crateName" "version" "build" "authors" "colors" "edition"
       "buildTests"
     ];
     extraDerivationAttrs = builtins.removeAttrs crate processedAttrs;
+    nativeBuildInputs_ = nativeBuildInputs;
     buildInputs_ = buildInputs;
     extraRustcOpts_ = extraRustcOpts;
     buildTests_ = buildTests;
@@ -219,7 +227,8 @@ stdenv.mkDerivation (rec {
     src = crate.src or (fetchCrate { inherit (crate) crateName version sha256; });
     name = "rust_${crate.crateName}-${crate.version}${lib.optionalString buildTests_ "-test"}";
     version = crate.version;
-    depsBuildBuild = [ rust stdenv.cc cargo jq ];
+    depsBuildBuild = [ pkgsBuildBuild.stdenv.cc ];
+    nativeBuildInputs = [ rust stdenv.cc cargo jq ] ++ (crate.nativeBuildInputs or []) ++ nativeBuildInputs_;
     buildInputs = (crate.buildInputs or []) ++ buildInputs_;
     dependencies = map lib.getLib dependencies_;
     buildDependencies = map lib.getLib buildDependencies_;
@@ -245,7 +254,7 @@ stdenv.mkDerivation (rec {
       depsMetadata = lib.foldl' (str: dep: str + dep.metadata) "" (dependencies ++ buildDependencies);
       hashedMetadata = builtins.hashString "sha256"
         (crateName + "-" + crateVersion + "___" + toString (mkRustcFeatureArgs crateFeatures) +
-          "___" + depsMetadata);
+          "___" + depsMetadata + "___" + rustAttrs.toRustTarget stdenv.hostPlatform);
       in lib.substring 0 10 hashedMetadata;
 
     build = crate.build or "";
@@ -295,6 +304,7 @@ stdenv.mkDerivation (rec {
   verbose = crate_.verbose or true;
   extraRustcOpts = [];
   features = [];
+  nativeBuildInputs = [];
   buildInputs = [];
   crateOverrides = defaultCrateOverrides;
   preUnpack = crate_.preUnpack or "";
diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix
index 24ddc11459ec..65c8880b134d 100644
--- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix
+++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix
@@ -1,4 +1,5 @@
 { lib
+, buildPackages
 , buildRustCrate
 , callPackage
 , releaseTools
@@ -10,13 +11,14 @@
 }:
 
 let
-  mkCrate = args: let
+  mkCrate = buildRustCrate: args: let
     p = {
       crateName = "nixtestcrate";
       version = "0.1.0";
       authors = [ "Test <test@example.com>" ];
     } // args;
   in buildRustCrate p;
+  mkHostCrate = mkCrate buildRustCrate;
 
   mkCargoToml =
     { name, crateVersion ? "0.1.0", path ? "Cargo.toml" }:
@@ -68,15 +70,15 @@ let
   mkLib = name: mkFile name "pub fn test() -> i32 { return 23; }";
 
   mkTest = crateArgs: let
-    crate = mkCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
+    crate = mkHostCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
     hasTests = crateArgs.buildTests or false;
     expectedTestOutputs = crateArgs.expectedTestOutputs or null;
-    binaries = map (v: ''"${v.name}"'') (crateArgs.crateBin or []);
+    binaries = map (v: lib.escapeShellArg v.name) (crateArgs.crateBin or []);
     isLib = crateArgs ? libName || crateArgs ? libPath;
     crateName = crateArgs.crateName or "nixtestcrate";
     libName = crateArgs.libName or crateName;
 
-    libTestBinary = if !isLib then null else mkCrate {
+    libTestBinary = if !isLib then null else mkHostCrate {
       crateName = "run-test-${crateName}";
       dependencies = [ crate ];
       src = mkBinExtern "src/main.rs" libName;
@@ -89,18 +91,27 @@ let
       runCommand "run-buildRustCrate-${crateName}-test" {
         nativeBuildInputs = [ crate ];
       } (if !hasTests then ''
-          ${lib.concatStringsSep "\n" binaries}
+          ${lib.concatMapStringsSep "\n" (binary:
+            # Can't actually run the binary when cross-compiling
+            (lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "type ") + binary
+          ) binaries}
           ${lib.optionalString isLib ''
               test -e ${crate}/lib/*.rlib || exit 1
-              ${libTestBinary}/bin/run-test-${crateName}
+              ${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "test -x "} \
+                ${libTestBinary}/bin/run-test-${crateName}
           ''}
           touch $out
-        '' else ''
+        '' else if stdenv.hostPlatform == stdenv.buildPlatform then ''
           for file in ${crate}/tests/*; do
             $file 2>&1 >> $out
           done
           set -e
           ${lib.concatMapStringsSep "\n" (o: "grep '${o}' $out || {  echo 'output \"${o}\" not found in:'; cat $out; exit 23; }") expectedTestOutputs}
+        '' else ''
+          for file in ${crate}/tests/*; do
+            test -x "$file"
+          done
+          touch "$out"
         ''
       );
 
@@ -109,7 +120,7 @@ let
 
        `name` is used as part of the derivation name that performs the checking.
 
-       `crateArgs` is passed to `mkCrate` to build the crate with `buildRustCrate`.
+       `crateArgs` is passed to `mkHostCrate` to build the crate with `buildRustCrate`.
 
        `expectedFiles` contains a list of expected file paths in the output. E.g.
        `[ "./bin/my_binary" ]`.
@@ -124,7 +135,7 @@ let
       assert (builtins.isList expectedFiles);
 
       let
-        crate = mkCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
+        crate = mkHostCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
         crateOutput = if output == null then crate else crate."${output}";
         expectedFilesFile = writeTextFile {
           name = "expected-files-${name}";
@@ -135,12 +146,18 @@ let
         };
       in
       runCommand "assert-outputs-${name}" {
-      } ''
+      } (''
       local actualFiles=$(mktemp)
 
       cd "${crateOutput}"
-      find . -type f | sort >$actualFiles
-      diff -q ${expectedFilesFile} $actualFiles >/dev/null || {
+      find . -type f \
+        | sort \
+      ''
+      # sed out the hash because it differs per platform
+      + ''
+        | sed -E -e 's/-[0-9a-fA-F]{10}\.rlib/-HASH.rlib/g' \
+        > "$actualFiles"
+      diff -q ${expectedFilesFile} "$actualFiles" > /dev/null || {
         echo -e "\033[0;1;31mERROR: Difference in expected output files in ${crateOutput} \033[0m" >&2
         echo === Got:
         sed -e 's/^/  /' $actualFiles
@@ -153,7 +170,7 @@ let
         exit 1
       }
       touch $out
-      ''
+      '')
       ;
 
   in rec {
@@ -188,17 +205,17 @@ let
       crateBinRename1 = {
         crateBin = [{ name = "my-binary-rename1"; }];
         src = mkBinExtern "src/main.rs" "foo_renamed";
-        dependencies = [ (mkCrate { crateName = "foo"; src = mkLib "src/lib.rs"; }) ];
+        dependencies = [ (mkHostCrate { crateName = "foo"; src = mkLib "src/lib.rs"; }) ];
         crateRenames = { "foo" = "foo_renamed"; };
       };
       crateBinRename2 = {
         crateBin = [{ name = "my-binary-rename2"; }];
         src = mkBinExtern "src/main.rs" "foo_renamed";
-        dependencies = [ (mkCrate { crateName = "foo"; libName = "foolib"; src = mkLib "src/lib.rs"; }) ];
+        dependencies = [ (mkHostCrate { crateName = "foo"; libName = "foolib"; src = mkLib "src/lib.rs"; }) ];
         crateRenames = { "foo" = "foo_renamed"; };
       };
       crateBinRenameMultiVersion = let
-        crateWithVersion = version: mkCrate {
+        crateWithVersion = version: mkHostCrate {
           crateName = "my_lib";
           inherit version;
           src = mkFile "src/lib.rs" ''
@@ -307,7 +324,7 @@ let
           fn main() {}
         '';
         dependencies = [
-          (mkCrate {
+          (mkHostCrate {
             crateName = "somerlib";
             type = [ "rlib" ];
             src = mkLib "src/lib.rs";
@@ -315,7 +332,7 @@ let
         ];
       };
       buildScriptDeps = let
-        depCrate = boolVal: mkCrate {
+        depCrate = buildRustCrate: boolVal: mkCrate buildRustCrate {
           crateName = "bar";
           src = mkFile "src/lib.rs" ''
             pub const baz: bool = ${boolVal};
@@ -339,8 +356,8 @@ let
             '')
           ];
         };
-        buildDependencies = [ (depCrate "true") ];
-        dependencies = [ (depCrate "false") ];
+        buildDependencies = [ (depCrate buildPackages.buildRustCrate "true") ];
+        dependencies = [ (depCrate buildRustCrate "false") ];
         buildTests = true;
         expectedTestOutputs = [ "test baz_false ... ok" ];
       };
@@ -373,7 +390,7 @@ let
       # Regression test for https://github.com/NixOS/nixpkgs/pull/88054
       # Build script output should be rewritten as valid env vars.
       buildScriptIncludeDirDeps = let
-        depCrate = mkCrate {
+        depCrate = mkHostCrate {
           crateName = "bar";
           src = symlinkJoin {
             name = "build-script-and-include-dir-bar";
@@ -460,7 +477,7 @@ let
             mkdir -p $out/lib
             # Note: On darwin (which defaults to clang) we have to add
             # `-undefined dynamic_lookup` as otherwise the compilation fails.
-            cc -shared \
+            $CC -shared \
               ${lib.optionalString stdenv.isDarwin "-undefined dynamic_lookup"} \
               -o $out/lib/${name}${stdenv.hostPlatform.extensions.sharedLibrary} ${src}
           '';
@@ -583,7 +600,7 @@ let
       };
       expectedFiles = [
         "./nix-support/propagated-build-inputs"
-        "./lib/libtest_lib-042a1fdbef.rlib"
+        "./lib/libtest_lib-HASH.rlib"
         "./lib/link"
       ];
     };
@@ -600,7 +617,7 @@ let
       };
       expectedFiles = [
         "./nix-support/propagated-build-inputs"
-        "./lib/libtest_lib-042a1fdbef.rlib"
+        "./lib/libtest_lib-HASH.rlib"
         "./lib/link"
       ];
     };
@@ -609,9 +626,11 @@ let
       pkg = brotliCrates.brotli_2_5_0 {};
     in runCommand "run-brotli-test-cmd" {
       nativeBuildInputs = [ pkg ];
-    } ''
+    } (if stdenv.hostPlatform == stdenv.buildPlatform then ''
       ${pkg}/bin/brotli -c ${pkg}/bin/brotli > /dev/null && touch $out
-    '';
+    '' else ''
+      test -x '${pkg}/bin/brotli' && touch $out
+    '');
     allocNoStdLibTest = let
       pkg = brotliCrates.alloc_no_stdlib_1_3_0 {};
     in runCommand "run-alloc-no-stdlib-test-cmd" {
diff --git a/nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix b/nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix
index 1c4fe9daeada..d0e69ad698a8 100644
--- a/nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix
+++ b/nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix
@@ -16,18 +16,21 @@ in
   };
 
   libz-sys = attrs: {
-    buildInputs = [ pkgconfig zlib ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ zlib ];
     extraLinkFlags = ["-L${zlib.out}/lib"];
   };
 
   curl-sys = attrs: {
-    buildInputs = [ pkgconfig zlib curl ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ zlib curl ];
     propagatedBuildInputs = [ curl zlib ];
     extraLinkFlags = ["-L${zlib.out}/lib"];
   };
 
   dbus = attrs: {
-    buildInputs = [ pkgconfig dbus ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ dbus ];
   };
 
   foundationdb-sys = attrs: {
@@ -62,19 +65,23 @@ in
 
   libgit2-sys = attrs: {
     LIBGIT2_SYS_USE_PKG_CONFIG = true;
-    buildInputs = [ pkgconfig openssl zlib libgit2 ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ openssl zlib libgit2 ];
   };
 
   libsqlite3-sys = attrs: {
-    buildInputs = [ pkgconfig sqlite ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ sqlite ];
   };
 
   libssh2-sys = attrs: {
-    buildInputs = [ pkgconfig openssl zlib libssh2 ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ openssl zlib libssh2 ];
   };
 
   libdbus-sys = attrs: {
-    buildInputs = [ pkgconfig dbus ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ dbus ];
   };
 
   openssl = attrs: {
@@ -82,11 +89,13 @@ in
   };
 
   openssl-sys = attrs: {
-    buildInputs = [ pkgconfig openssl ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ openssl ];
   };
 
   pq-sys = attr: {
-    buildInputs = [ pkgconfig postgresql ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ postgresql ];
   };
 
   rink = attrs: {
@@ -103,7 +112,8 @@ in
   };
 
   thrussh-libsodium = attrs: {
-    buildInputs = [ pkgconfig libsodium ];
+    nativeBuildInputs = [ pkgconfig ];
+    buildInputs = [ libsodium ];
   };
 
   xcb = attrs: {
diff --git a/nixpkgs/pkgs/build-support/rust/default.nix b/nixpkgs/pkgs/build-support/rust/default.nix
index 6ea1dc27dd85..47a7aa8cda9d 100644
--- a/nixpkgs/pkgs/build-support/rust/default.nix
+++ b/nixpkgs/pkgs/build-support/rust/default.nix
@@ -4,6 +4,10 @@
 , cargo
 , diffutils
 , fetchCargoTarball
+, runCommandNoCC
+, rustPlatform
+, callPackage
+, remarshal
 , git
 , rust
 , rustc
@@ -13,7 +17,13 @@
 let
   buildRustPackage =
     { name ? "${args.pname}-${args.version}"
-    , cargoSha256 ? "unset"
+
+      # SRI hash
+    , cargoHash ? ""
+
+      # Legacy hash
+    , cargoSha256 ? ""
+
     , src ? null
     , srcs ? null
     , unpackPhase ? null
@@ -28,12 +38,15 @@ let
     , cargoBuildFlags ? []
     , buildType ? "release"
     , meta ? {}
-    , target ? null
+    , target ? rust.toRustTargetSpec stdenv.hostPlatform
     , cargoVendorDir ? null
     , checkType ? buildType
     , depsExtraArgs ? {}
     , cargoParallelTestThreads ? true
 
+    # Toggles whether a custom sysroot is created when the target is a .json file.
+    , __internal_dontAddSysroot ? false
+
     # Needed to `pushd`/`popd` into a subdir of a tarball if this subdir
     # contains a Cargo.toml, but isn't part of a workspace (which is e.g. the
     # case for `rustfmt`/etc from the `rust-sources).
@@ -41,7 +54,7 @@ let
     , buildAndTestSubdir ? null
     , ... } @ args:
 
-    assert cargoVendorDir == null -> cargoSha256 != "unset";
+    assert cargoVendorDir == null -> !(cargoSha256 == "" && cargoHash == "");
     assert buildType == "release" || buildType == "debug";
 
     let
@@ -49,6 +62,7 @@ let
       cargoDeps = if cargoVendorDir == null
         then fetchCargoTarball ({
             inherit name src srcs sourceRoot unpackPhase cargoUpdateHook;
+            hash = cargoHash;
             patches = cargoPatches;
             sha256 = cargoSha256;
           } // depsExtraArgs)
@@ -56,7 +70,7 @@ let
 
       # If we have a cargoSha256 fixed-output derivation, validate it at build time
       # against the src fixed-output derivation to check consistency.
-      validateCargoDeps = cargoSha256 != "unset";
+      validateCargoDeps = !(cargoHash == "" && cargoSha256 == "");
 
       # Some cargo builds include build hooks that modify their own vendor
       # dependencies. This copies the vendor directory into the build tree and makes
@@ -71,13 +85,26 @@ let
           cargoDepsCopy="$sourceRoot/${cargoVendorDir}"
         '';
 
-      rustTarget = if target == null then rust.toRustTarget stdenv.hostPlatform else target;
+      targetIsJSON = stdenv.lib.hasSuffix ".json" target;
+      useSysroot = targetIsJSON && !__internal_dontAddSysroot;
+
+      # see https://github.com/rust-lang/cargo/blob/964a16a28e234a3d397b2a7031d4ab4a428b1391/src/cargo/core/compiler/compile_kind.rs#L151-L168
+      # the "${}" is needed to transform the path into a /nix/store path before baseNameOf
+      shortTarget = if targetIsJSON then
+          (stdenv.lib.removeSuffix ".json" (builtins.baseNameOf "${target}"))
+        else target;
+
+      sysroot = (callPackage ./sysroot {}) {
+        inherit target shortTarget;
+        RUSTFLAGS = args.RUSTFLAGS or "";
+        originalCargoToml = src + /Cargo.toml; # profile info is later extracted
+      };
 
       ccForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc";
       cxxForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}c++";
       ccForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
       cxxForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++";
-      releaseDir = "target/${rustTarget}/${buildType}";
+      releaseDir = "target/${shortTarget}/${buildType}";
       tmpDir = "${releaseDir}-tmp";
 
       # Specify the stdenv's `diff` by abspath to ensure that the user's build
@@ -87,7 +114,13 @@ let
 
     in
 
-    stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // {
+    # Tests don't currently work for `no_std`, and all custom sysroots are currently built without `std`.
+    # See https://os.phil-opp.com/testing/ for more information.
+    assert useSysroot -> !(args.doCheck or true);
+
+    stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // stdenv.lib.optionalAttrs useSysroot {
+      RUSTFLAGS = "--sysroot ${sysroot} " + (args.RUSTFLAGS or "");
+    } // {
       inherit cargoDeps;
 
       patchRegistryDeps = ./patch-registry-deps;
@@ -117,7 +150,7 @@ let
         [target."${rust.toRustTarget stdenv.buildPlatform}"]
         "linker" = "${ccForBuild}"
         ${stdenv.lib.optionalString (stdenv.buildPlatform.config != stdenv.hostPlatform.config) ''
-        [target."${rustTarget}"]
+        [target."${shortTarget}"]
         "linker" = "${ccForHost}"
         ${# https://github.com/rust-lang/rust/issues/46651#issuecomment-433611633
           stdenv.lib.optionalString (stdenv.hostPlatform.isMusl && stdenv.hostPlatform.isAarch64) ''
@@ -187,7 +220,7 @@ let
           "CXX_${rust.toRustTarget stdenv.hostPlatform}"="${cxxForHost}" \
           cargo build -j $NIX_BUILD_CORES \
             ${stdenv.lib.optionalString (buildType == "release") "--release"} \
-            --target ${rustTarget} \
+            --target ${target} \
             --frozen ${concatStringsSep " " cargoBuildFlags}
         )
 
@@ -207,7 +240,7 @@ let
       '';
 
       checkPhase = args.checkPhase or (let
-        argstr = "${stdenv.lib.optionalString (checkType == "release") "--release"} --target ${rustTarget} --frozen";
+        argstr = "${stdenv.lib.optionalString (checkType == "release") "--release"} --target ${target} --frozen";
         threads = if cargoParallelTestThreads then "$NIX_BUILD_CORES" else "1";
       in ''
         ${stdenv.lib.optionalString (buildAndTestSubdir != null) "pushd ${buildAndTestSubdir}"}
diff --git a/nixpkgs/pkgs/build-support/rust/fetchCargoTarball.nix b/nixpkgs/pkgs/build-support/rust/fetchCargoTarball.nix
index dff5d99da9eb..0726e5cfa5a1 100644
--- a/nixpkgs/pkgs/build-support/rust/fetchCargoTarball.nix
+++ b/nixpkgs/pkgs/build-support/rust/fetchCargoTarball.nix
@@ -22,11 +22,17 @@ in
 , srcs ? []
 , patches ? []
 , sourceRoot
-, sha256
+, hash ? ""
+, sha256 ? ""
 , cargoUpdateHook ? ""
 , ...
 } @ args:
-stdenv.mkDerivation ({
+
+let hash_ =
+  if hash != "" then { outputHashAlgo = null; outputHash = hash; }
+  else if sha256 != "" then { outputHashAlgo = "sha256"; outputHash = sha256; }
+  else throw "fetchCargoTarball requires a hash for ${name}";
+in stdenv.mkDerivation ({
   name = "${name}-vendor.tar.gz";
   nativeBuildInputs = [ cacert git cargo-vendor-normalise cargo ];
 
@@ -40,7 +46,7 @@ stdenv.mkDerivation ({
         echo
         echo "ERROR: The Cargo.lock file doesn't exist"
         echo
-        echo "Cargo.lock is needed to make sure that cargoSha256 doesn't change"
+        echo "Cargo.lock is needed to make sure that cargoHash/cargoSha256 doesn't change"
         echo "when the registry is updated."
         echo
 
@@ -72,8 +78,7 @@ stdenv.mkDerivation ({
         -czf $out $name
   '';
 
-  outputHashAlgo = "sha256";
-  outputHash = sha256;
+  inherit (hash_) outputHashAlgo outputHash;
 
   impureEnvVars = stdenv.lib.fetchers.proxyImpureEnvVars;
 } // (builtins.removeAttrs args [
diff --git a/nixpkgs/pkgs/build-support/rust/sysroot/Cargo.lock b/nixpkgs/pkgs/build-support/rust/sysroot/Cargo.lock
new file mode 100644
index 000000000000..61fcef61744e
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/sysroot/Cargo.lock
@@ -0,0 +1,29 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "alloc"
+version = "0.0.0"
+dependencies = [
+ "compiler_builtins",
+ "core",
+]
+
+[[package]]
+name = "compiler_builtins"
+version = "0.1.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cd0782e0a7da7598164153173e5a5d4d9b1da094473c98dce0ff91406112369"
+dependencies = [
+ "rustc-std-workspace-core",
+]
+
+[[package]]
+name = "core"
+version = "0.0.0"
+
+[[package]]
+name = "rustc-std-workspace-core"
+version = "1.99.0"
+dependencies = [
+ "core",
+]
diff --git a/nixpkgs/pkgs/build-support/rust/sysroot/cargo.py b/nixpkgs/pkgs/build-support/rust/sysroot/cargo.py
new file mode 100644
index 000000000000..09f6fba6d1c8
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/sysroot/cargo.py
@@ -0,0 +1,45 @@
+import os
+import toml
+
+rust_src = os.environ['RUSTC_SRC']
+orig_cargo = os.environ['ORIG_CARGO'] if 'ORIG_CARGO' in os.environ else None
+
+base = {
+  'package': {
+    'name': 'alloc',
+    'version': '0.0.0',
+    'authors': ['The Rust Project Developers'],
+    'edition': '2018',
+  },
+  'dependencies': {
+    'compiler_builtins': {
+      'version': '0.1.0',
+      'features': ['rustc-dep-of-std', 'mem'],
+    },
+    'core': {
+      'path': os.path.join(rust_src, 'libcore'),
+    },
+  },
+  'lib': {
+    'name': 'alloc',
+    'path': os.path.join(rust_src, 'liballoc/lib.rs'),
+  },
+  'patch': {
+    'crates-io': {
+      'rustc-std-workspace-core': {
+        'path': os.path.join(rust_src, 'tools/rustc-std-workspace-core'),
+      },
+    },
+  },
+}
+
+if orig_cargo is not None:
+  with open(orig_cargo, 'r') as f:
+    src = toml.loads(f.read())
+    if 'profile' in src:
+      base['profile'] = src['profile']
+
+out = toml.dumps(base)
+
+with open('Cargo.toml', 'x') as f:
+  f.write(out)
diff --git a/nixpkgs/pkgs/build-support/rust/sysroot/default.nix b/nixpkgs/pkgs/build-support/rust/sysroot/default.nix
new file mode 100644
index 000000000000..4db7cf0dc392
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/sysroot/default.nix
@@ -0,0 +1,41 @@
+{ stdenv, rust, rustPlatform, buildPackages }:
+
+{ shortTarget, originalCargoToml, target, RUSTFLAGS }:
+
+let
+  cargoSrc = stdenv.mkDerivation {
+    name = "cargo-src";
+    preferLocalBuild = true;
+    phases = [ "installPhase" ];
+    installPhase = ''
+      RUSTC_SRC=${rustPlatform.rustcSrc.override { minimalContent = false; }} ORIG_CARGO=${originalCargoToml} \
+        ${buildPackages.python3.withPackages (ps: with ps; [ toml ])}/bin/python3 ${./cargo.py}
+      mkdir -p $out
+      cp Cargo.toml $out/Cargo.toml
+      cp ${./Cargo.lock} $out/Cargo.lock
+    '';
+  };
+in rustPlatform.buildRustPackage {
+  inherit target RUSTFLAGS;
+
+  name = "custom-sysroot";
+  src =  cargoSrc;
+
+  RUSTC_BOOTSTRAP = 1;
+  __internal_dontAddSysroot = true;
+  cargoSha256 = "0y6dqfhsgk00y3fv5bnjzk0s7i30nwqc1rp0xlrk83hkh80x81mw";
+
+  doCheck = false;
+
+  installPhase = ''
+    export LIBS_DIR=$out/lib/rustlib/${shortTarget}/lib
+    mkdir -p $LIBS_DIR
+    for f in target/${shortTarget}/release/deps/*.{rlib,rmeta}; do
+      cp $f $LIBS_DIR
+    done
+
+    export RUST_SYSROOT=$(rustc --print=sysroot)
+    host=${rust.toRustTarget stdenv.buildPlatform}
+    cp -r $RUST_SYSROOT/lib/rustlib/$host $out
+  '';
+}
diff --git a/nixpkgs/pkgs/build-support/rust/sysroot/update-lockfile.sh b/nixpkgs/pkgs/build-support/rust/sysroot/update-lockfile.sh
new file mode 100755
index 000000000000..83d29832384f
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/sysroot/update-lockfile.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -i bash -p python3 python3.pkgs.toml cargo
+
+set -e
+
+HERE=$(dirname "${BASH_SOURCE[0]}")
+NIXPKGS_ROOT="$HERE/../../../.."
+
+# https://unix.stackexchange.com/a/84980/390173
+tempdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'update-lockfile')
+
+cd "$tempdir"
+nix-build -E "with import (/. + \"${NIXPKGS_ROOT}\") {}; pkgs.rustPlatform.rustcSrc.override { minimalContent = false; }"
+RUSTC_SRC="$(pwd)/result" python3 "$HERE/cargo.py"
+RUSTC_BOOTSTRAP=1 cargo build || echo "Build failure is expected. All that's needed is the lockfile."
+
+cp Cargo.lock "$HERE"
+
+rm -rf "$tempdir"
+
+
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.sh b/nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.sh
index 4f7c0c14304c..511371931de8 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.sh
+++ b/nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.sh
@@ -1,9 +1,20 @@
+#!/usr/bin/env bash
+
 declare -a autoPatchelfLibs
+declare -Ag autoPatchelfFailedDeps
 
 gatherLibraries() {
     autoPatchelfLibs+=("$1/lib")
 }
 
+# wrapper around patchelf to raise proper error messages
+# containing the tried file name and command
+runPatchelf() {
+  patchelf "$@" || (echo "Command failed: patchelf $*" && exit 1)
+}
+
+# shellcheck disable=SC2154
+# (targetOffset is referenced but not assigned.)
 addEnvHooks "$targetOffset" gatherLibraries
 
 isExecutable() {
@@ -23,14 +34,19 @@ isExecutable() {
 
 # We cache dependencies so that we don't need to search through all of them on
 # every consecutive call to findDependency.
-declare -a cachedDependencies
+declare -Ag autoPatchelfCachedDepsAssoc
+declare -ag autoPatchelfCachedDeps
+
 
 addToDepCache() {
-    local existing
-    for existing in "${cachedDependencies[@]}"; do
-        if [ "$existing" = "$1" ]; then return; fi
-    done
-    cachedDependencies+=("$1")
+    if [[ ${autoPatchelfCachedDepsAssoc[$1]+f} ]]; then return; fi
+
+    # store deps in an assoc. array for efficient lookups
+    # otherwise findDependency would have quadratic complexity
+    autoPatchelfCachedDepsAssoc["$1"]=""
+
+    # also store deps in normal array to maintain their order
+    autoPatchelfCachedDeps+=("$1")
 }
 
 declare -gi depCacheInitialised=0
@@ -43,9 +59,8 @@ getDepsFromSo() {
 
 populateCacheWithRecursiveDeps() {
     local so found foundso
-    for so in "${cachedDependencies[@]}"; do
+    for so in "${autoPatchelfCachedDeps[@]}"; do
         for found in $(getDepsFromSo "$so"); do
-            local libdir="${found%/*}"
             local base="${found##*/}"
             local soname="${base%.so*}"
             for foundso in "${found%/*}/$soname".so*; do
@@ -76,7 +91,7 @@ findDependency() {
         depCacheInitialised=1
     fi
 
-    for dep in "${cachedDependencies[@]}"; do
+    for dep in "${autoPatchelfCachedDeps[@]}"; do
         if [ "$filename" = "${dep##*/}" ]; then
             if [ "$(getSoArch "$dep")" = "$arch" ]; then
                 foundDependency="$dep"
@@ -101,9 +116,12 @@ findDependency() {
 autoPatchelfFile() {
     local dep rpath="" toPatch="$1"
 
-    local interpreter="$(< "$NIX_CC/nix-support/dynamic-linker")"
+    local interpreter
+    interpreter="$(< "$NIX_CC/nix-support/dynamic-linker")"
     if isExecutable "$toPatch"; then
-        patchelf --set-interpreter "$interpreter" "$toPatch"
+        runPatchelf --set-interpreter "$interpreter" "$toPatch"
+        # shellcheck disable=SC2154
+        # (runtimeDependencies is referenced but not assigned.)
         if [ -n "$runtimeDependencies" ]; then
             for dep in $runtimeDependencies; do
                 rpath="$rpath${rpath:+:}$dep/lib"
@@ -115,17 +133,19 @@ autoPatchelfFile() {
 
     # We're going to find all dependencies based on ldd output, so we need to
     # clear the RPATH first.
-    patchelf --remove-rpath "$toPatch"
+    runPatchelf --remove-rpath "$toPatch"
 
-    local missing="$(
+    # If the file is not a dynamic executable, ldd/sed will fail,
+    # in which case we return, since there is nothing left to do.
+    local missing
+    missing="$(
         ldd "$toPatch" 2> /dev/null | \
             sed -n -e 's/^[\t ]*\([^ ]\+\) => not found.*/\1/p'
-    )"
+    )" || return 0
 
     # This ensures that we get the output of all missing dependencies instead
     # of failing at the first one, because it's more useful when working on a
     # new package where you don't yet know its dependencies.
-    local -i depNotFound=0
 
     for dep in $missing; do
         echo -n "  $dep -> " >&2
@@ -134,18 +154,13 @@ autoPatchelfFile() {
             echo "found: $foundDependency" >&2
         else
             echo "not found!" >&2
-            depNotFound=1
+            autoPatchelfFailedDeps["$dep"]="$toPatch"
         fi
     done
 
-    # This makes sure the builder fails if we didn't find a dependency, because
-    # the stdenv setup script is run with set -e. The actual error is emitted
-    # earlier in the previous loop.
-    [ $depNotFound -eq 0 -o -n "$autoPatchelfIgnoreMissingDeps" ]
-
     if [ -n "$rpath" ]; then
         echo "setting RPATH to: $rpath" >&2
-        patchelf --set-rpath "$rpath" "$toPatch"
+        runPatchelf --set-rpath "$rpath" "$toPatch"
     fi
 }
 
@@ -168,10 +183,10 @@ addAutoPatchelfSearchPath() {
         esac
     done
 
-    cachedDependencies+=(
-        $(find "$@" "${findOpts[@]}" \! -type d \
-               \( -name '*.so' -o -name '*.so.*' \))
-    )
+    while IFS= read -r -d '' file; do
+    addToDepCache "$file"
+    done <  <(find "$@" "${findOpts[@]}" \! -type d \
+            \( -name '*.so' -o -name '*.so.*' \) -print0)
 }
 
 autoPatchelf() {
@@ -197,14 +212,9 @@ autoPatchelf() {
     echo "automatically fixing dependencies for ELF files" >&2
 
     # Add all shared objects of the current output path to the start of
-    # cachedDependencies so that it's choosen first in findDependency.
+    # autoPatchelfCachedDeps so that it's chosen first in findDependency.
     addAutoPatchelfSearchPath ${norecurse:+--no-recurse} -- "$@"
 
-    # Here we actually have a subshell, which also means that
-    # $cachedDependencies is final at this point, so whenever we want to run
-    # findDependency outside of this, the dependency cache needs to be rebuilt
-    # from scratch, so keep this in mind if you want to run findDependency
-    # outside of this function.
     while IFS= read -r -d $'\0' file; do
       isELF "$file" || continue
       segmentHeaders="$(LANG=C $READELF -l "$file")"
@@ -215,8 +225,26 @@ autoPatchelf() {
           # Skip if the executable is statically linked.
           [ -n "$(echo "$segmentHeaders" | grep "^ *INTERP\\>")" ] || continue
       fi
+      # Jump file if patchelf is unable to parse it
+      # Some programs contain binary blobs for testing,
+      # which are identified as ELF but fail to be parsed by patchelf
+      patchelf "$file" || continue
       autoPatchelfFile "$file"
     done < <(find "$@" ${norecurse:+-maxdepth 1} -type f -print0)
+
+    # fail if any dependencies were not found and
+    # autoPatchelfIgnoreMissingDeps is not set
+    local depsMissing=0
+    for failedDep in "${!autoPatchelfFailedDeps[@]}"; do
+      echo "autoPatchelfHook could not satisfy dependency $failedDep wanted by ${autoPatchelfFailedDeps[$failedDep]}"
+      depsMissing=1
+    done
+    # shellcheck disable=SC2154
+    # (autoPatchelfIgnoreMissingDeps is referenced but not assigned.)
+    if [[ $depsMissing == 1 && -z "$autoPatchelfIgnoreMissingDeps" ]]; then
+      echo "Add the missing dependencies to the build inputs or set autoPatchelfIgnoreMissingDeps=true"
+      exit 1
+    fi
 }
 
 # XXX: This should ultimately use fixupOutputHooks but we currently don't have
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/compress-man-pages.sh b/nixpkgs/pkgs/build-support/setup-hooks/compress-man-pages.sh
index 82e48cd8aa77..f5af76e8168f 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/compress-man-pages.sh
+++ b/nixpkgs/pkgs/build-support/setup-hooks/compress-man-pages.sh
@@ -21,6 +21,7 @@ compressManPages() {
 
     # Point symlinks to compressed manpages.
     find "$dir"/share/man/ -type l -a '!' -regex '.*\.\(bz2\|gz\)$' -print0 \
+        | sort -z \
         | while IFS= read -r -d $'\0' f
     do
         local target
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/copy-desktop-items.sh b/nixpkgs/pkgs/build-support/setup-hooks/copy-desktop-items.sh
new file mode 100644
index 000000000000..f96a10f33d5c
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/setup-hooks/copy-desktop-items.sh
@@ -0,0 +1,42 @@
+# shellcheck shell=bash
+
+# Setup hook that installs specified desktop items.
+#
+# Example usage in a derivation:
+#
+#   { …, makeDesktopItem, copyDesktopItems, … }:
+#
+#   let desktopItem = makeDesktopItem { … }; in
+#   stdenv.mkDerivation {
+#     …
+#     nativeBuildInputs = [ copyDesktopItems ];
+#
+#     desktopItems =  [ desktopItem ];
+#     …
+#   }
+#
+# This hook will copy files which are either given by full path
+# or all '*.desktop' files placed inside the 'share/applications'
+# folder of each `desktopItems` argument.
+
+postInstallHooks+=(copyDesktopItems)
+
+copyDesktopItems() {
+    if [ "${dontCopyDesktopItems-}" = 1 ]; then return; fi
+
+    if [ -z "$desktopItems" ]; then
+        return
+    fi
+
+    for desktopItem in $desktopItems; do
+        if [[ -f "$desktopItem" ]]; then
+            echo "Copying '$f' into '$out/share/applications'"
+            install -D -m 444 -t "$out"/share/applications "$f"
+        else
+            for f in "$desktopItem"/share/applications/*.desktop; do
+                echo "Copying '$f' into '$out/share/applications'"
+                install -D -m 444 -t "$out"/share/applications "$f"
+            done
+        fi
+    done
+}
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/install-shell-files.sh b/nixpkgs/pkgs/build-support/setup-hooks/install-shell-files.sh
index e0ea1f7f30a7..194b408b1050 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/install-shell-files.sh
+++ b/nixpkgs/pkgs/build-support/setup-hooks/install-shell-files.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+# shellcheck shell=bash
 # Setup hook for the `installShellFiles` package.
 #
 # Example usage in a derivation:
@@ -19,8 +19,8 @@
 # installManPage <path> [...<path>]
 #
 # Each argument is checked for its man section suffix and installed into the appropriate
-# share/man<n>/ directory. The function returns an error if any paths don't have the man section
-# suffix (with optional .gz compression).
+# share/man/man<n>/ directory. The function returns an error if any paths don't have the man
+# section suffix (with optional .gz compression).
 installManPage() {
     local path
     for path in "$@"; do
@@ -49,7 +49,7 @@ installManPage() {
     done
 }
 
-# installShellCompletion [--bash|--fish|--zsh] ([--name <name>] <path>)...
+# installShellCompletion [--cmd <name>] ([--bash|--fish|--zsh] [--name <name>] <path>)...
 #
 # Each path is installed into the appropriate directory for shell completions for the given shell.
 # If one of `--bash`, `--fish`, or `--zsh` is given the path is assumed to belong to that shell.
@@ -61,9 +61,20 @@ installManPage() {
 # If the shell completion needs to be renamed before installing the optional `--name <name>` flag
 # may be given. Any name provided with this flag only applies to the next path.
 #
+# If all shell completions need to be renamed before installing the optional `--cmd <name>` flag
+# may be given. This will synthesize a name for each file, unless overridden with an explicit
+# `--name` flag. For example, `--cmd foobar` will synthesize the name `_foobar` for zsh and
+# `foobar.bash` for bash.
+#
 # For zsh completions, if the `--name` flag is not given, the path will be automatically renamed
 # such that `foobar.zsh` becomes `_foobar`.
 #
+# A path may be a named fd, such as produced by the bash construct `<(cmd)`. When using a named fd,
+# the shell type flag must be provided, and either the `--name` or `--cmd` flag must be provided.
+# This might look something like:
+#
+#   installShellCompletion --zsh --name _foobar <($out/bin/foobar --zsh-completion)
+#
 # This command accepts multiple shell flags in conjunction with multiple paths if you wish to
 # install them all in one command:
 #
@@ -76,9 +87,16 @@ installManPage() {
 #   installShellCompletion --fish --name foobar.fish share/completions.fish
 #   installShellCompletion --zsh --name _foobar share/completions.zsh
 #
+# Or to use shell newline escaping to split a single invocation across multiple lines:
+#
+#   installShellCompletion --cmd foobar \
+#     --bash <($out/bin/foobar --bash-completion) \
+#     --fish <($out/bin/foobar --fish-completion) \
+#     --zsh <($out/bin/foobar --zsh-completion)
+#
 # If any argument is `--` the remaining arguments will be treated as paths.
 installShellCompletion() {
-    local shell='' name='' retval=0 parseArgs=1 arg
+    local shell='' name='' cmdname='' retval=0 parseArgs=1 arg
     while { arg=$1; shift; }; do
         # Parse arguments
         if (( parseArgs )); then
@@ -97,6 +115,17 @@ installShellCompletion() {
                 # treat `--name=foo` the same as `--name foo`
                 name=${arg#--name=}
                 continue;;
+            --cmd)
+                cmdname=$1
+                shift || {
+                    echo 'installShellCompletion: error: --cmd flag expected an argument' >&2
+                    return 1
+                }
+                continue;;
+            --cmd=*)
+                # treat `--cmd=foo` the same as `--cmd foo`
+                cmdname=${arg#--cmd=}
+                continue;;
             --?*)
                 echo "installShellCompletion: warning: unknown flag ${arg%%=*}" >&2
                 retval=2
@@ -110,39 +139,67 @@ installShellCompletion() {
         if (( "${NIX_DEBUG:-0}" >= 1 )); then
             echo "installShellCompletion: installing $arg${name:+ as $name}"
         fi
-        # if we get here, this is a path
-        # Identify shell
-        local basename
-        basename=$(stripHash "$arg")
+        # if we get here, this is a path or named pipe
+        # Identify shell and output name
         local curShell=$shell
-        if [[ -z "$curShell" ]]; then
-            # auto-detect the shell
-            case "$basename" in
-            ?*.bash) curShell=bash;;
-            ?*.fish) curShell=fish;;
-            ?*.zsh) curShell=zsh;;
+        local outName=''
+        if [[ -z "$arg" ]]; then
+            echo "installShellCompletion: error: empty path is not allowed" >&2
+            return 1
+        elif [[ -p "$arg" ]]; then
+            # this is a named fd or fifo
+            if [[ -z "$curShell" ]]; then
+                echo "installShellCompletion: error: named pipe requires one of --bash, --fish, or --zsh" >&2
+                return 1
+            elif [[ -z "$name" && -z "$cmdname" ]]; then
+                echo "installShellCompletion: error: named pipe requires one of --cmd or --name" >&2
+                return 1
+            fi
+        else
+            # this is a path
+            local argbase
+            argbase=$(stripHash "$arg")
+            if [[ -z "$curShell" ]]; then
+                # auto-detect the shell
+                case "$argbase" in
+                ?*.bash) curShell=bash;;
+                ?*.fish) curShell=fish;;
+                ?*.zsh) curShell=zsh;;
+                *)
+                    if [[ "$argbase" = _* && "$argbase" != *.* ]]; then
+                        # probably zsh
+                        echo "installShellCompletion: warning: assuming path \`$arg' is zsh; please specify with --zsh" >&2
+                        curShell=zsh
+                    else
+                        echo "installShellCompletion: warning: unknown shell for path: $arg" >&2
+                        retval=2
+                        continue
+                    fi;;
+                esac
+            fi
+            outName=$argbase
+        fi
+        # Identify output path
+        if [[ -n "$name" ]]; then
+            outName=$name
+        elif [[ -n "$cmdname" ]]; then
+            case "$curShell" in
+            bash|fish) outName=$cmdname.$curShell;;
+            zsh) outName=_$cmdname;;
             *)
-                if [[ "$basename" = _* && "$basename" != *.* ]]; then
-                    # probably zsh
-                    echo "installShellCompletion: warning: assuming path \`$arg' is zsh; please specify with --zsh" >&2
-                    curShell=zsh
-                else
-                    echo "installShellCompletion: warning: unknown shell for path: $arg" >&2
-                    retval=2
-                    continue
-                fi;;
+                # Our list of shells is out of sync with the flags we accept or extensions we detect.
+                echo 'installShellCompletion: internal error' >&2
+                return 1;;
             esac
         fi
-        # Identify output path
-        local outName sharePath
-        outName=${name:-$basename}
+        local sharePath
         case "$curShell" in
         bash) sharePath=bash-completion/completions;;
         fish) sharePath=fish/vendor_completions.d;;
         zsh)
             sharePath=zsh/site-functions
             # only apply automatic renaming if we didn't have a manual rename
-            if test -z "$name"; then
+            if [[ -z "$name" && -z "$cmdname" ]]; then
                 # convert a name like `foo.zsh` into `_foo`
                 outName=${outName%.zsh}
                 outName=_${outName#_}
@@ -153,8 +210,16 @@ installShellCompletion() {
             return 1;;
         esac
         # Install file
-        install -Dm644 -T "$arg" "${!outputBin:?}/share/$sharePath/$outName" || return
-        # Clear the name, it only applies to one path
+        local outDir="${!outputBin:?}/share/$sharePath"
+        local outPath="$outDir/$outName"
+        if [[ -p "$arg" ]]; then
+            # install handles named pipes on NixOS but not on macOS
+            mkdir -p "$outDir" \
+            && cat "$arg" > "$outPath"
+        else
+            install -Dm644 -T "$arg" "$outPath"
+        fi || return
+        # Clear the per-path flags
         name=
     done
     if [[ -n "$name" ]]; then
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/move-systemd-user-units.sh b/nixpkgs/pkgs/build-support/setup-hooks/move-systemd-user-units.sh
new file mode 100755
index 000000000000..5963d87c7515
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/setup-hooks/move-systemd-user-units.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+# This setup hook, for each output, moves everything in
+# $output/lib/systemd/user to $output/share/systemd/user, and replaces
+# $output/lib/systemd/user with a symlink to
+# $output/share/systemd/user.
+
+fixupOutputHooks+=(_moveSystemdUserUnits)
+
+_moveSystemdUserUnits() {
+    if [ "${dontMoveSystemdUserUnits:-0}" = 1 ]; then return; fi
+    if [ ! -e "${prefix:?}/lib/systemd/user" ]; then return; fi
+    local source="$prefix/lib/systemd/user"
+    local target="$prefix/share/systemd/user"
+    echo "moving $source/* to $target"
+    mkdir -p "$target"
+    (
+      shopt -s dotglob
+      for i in "$source"/*; do
+          mv "$i" "$target"
+      done
+    )
+    rmdir "$source"
+    ln -s "$target" "$source"
+}
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/reproducible-builds.sh b/nixpkgs/pkgs/build-support/setup-hooks/reproducible-builds.sh
new file mode 100644
index 000000000000..2d8db6ff7d3c
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/setup-hooks/reproducible-builds.sh
@@ -0,0 +1,4 @@
+# Use the last part of the out path as hash input for the build.
+# This should ensure that it is deterministic across rebuilds of the same
+# derivation and not easily collide with other builds.
+export NIX_CFLAGS_COMPILE+=" -frandom-seed=${out##*/}"
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/strip.sh b/nixpkgs/pkgs/build-support/setup-hooks/strip.sh
index f5fa9378fd7e..a7cdfd1d2767 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/strip.sh
+++ b/nixpkgs/pkgs/build-support/setup-hooks/strip.sh
@@ -51,7 +51,7 @@ stripDirs() {
 
     if [ -n "${dirs}" ]; then
         header "stripping (with command $cmd and flags $stripFlags) in$dirs"
-        find $dirs -type f -print0 | xargs -0 ${xargsFlags:--r} $cmd $commonStripFlags $stripFlags 2>/dev/null || true
+        find $dirs -type f -exec $cmd $commonStripFlags $stripFlags '{}' \; #
         stopNest
     fi
 }
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/validate-pkg-config.sh b/nixpkgs/pkgs/build-support/setup-hooks/validate-pkg-config.sh
index 54fc9cc122ca..ada1b56760d6 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/validate-pkg-config.sh
+++ b/nixpkgs/pkgs/build-support/setup-hooks/validate-pkg-config.sh
@@ -3,9 +3,8 @@
 fixupOutputHooks+=(_validatePkgConfig)
 
 _validatePkgConfig() {
+    local bail=0
     for pc in $(find "$prefix" -name '*.pc'); do
-        local bail=0
-
         # Do not fail immediately. It's nice to see all errors when
         # there are multiple pkgconfig files.
         if ! pkg-config --validate "$pc"; then
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix b/nixpkgs/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix
index 5a87893d9726..d0ea088bf71e 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix
+++ b/nixpkgs/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix
@@ -3,6 +3,7 @@
 , makeSetupHook
 , makeWrapper
 , gobject-introspection
+, isGraphical ? true
 , gtk3
 , librsvg
 , dconf
@@ -21,7 +22,7 @@ makeSetupHook {
     # Unfortunately, it also requires the user to have dconf
     # D-Bus service enabled globally (e.g. through a NixOS module).
     dconf.lib
-  ] ++ [
+  ] ++ lib.optionals isGraphical [
     # TODO: remove this, packages should depend on GTK explicitly.
     gtk3
 
@@ -30,6 +31,7 @@ makeSetupHook {
     # graphics in GTK (e.g. cross for closing window in window title bar)
     # so it is pretty much required for applications using GTK.
     librsvg
+  ] ++ [
 
     # We use the wrapProgram function.
     makeWrapper
diff --git a/nixpkgs/pkgs/build-support/singularity-tools/default.nix b/nixpkgs/pkgs/build-support/singularity-tools/default.nix
index d937ec626682..4a54498d117c 100644
--- a/nixpkgs/pkgs/build-support/singularity-tools/default.nix
+++ b/nixpkgs/pkgs/build-support/singularity-tools/default.nix
@@ -7,7 +7,7 @@
 , bash
 , vmTools
 , gawk
-, utillinux
+, util-linux
 , runtimeShell
 , e2fsprogs }:
 
@@ -47,7 +47,7 @@ rec {
         runScriptFile = shellScript "run-script.sh" runScript;
         result = vmTools.runInLinuxVM (
           runCommand "singularity-image-${name}.img" {
-            buildInputs = [ singularity e2fsprogs utillinux gawk ];
+            buildInputs = [ singularity e2fsprogs util-linux gawk ];
             layerClosure = writeReferencesToFile layer;
             preVM = vmTools.createEmptyImage {
               size = diskSize;
diff --git a/nixpkgs/pkgs/build-support/vm/default.nix b/nixpkgs/pkgs/build-support/vm/default.nix
index 909cdc6da044..5f3c7e1d621c 100644
--- a/nixpkgs/pkgs/build-support/vm/default.nix
+++ b/nixpkgs/pkgs/build-support/vm/default.nix
@@ -151,7 +151,7 @@ rec {
 
     # Set the system time from the hardware clock.  Works around an
     # apparent KVM > 1.5.2 bug.
-    ${pkgs.utillinux}/bin/hwclock -s
+    ${pkgs.util-linux}/bin/hwclock -s
 
     export NIX_STORE=${storeDir}
     export NIX_BUILD_TOP=/tmp
@@ -270,7 +270,7 @@ rec {
   defaultCreateRootFS = ''
     mkdir /mnt
     ${e2fsprogs}/bin/mkfs.ext4 /dev/${hd}
-    ${utillinux}/bin/mount -t ext4 /dev/${hd} /mnt
+    ${util-linux}/bin/mount -t ext4 /dev/${hd} /mnt
 
     if test -e /mnt/.debug; then
       exec ${bash}/bin/sh
@@ -317,7 +317,7 @@ rec {
     with pkgs; runInLinuxVM (
     stdenv.mkDerivation {
       name = "extract-file";
-      buildInputs = [ utillinux ];
+      buildInputs = [ util-linux ];
       buildCommand = ''
         ln -s ${kernel}/lib /lib
         ${kmod}/bin/modprobe loop
@@ -342,7 +342,7 @@ rec {
     with pkgs; runInLinuxVM (
     stdenv.mkDerivation {
       name = "extract-file-mtd";
-      buildInputs = [ utillinux mtdutils ];
+      buildInputs = [ util-linux mtdutils ];
       buildCommand = ''
         ln -s ${kernel}/lib /lib
         ${kmod}/bin/modprobe mtd
@@ -417,7 +417,7 @@ rec {
 
         # Make the Nix store available in /mnt, because that's where the RPMs live.
         mkdir -p /mnt${storeDir}
-        ${utillinux}/bin/mount -o bind ${storeDir} /mnt${storeDir}
+        ${util-linux}/bin/mount -o bind ${storeDir} /mnt${storeDir}
 
         # Newer distributions like Fedora 18 require /lib etc. to be
         # symlinked to /usr.
@@ -427,7 +427,7 @@ rec {
           ln -s /usr/sbin /mnt/sbin
           ln -s /usr/lib /mnt/lib
           ln -s /usr/lib64 /mnt/lib64
-          ${utillinux}/bin/mount -t proc none /mnt/proc
+          ${util-linux}/bin/mount -t proc none /mnt/proc
         ''}
 
         echo "unpacking RPMs..."
@@ -445,7 +445,7 @@ rec {
         PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \
           rpm --initdb
 
-        ${utillinux}/bin/mount -o bind /tmp /mnt/tmp
+        ${util-linux}/bin/mount -o bind /tmp /mnt/tmp
 
         echo "installing RPMs..."
         PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \
@@ -456,8 +456,8 @@ rec {
 
         rm /mnt/.debug
 
-        ${utillinux}/bin/umount /mnt${storeDir} /mnt/tmp ${lib.optionalString unifiedSystemDir "/mnt/proc"}
-        ${utillinux}/bin/umount /mnt
+        ${util-linux}/bin/umount /mnt${storeDir} /mnt/tmp ${lib.optionalString unifiedSystemDir "/mnt/proc"}
+        ${util-linux}/bin/umount /mnt
       '';
 
       passthru = { inherit fullName; };
@@ -587,9 +587,9 @@ rec {
 
         # Make the Nix store available in /mnt, because that's where the .debs live.
         mkdir -p /mnt/inst${storeDir}
-        ${utillinux}/bin/mount -o bind ${storeDir} /mnt/inst${storeDir}
-        ${utillinux}/bin/mount -o bind /proc /mnt/proc
-        ${utillinux}/bin/mount -o bind /dev /mnt/dev
+        ${util-linux}/bin/mount -o bind ${storeDir} /mnt/inst${storeDir}
+        ${util-linux}/bin/mount -o bind /proc /mnt/proc
+        ${util-linux}/bin/mount -o bind /dev /mnt/dev
 
         # Misc. files/directories assumed by various packages.
         echo "initialising Dpkg DB..."
@@ -635,10 +635,10 @@ rec {
 
         rm /mnt/.debug
 
-        ${utillinux}/bin/umount /mnt/inst${storeDir}
-        ${utillinux}/bin/umount /mnt/proc
-        ${utillinux}/bin/umount /mnt/dev
-        ${utillinux}/bin/umount /mnt
+        ${util-linux}/bin/umount /mnt/inst${storeDir}
+        ${util-linux}/bin/umount /mnt/proc
+        ${util-linux}/bin/umount /mnt/dev
+        ${util-linux}/bin/umount /mnt
       '';
 
       passthru = { inherit fullName; };
@@ -1196,4 +1196,4 @@ rec {
      `debDistros' sets. */
   diskImages = lib.mapAttrs (name: f: f {}) diskImageFuns;
 
-} // import ./windows pkgs
+}
diff --git a/nixpkgs/pkgs/build-support/vm/windows/bootstrap.nix b/nixpkgs/pkgs/build-support/vm/windows/bootstrap.nix
deleted file mode 100644
index 3b06d8f47490..000000000000
--- a/nixpkgs/pkgs/build-support/vm/windows/bootstrap.nix
+++ /dev/null
@@ -1,83 +0,0 @@
-{ stdenv, fetchurl, vmTools, writeScript, writeText, runCommand, makeInitrd
-, python, perl, coreutils, dosfstools, gzip, mtools, netcat-gnu, openssh, qemu
-, samba, socat, vde2, cdrkit, pathsFromGraph, gnugrep
-}:
-
-{ isoFile, productKey, arch ? null }:
-
-with stdenv.lib;
-
-let
-  controller = import ./controller {
-    inherit stdenv writeScript vmTools makeInitrd;
-    inherit samba vde2 openssh socat netcat-gnu coreutils gzip gnugrep;
-  };
-
-  mkCygwinImage = import ./cygwin-iso {
-    inherit stdenv fetchurl runCommand python perl cdrkit pathsFromGraph;
-    arch = let
-      defaultArch = if stdenv.is64bit then "x86_64" else "i686";
-    in if arch == null then defaultArch else arch;
-  };
-
-  installer = import ./install {
-    inherit controller mkCygwinImage;
-    inherit stdenv runCommand openssh qemu writeText dosfstools mtools;
-  };
-in rec {
-  installedVM = installer {
-    inherit isoFile productKey;
-  };
-
-  runInVM = img: attrs: controller (attrs // {
-    inherit (installedVM) sshKey;
-    qemuArgs = attrs.qemuArgs or [] ++ [
-      "-boot order=c"
-      "-drive file=${img},index=0,media=disk"
-    ];
-  });
-
-  runAndSuspend = let
-    drives = {
-      s = {
-        source = "nixstore";
-        target = "/nix/store";
-      };
-      x = {
-        source = "xchg";
-        target = "/tmp/xchg";
-      };
-    };
-
-    genDriveCmds = letter: { source, target }: [
-      "net use ${letter}: '\\\\192.168.0.2\\${source}' /persistent:yes"
-      "mkdir -p '${target}'"
-      "mount -o bind '/cygdrive/${letter}' '${target}'"
-      "echo '/cygdrive/${letter} ${target} none bind 0 0' >> /etc/fstab"
-    ];
-  in runInVM "winvm.img" {
-    command = concatStringsSep " && " ([
-      "net config server /autodisconnect:-1"
-    ] ++ concatLists (mapAttrsToList genDriveCmds drives));
-    suspendTo = "state.gz";
-  };
-
-  suspendedVM = stdenv.mkDerivation {
-    name = "cygwin-suspended-vm";
-    buildCommand = ''
-      ${qemu}/bin/qemu-img create \
-        -b "${installedVM}/disk.img" \
-        -f qcow2 winvm.img
-      ${runAndSuspend}
-      mkdir -p "$out"
-      cp winvm.img "$out/disk.img"
-      cp state.gz "$out/state.gz"
-    '';
-  };
-
-  resumeAndRun = command: runInVM "${suspendedVM}/disk.img" {
-    resumeFrom = "${suspendedVM}/state.gz";
-    qemuArgs = singleton "-snapshot";
-    inherit command;
-  };
-}
diff --git a/nixpkgs/pkgs/build-support/vm/windows/controller/default.nix b/nixpkgs/pkgs/build-support/vm/windows/controller/default.nix
deleted file mode 100644
index 9d13983a2833..000000000000
--- a/nixpkgs/pkgs/build-support/vm/windows/controller/default.nix
+++ /dev/null
@@ -1,263 +0,0 @@
-{ stdenv, writeScript, vmTools, makeInitrd
-, samba, vde2, openssh, socat, netcat-gnu, coreutils, gnugrep, gzip
-, runtimeShell
-}:
-
-{ sshKey
-, qemuArgs ? []
-, command ? "sync"
-, suspendTo ? null
-, resumeFrom ? null
-, installMode ? false
-}:
-
-with stdenv.lib;
-
-let
-  preInitScript = writeScript "preinit.sh" ''
-    #!${vmTools.initrdUtils}/bin/ash -e
-    export PATH=${vmTools.initrdUtils}/bin
-    mount -t proc none /proc
-    mount -t sysfs none /sys
-    for arg in $(cat /proc/cmdline); do
-      if [ "x''${arg#command=}" != "x$arg" ]; then
-        command="''${arg#command=}"
-      fi
-    done
-
-    for i in $(cat ${modulesClosure}/insmod-list); do
-      insmod $i
-    done
-
-    mkdir -p /dev /fs
-
-    mount -t tmpfs none /dev
-    mknod /dev/null    c 1 3
-    mknod /dev/zero    c 1 5
-    mknod /dev/random  c 1 8
-    mknod /dev/urandom c 1 9
-    mknod /dev/tty     c 5 0
-
-    ifconfig lo up
-    ifconfig eth0 up 192.168.0.2
-
-    mount -t tmpfs none /fs
-    mkdir -p /fs/nix/store /fs/xchg /fs/dev /fs/sys /fs/proc /fs/etc /fs/tmp
-
-    mount -o bind /dev /fs/dev
-    mount -t sysfs none /fs/sys
-    mount -t proc none /fs/proc
-
-    mount -t 9p \
-      -o trans=virtio,version=9p2000.L,cache=loose \
-      store /fs/nix/store
-
-    mount -t 9p \
-      -o trans=virtio,version=9p2000.L \
-      xchg /fs/xchg
-
-    echo root:x:0:0::/root:/bin/false > /fs/etc/passwd
-
-    set +e
-    chroot /fs $command $out
-    echo $? > /fs/xchg/in-vm-exit
-
-    poweroff -f
-  '';
-
-  initrd = makeInitrd {
-    contents = singleton {
-      object = preInitScript;
-      symlink = "/init";
-    };
-  };
-
-  loopForever = "while :; do ${coreutils}/bin/sleep 1; done";
-
-  initScript = writeScript "init.sh" (''
-    #!${runtimeShell}
-    ${coreutils}/bin/cp -L "${sshKey}" /ssh.key
-    ${coreutils}/bin/chmod 600 /ssh.key
-  '' + (if installMode then ''
-    echo -n "Waiting for Windows installation to finish..."
-    while ! ${netcat-gnu}/bin/netcat -z 192.168.0.1 22; do
-      echo -n .
-      # Print a dot every 10 seconds only to shorten line length.
-      ${coreutils}/bin/sleep 10
-    done
-    ${coreutils}/bin/touch /xchg/waiting_done
-    echo " success."
-    # Loop forever, because this VM is going to be killed.
-    ${loopForever}
-  '' else ''
-    ${coreutils}/bin/mkdir -p /etc/samba /etc/samba/private \
-                              /var/lib/samba /var/log /var/run
-    ${coreutils}/bin/cat > /etc/samba/smb.conf <<CONFIG
-    [global]
-    security = user
-    map to guest = Bad User
-    guest account = root
-    workgroup = cygwin
-    netbios name = controller
-    server string = %h
-    log level = 1
-    max log size = 1000
-    log file = /var/log/samba.log
-
-    [nixstore]
-    path = /nix/store
-    writable = yes
-    guest ok = yes
-
-    [xchg]
-    path = /xchg
-    writable = yes
-    guest ok = yes
-    CONFIG
-
-    ${samba}/sbin/nmbd -D
-    ${samba}/sbin/smbd -D
-
-    echo -n "Waiting for Windows VM to become available..."
-    while ! ${netcat-gnu}/bin/netcat -z 192.168.0.1 22; do
-      echo -n .
-      ${coreutils}/bin/sleep 1
-    done
-    ${coreutils}/bin/touch /xchg/waiting_done
-    echo " success."
-
-    ${openssh}/bin/ssh \
-      -o UserKnownHostsFile=/dev/null \
-      -o StrictHostKeyChecking=no \
-      -i /ssh.key \
-      -l Administrator \
-      192.168.0.1 -- ${lib.escapeShellArg command}
-  '') + optionalString (suspendTo != null) ''
-    ${coreutils}/bin/touch /xchg/suspend_now
-    ${loopForever}
-  '');
-
-  kernelAppend = concatStringsSep " " [
-    "panic=1"
-    "loglevel=4"
-    "console=tty1"
-    "console=ttyS0"
-    "command=${initScript}"
-  ];
-
-  controllerQemuArgs = concatStringsSep " " (maybeKvm64 ++ [
-    "-pidfile $CTRLVM_PIDFILE"
-    "-nographic"
-    "-no-reboot"
-    "-virtfs local,path=/nix/store,security_model=none,mount_tag=store"
-    "-virtfs local,path=$XCHG_DIR,security_model=none,mount_tag=xchg"
-    "-kernel ${modulesClosure.kernel}/bzImage"
-    "-initrd ${initrd}/initrd"
-    "-append \"${kernelAppend}\""
-    "-net nic,vlan=0,macaddr=52:54:00:12:01:02,model=virtio"
-    "-net vde,vlan=0,sock=$QEMU_VDE_SOCKET"
-  ]);
-
-  maybeKvm64 = optional (stdenv.hostPlatform.system == "x86_64-linux") "-cpu kvm64";
-
-  cygwinQemuArgs = concatStringsSep " " (maybeKvm64 ++ [
-    "-monitor unix:$MONITOR_SOCKET,server,nowait"
-    "-pidfile $WINVM_PIDFILE"
-    "-nographic"
-    "-net nic,vlan=0,macaddr=52:54:00:12:01:01"
-    "-net vde,vlan=0,sock=$QEMU_VDE_SOCKET"
-    "-rtc base=2010-01-01,clock=vm"
-  ] ++ qemuArgs ++ optionals (resumeFrom != null) [
-    "-incoming 'exec: ${gzip}/bin/gzip -c -d \"${resumeFrom}\"'"
-  ]);
-
-  modulesClosure = overrideDerivation vmTools.modulesClosure (o: {
-    rootModules = o.rootModules ++ singleton "virtio_net";
-  });
-
-  preVM = ''
-    (set; declare -p) > saved-env
-    XCHG_DIR="$(${coreutils}/bin/mktemp -d nix-vm.XXXXXXXXXX --tmpdir)"
-    ${coreutils}/bin/mv saved-env "$XCHG_DIR/"
-
-    eval "$preVM"
-
-    QEMU_VDE_SOCKET="$(pwd)/vde.ctl"
-    MONITOR_SOCKET="$(pwd)/monitor"
-    WINVM_PIDFILE="$(pwd)/winvm.pid"
-    CTRLVM_PIDFILE="$(pwd)/ctrlvm.pid"
-    ${vde2}/bin/vde_switch -s "$QEMU_VDE_SOCKET" --dirmode 0700 &
-    echo 'alive?' | ${socat}/bin/socat - \
-      UNIX-CONNECT:$QEMU_VDE_SOCKET/ctl,retry=20
-  '';
-
-  vmExec = ''
-    ${vmTools.qemuProg} ${controllerQemuArgs} &
-    ${vmTools.qemuProg} ${cygwinQemuArgs} &
-    echo -n "Waiting for VMs to start up..."
-    timeout=60
-    while ! test -e "$WINVM_PIDFILE" -a -e "$CTRLVM_PIDFILE"; do
-      timeout=$(($timeout - 1))
-      echo -n .
-      if test $timeout -le 0; then
-        echo " timed out."
-        exit 1
-      fi
-      ${coreutils}/bin/sleep 1
-    done
-    echo " done."
-  '';
-
-  checkDropOut = ''
-    if ! test -e "$XCHG_DIR/waiting_done" &&
-       ! kill -0 $(< "$WINVM_PIDFILE"); then
-      echo "Windows VM has dropped out early, bailing out!" >&2
-      exit 1
-    fi
-  '';
-
-  toMonitor = "${socat}/bin/socat - UNIX-CONNECT:$MONITOR_SOCKET";
-
-  postVM = if suspendTo != null then ''
-    while ! test -e "$XCHG_DIR/suspend_now"; do
-      ${checkDropOut}
-      ${coreutils}/bin/sleep 1
-    done
-    ${toMonitor} <<CMD
-    stop
-    migrate_set_speed 4095m
-    migrate "exec:${gzip}/bin/gzip -c > '${suspendTo}'"
-    CMD
-    echo -n "Waiting for memory dump to finish..."
-    while ! echo info migrate | ${toMonitor} | \
-          ${gnugrep}/bin/grep -qi '^migration *status: *complete'; do
-      ${coreutils}/bin/sleep 1
-      echo -n .
-    done
-    echo " done."
-    echo quit | ${toMonitor}
-    wait $(< "$WINVM_PIDFILE")
-    eval "$postVM"
-    exit 0
-  '' else if installMode then ''
-    wait $(< "$WINVM_PIDFILE")
-    eval "$postVM"
-    exit 0
-  '' else ''
-    while kill -0 $(< "$CTRLVM_PIDFILE"); do
-      ${checkDropOut}
-    done
-    if ! test -e "$XCHG_DIR/in-vm-exit"; then
-      echo "Virtual machine didn't produce an exit code."
-      exit 1
-    fi
-    eval "$postVM"
-    exit $(< "$XCHG_DIR/in-vm-exit")
-  '';
-
-in writeScript "run-cygwin-vm.sh" ''
-  #!${stdenv.shell} -e
-  ${preVM}
-  ${vmExec}
-  ${postVM}
-''
diff --git a/nixpkgs/pkgs/build-support/vm/windows/cygwin-iso/default.nix b/nixpkgs/pkgs/build-support/vm/windows/cygwin-iso/default.nix
deleted file mode 100644
index 76cd41a75bc7..000000000000
--- a/nixpkgs/pkgs/build-support/vm/windows/cygwin-iso/default.nix
+++ /dev/null
@@ -1,56 +0,0 @@
-{ stdenv, fetchurl, runCommand, python, perl, xorriso, pathsFromGraph
-, arch ? "x86_64"
-}:
-
-{ packages ? []
-, mirror ? "http://ftp.gwdg.de/pub/linux/sources.redhat.com/cygwin"
-, extraContents ? []
-}:
-
-let
-  cygPkgList = if arch == "x86_64" then fetchurl {
-    url = "${mirror}/x86_64/setup.ini";
-    sha256 = "0arrxvxbl85l82iy648snx5cl952w791p45p0dfg1xpiaf96cbkj";
-  } else fetchurl {
-    url = "${mirror}/x86/setup.ini";
-    sha256 = "1fayx34868vd5h2nah7chiw65sl3i9qzrwvs7lrlv2h8k412vb69";
-  };
-
-  cygwinCross = (import ../../../../.. {
-    localSystem = stdenv.hostPlatform;
-    crossSystem = {
-      libc = "msvcrt";
-      platform = {};
-      inherit arch;
-      config = "${arch}-w64-mingw32";
-    };
-  }).windows.cygwinSetup;
-
-  makeCygwinClosure = { packages, packageList }: let
-    expr = import (runCommand "cygwin.nix" { buildInputs = [ python ]; } ''
-      python ${./mkclosure.py} "${packages}" ${toString packageList} > "$out"
-    '');
-    gen = { url, hash }: {
-      source = fetchurl {
-        url = "${mirror}/${url}";
-        sha512 = hash;
-      };
-      target = url;
-    };
-  in map gen expr;
-
-in import ../../../../../nixos/lib/make-iso9660-image.nix {
-  inherit stdenv perl xorriso pathsFromGraph;
-  syslinux = null;
-  contents = [
-    { source = "${cygwinCross}/bin/setup.exe";
-      target = "setup.exe";
-    }
-    { source = cygPkgList;
-      target = "setup.ini";
-    }
-  ] ++ makeCygwinClosure {
-    packages = cygPkgList;
-    packageList = packages;
-  } ++ extraContents;
-}
diff --git a/nixpkgs/pkgs/build-support/vm/windows/cygwin-iso/mkclosure.py b/nixpkgs/pkgs/build-support/vm/windows/cygwin-iso/mkclosure.py
deleted file mode 100644
index 4c0d67c43bac..000000000000
--- a/nixpkgs/pkgs/build-support/vm/windows/cygwin-iso/mkclosure.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Ugliest Python code I've ever written. -- aszlig
-import sys
-
-def get_plist(path):
-    in_pack = False
-    in_str = False
-    current_key = None
-    buf = ""
-    packages = {}
-    package_name = None
-    package_attrs = {}
-    with open(path, 'r') as setup:
-        for line in setup:
-            if in_str and line.rstrip().endswith('"'):
-                package_attrs[current_key] = buf + line.rstrip()[:-1]
-                in_str = False
-                continue
-            elif in_str:
-                buf += line
-                continue
-
-            if line.startswith('@'):
-                in_pack = True
-                package_name = line[1:].strip()
-                package_attrs = {}
-            elif in_pack and ':' in line:
-                key, value = line.split(':', 1)
-                if value.lstrip().startswith('"'):
-                    if value.lstrip()[1:].rstrip().endswith('"'):
-                        value = value.strip().strip('"')
-                    else:
-                        in_str = True
-                        current_key = key.strip().lower()
-                        buf = value.lstrip()[1:]
-                        continue
-                package_attrs[key.strip().lower()] = value.strip()
-            elif in_pack:
-                in_pack = False
-                packages[package_name] = package_attrs
-    return packages
-
-def main():
-    packages = get_plist(sys.argv[1])
-    to_include = set()
-
-    def traverse(package):
-        to_include.add(package)
-        attrs = packages.get(package, {})
-        deps = attrs.get('requires', '').split()
-        for new_dep in set(deps) - to_include:
-            traverse(new_dep)
-
-    map(traverse, sys.argv[2:])
-
-    sys.stdout.write('[\n')
-    for package, attrs in packages.iteritems():
-        if package not in to_include:
-            cats = [c.lower() for c in attrs.get('category', '').split()]
-            if 'base' not in cats:
-                continue
-
-        install_line = attrs.get('install')
-        if install_line is None:
-            continue
-
-        url, size, hash = install_line.split(' ', 2)
-
-        pack = [
-            '  {',
-            '    url = "{0}";'.format(url),
-            '    hash = "{0}";'.format(hash),
-            '  }',
-        ];
-        sys.stdout.write('\n'.join(pack) + '\n')
-    sys.stdout.write(']\n')
-
-if __name__ == '__main__':
-    main()
diff --git a/nixpkgs/pkgs/build-support/vm/windows/default.nix b/nixpkgs/pkgs/build-support/vm/windows/default.nix
deleted file mode 100644
index 309241c36dee..000000000000
--- a/nixpkgs/pkgs/build-support/vm/windows/default.nix
+++ /dev/null
@@ -1,44 +0,0 @@
-#note: the hardcoded /bin/sh is required for the VM's cygwin shell
-pkgs:
-
-let
-  bootstrapper = import ./bootstrap.nix {
-    inherit (pkgs) stdenv vmTools writeScript writeText runCommand makeInitrd;
-    inherit (pkgs) coreutils dosfstools gzip mtools netcat-gnu openssh qemu samba;
-    inherit (pkgs) socat vde2 fetchurl python perl cdrkit pathsFromGraph;
-    inherit (pkgs) gnugrep;
-  };
-
-  builder = ''
-    source /tmp/xchg/saved-env 2> /dev/null || true
-    export NIX_STORE=/nix/store
-    export NIX_BUILD_TOP=/tmp
-    export TMPDIR=/tmp
-    export PATH=/empty
-    cd "$NIX_BUILD_TOP"
-    exec $origBuilder $origArgs
-  '';
-
-in {
-  runInWindowsVM = drv: pkgs.lib.overrideDerivation drv (attrs: let
-    bootstrap = bootstrapper attrs.windowsImage;
-  in {
-    requiredSystemFeatures = [ "kvm" ];
-    builder = pkgs.stdenv.shell;
-    args = ["-e" (bootstrap.resumeAndRun builder)];
-    windowsImage = bootstrap.suspendedVM;
-    origArgs = attrs.args;
-    origBuilder = if attrs.builder == attrs.stdenv.shell
-                  then "/bin/sh"
-                  else attrs.builder;
-
-    postHook = ''
-      PATH=/usr/bin:/bin:/usr/sbin:/sbin
-      SHELL=/bin/sh
-      eval "$origPostHook"
-    '';
-
-    origPostHook = attrs.postHook or "";
-    fixupPhase = ":";
-  });
-}
diff --git a/nixpkgs/pkgs/build-support/vm/windows/install/default.nix b/nixpkgs/pkgs/build-support/vm/windows/install/default.nix
deleted file mode 100644
index fe8e8f61de02..000000000000
--- a/nixpkgs/pkgs/build-support/vm/windows/install/default.nix
+++ /dev/null
@@ -1,74 +0,0 @@
-{ stdenv, runCommand, openssh, qemu, controller, mkCygwinImage
-, writeText, dosfstools, mtools
-}:
-
-{ isoFile
-, productKey
-}:
-
-let
-  bootstrapAfterLogin = runCommand "bootstrap.sh" {} ''
-    cat > "$out" <<EOF
-    mkdir -p ~/.ssh
-    cat > ~/.ssh/authorized_keys <<PUBKEY
-    $(cat "${cygwinSshKey}/key.pub")
-    PUBKEY
-    ssh-host-config -y -c 'binmode ntsec' -w dummy
-    cygrunsrv -S sshd
-    shutdown -s 5
-    EOF
-  '';
-
-  cygwinSshKey = stdenv.mkDerivation {
-    name = "snakeoil-ssh-cygwin";
-    buildCommand = ''
-      mkdir -p "$out"
-      ${openssh}/bin/ssh-keygen -t ecdsa -f "$out/key" -N ""
-    '';
-  };
-
-  sshKey = "${cygwinSshKey}/key";
-
-  packages = [ "openssh" "shutdown" ];
-
-  floppyCreator = import ./unattended-image.nix {
-    inherit stdenv writeText dosfstools mtools;
-  };
-
-  instfloppy = floppyCreator {
-    cygwinPackages = packages;
-    inherit productKey;
-  };
-
-  cygiso = mkCygwinImage {
-    inherit packages;
-    extraContents = stdenv.lib.singleton {
-      source = bootstrapAfterLogin;
-      target = "bootstrap.sh";
-    };
-  };
-
-  installController = controller {
-    inherit sshKey;
-    installMode = true;
-    qemuArgs = [
-      "-boot order=c,once=d"
-      "-drive file=${instfloppy},readonly,index=0,if=floppy"
-      "-drive file=winvm.img,index=0,media=disk"
-      "-drive file=${isoFile},index=1,media=cdrom"
-      "-drive file=${cygiso}/iso/cd.iso,index=2,media=cdrom"
-    ];
-  };
-
-in stdenv.mkDerivation {
-  name = "cygwin-base-vm";
-  buildCommand = ''
-    ${qemu}/bin/qemu-img create -f qcow2 winvm.img 2G
-    ${installController}
-    mkdir -p "$out"
-    cp winvm.img "$out/disk.img"
-  '';
-  passthru = {
-    inherit sshKey;
-  };
-}
diff --git a/nixpkgs/pkgs/build-support/vm/windows/install/unattended-image.nix b/nixpkgs/pkgs/build-support/vm/windows/install/unattended-image.nix
deleted file mode 100644
index 5b1ff84cf44d..000000000000
--- a/nixpkgs/pkgs/build-support/vm/windows/install/unattended-image.nix
+++ /dev/null
@@ -1,123 +0,0 @@
-{ stdenv, writeText, dosfstools, mtools }:
-
-{ productKey
-, shExecAfterwards ? "E:\\bootstrap.sh"
-, cygwinRoot ? "C:\\cygwin"
-, cygwinSetup ? "E:\\setup.exe"
-, cygwinRepository ? "E:\\"
-, cygwinPackages ? [ "openssh" ]
-}:
-
-let
-  afterSetup = [
-    cygwinSetup
-    "-L -n -q"
-    "-l ${cygwinRepository}"
-    "-R ${cygwinRoot}"
-    "-C base"
-  ] ++ map (p: "-P ${p}") cygwinPackages;
-
-  winXpUnattended = writeText "winnt.sif" ''
-    [Data]
-    AutoPartition = 1
-    AutomaticUpdates = 0
-    MsDosInitiated = 0
-    UnattendedInstall = Yes
-
-    [Unattended]
-    DUDisable = Yes
-    DriverSigningPolicy = Ignore
-    Hibernation = No
-    OemPreinstall = No
-    OemSkipEula = Yes
-    Repartition = Yes
-    TargetPath = \WINDOWS
-    UnattendMode = FullUnattended
-    UnattendSwitch = Yes
-    WaitForReboot = No
-
-    [GuiUnattended]
-    AdminPassword = "nopasswd"
-    AutoLogon = Yes
-    AutoLogonCount = 1
-    OEMSkipRegional = 1
-    OemSkipWelcome = 1
-    ServerWelcome = No
-    TimeZone = 85
-
-    [UserData]
-    ComputerName = "cygwin"
-    FullName = "cygwin"
-    OrgName = ""
-    ProductKey = "${productKey}"
-
-    [Networking]
-    InstallDefaultComponents = Yes
-
-    [Identification]
-    JoinWorkgroup = cygwin
-
-    [NetAdapters]
-    PrimaryAdapter = params.PrimaryAdapter
-
-    [params.PrimaryAdapter]
-    InfID = *
-
-    [params.MS_MSClient]
-
-    [NetProtocols]
-    MS_TCPIP = params.MS_TCPIP
-
-    [params.MS_TCPIP]
-    AdapterSections=params.MS_TCPIP.PrimaryAdapter
-
-    [params.MS_TCPIP.PrimaryAdapter]
-    DHCP = No
-    IPAddress = 192.168.0.1
-    SpecificTo = PrimaryAdapter
-    SubnetMask = 255.255.255.0
-    WINS = No
-
-    ; Turn off all components
-    [Components]
-    ${stdenv.lib.concatMapStrings (comp: "${comp} = Off\n") [
-      "AccessOpt" "Appsrv_console" "Aspnet" "BitsServerExtensionsISAPI"
-      "BitsServerExtensionsManager" "Calc" "Certsrv" "Certsrv_client"
-      "Certsrv_server" "Charmap" "Chat" "Clipbook" "Cluster" "Complusnetwork"
-      "Deskpaper" "Dialer" "Dtcnetwork" "Fax" "Fp_extensions" "Fp_vdir_deploy"
-      "Freecell" "Hearts" "Hypertrm" "IEAccess" "IEHardenAdmin" "IEHardenUser"
-      "Iis_asp" "Iis_common" "Iis_ftp" "Iis_inetmgr" "Iis_internetdataconnector"
-      "Iis_nntp" "Iis_serversideincludes" "Iis_smtp" "Iis_webdav" "Iis_www"
-      "Indexsrv_system" "Inetprint" "Licenseserver" "Media_clips" "Media_utopia"
-      "Minesweeper" "Mousepoint" "Msmq_ADIntegrated" "Msmq_Core"
-      "Msmq_HTTPSupport" "Msmq_LocalStorage" "Msmq_MQDSService"
-      "Msmq_RoutingSupport" "Msmq_TriggersService" "Msnexplr" "Mswordpad"
-      "Netcis" "Netoc" "OEAccess" "Objectpkg" "Paint" "Pinball" "Pop3Admin"
-      "Pop3Service" "Pop3Srv" "Rec" "Reminst" "Rootautoupdate" "Rstorage" "SCW"
-      "Sakit_web" "Solitaire" "Spider" "TSWebClient" "Templates"
-      "TerminalServer" "UDDIAdmin" "UDDIDatabase" "UDDIWeb" "Vol" "WMAccess"
-      "WMPOCM" "WbemMSI" "Wms" "Wms_admin_asp" "Wms_admin_mmc" "Wms_isapi"
-      "Wms_server" "Zonegames"
-    ]}
-
-    [WindowsFirewall]
-    Profiles = WindowsFirewall.TurnOffFirewall
-
-    [WindowsFirewall.TurnOffFirewall]
-    Mode = 0
-
-    [SetupParams]
-    UserExecute = "${stdenv.lib.concatStringsSep " " afterSetup}"
-
-    [GuiRunOnce]
-    Command0 = "${cygwinRoot}\bin\bash -l ${shExecAfterwards}"
-  '';
-
-in stdenv.mkDerivation {
-  name = "unattended-floppy.img";
-  buildCommand = ''
-    dd if=/dev/zero of="$out" count=1440 bs=1024
-    ${dosfstools}/sbin/mkfs.msdos "$out"
-    ${mtools}/bin/mcopy -i "$out" "${winXpUnattended}" ::winnt.sif
-  '';
-}
diff --git a/nixpkgs/pkgs/build-support/wrapper-common/utils.bash b/nixpkgs/pkgs/build-support/wrapper-common/utils.bash
index 8c4680a8e446..d164982b4345 100644
--- a/nixpkgs/pkgs/build-support/wrapper-common/utils.bash
+++ b/nixpkgs/pkgs/build-support/wrapper-common/utils.bash
@@ -69,9 +69,13 @@ badPath() {
     # directory (including the build directory).
     test \
         "$p" != "/dev/null" -a \
-        "${p:0:${#NIX_STORE}}" != "$NIX_STORE" -a \
-        "${p:0:4}" != "/tmp" -a \
-        "${p:0:${#NIX_BUILD_TOP}}" != "$NIX_BUILD_TOP"
+        "${p#${NIX_STORE}}"     = "$p" -a \
+        "${p#${NIX_BUILD_TOP}}" = "$p" -a \
+        "${p#/tmp}"             = "$p" -a \
+        "${p#${TMP:-/tmp}}"     = "$p" -a \
+        "${p#${TMPDIR:-/tmp}}"  = "$p" -a \
+        "${p#${TEMP:-/tmp}}"    = "$p" -a \
+        "${p#${TEMPDIR:-/tmp}}" = "$p"
 }
 
 expandResponseParams() {
diff --git a/nixpkgs/pkgs/build-support/writers/default.nix b/nixpkgs/pkgs/build-support/writers/default.nix
index 495a56b41974..9c709921d210 100644
--- a/nixpkgs/pkgs/build-support/writers/default.nix
+++ b/nixpkgs/pkgs/build-support/writers/default.nix
@@ -1,4 +1,4 @@
-{ pkgs, lib }:
+{ pkgs, lib, gawk, gnused, gixy }:
 
 with lib;
 rec {
@@ -219,10 +219,11 @@ rec {
   writeNginxConfig = name: text: pkgs.runCommandLocal name {
     inherit text;
     passAsFile = [ "text" ];
+    nativeBuildInputs = [ gawk gnused gixy ];
   } /* sh */ ''
     # nginx-config-formatter has an error - https://github.com/1connect/nginx-config-formatter/issues/16
-    ${pkgs.gawk}/bin/awk -f ${awkFormatNginx} "$textPath" | ${pkgs.gnused}/bin/sed '/^\s*$/d' > $out
-    ${pkgs.gixy}/bin/gixy $out
+    awk -f ${awkFormatNginx} "$textPath" | sed '/^\s*$/d' > $out
+    gixy $out
   '';
 
   # writePerl takes a name an attributeset with libraries and some perl sourcecode and