about summary refs log tree commit diff
path: root/nixpkgs/pkgs/build-support
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2022-01-03 23:55:00 +0000
committerAlyssa Ross <hi@alyssa.is>2022-02-19 11:03:39 +0000
commitf4cf97a04cd5d0b86aa46baec9fb228a8f671c03 (patch)
tree28192415ff39a661d0001563bf81cc93fa25d16d /nixpkgs/pkgs/build-support
parentf8422837c9bde058e8f2de37702e7e94b2226040 (diff)
parent18c84ea816348e2a098390101b92d1e39a9dbd45 (diff)
downloadnixlib-f4cf97a04cd5d0b86aa46baec9fb228a8f671c03.tar
nixlib-f4cf97a04cd5d0b86aa46baec9fb228a8f671c03.tar.gz
nixlib-f4cf97a04cd5d0b86aa46baec9fb228a8f671c03.tar.bz2
nixlib-f4cf97a04cd5d0b86aa46baec9fb228a8f671c03.tar.lz
nixlib-f4cf97a04cd5d0b86aa46baec9fb228a8f671c03.tar.xz
nixlib-f4cf97a04cd5d0b86aa46baec9fb228a8f671c03.tar.zst
nixlib-f4cf97a04cd5d0b86aa46baec9fb228a8f671c03.zip
Merge commit '18c84ea816348e2a098390101b92d1e39a9dbd45'
Conflicts:
	nixpkgs/nixos/modules/misc/documentation.nix
	nixpkgs/pkgs/applications/networking/browsers/firefox/packages.nix
	nixpkgs/pkgs/applications/window-managers/sway/default.nix
	nixpkgs/pkgs/build-support/rust/build-rust-package/default.nix
	nixpkgs/pkgs/development/go-modules/generic/default.nix
	nixpkgs/pkgs/development/interpreters/ruby/default.nix
	nixpkgs/pkgs/development/interpreters/ruby/patchsets.nix
	nixpkgs/pkgs/development/libraries/boehm-gc/7.6.6.nix
	nixpkgs/pkgs/development/python-modules/django-mailman3/default.nix
	nixpkgs/pkgs/servers/mail/mailman/web.nix
	nixpkgs/pkgs/top-level/aliases.nix
	nixpkgs/pkgs/top-level/all-packages.nix
	nixpkgs/pkgs/top-level/impure.nix
Diffstat (limited to 'nixpkgs/pkgs/build-support')
-rw-r--r--nixpkgs/pkgs/build-support/appimage/default.nix11
-rw-r--r--nixpkgs/pkgs/build-support/bintools-wrapper/default.nix12
-rw-r--r--nixpkgs/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh4
-rw-r--r--nixpkgs/pkgs/build-support/build-bazel-package/default.nix1
-rw-r--r--nixpkgs/pkgs/build-support/build-dotnet-module/default.nix216
-rw-r--r--nixpkgs/pkgs/build-support/build-dotnet-package/default.nix22
-rw-r--r--nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix5
-rw-r--r--nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix2
-rw-r--r--nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c2
-rw-r--r--nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/default.nix2
-rw-r--r--nixpkgs/pkgs/build-support/build-fhs-userenv/env.nix2
-rw-r--r--nixpkgs/pkgs/build-support/build-graalvm-native-image/default.nix57
-rw-r--r--nixpkgs/pkgs/build-support/buildenv/default.nix2
-rw-r--r--nixpkgs/pkgs/build-support/dhall/directory-to-nix.nix25
-rw-r--r--nixpkgs/pkgs/build-support/dhall/package-to-nix.nix36
-rw-r--r--nixpkgs/pkgs/build-support/dhall/to-nix.nix (renamed from nixpkgs/pkgs/build-support/dhall-to-nix.nix)0
-rw-r--r--nixpkgs/pkgs/build-support/docker/default.nix35
-rw-r--r--nixpkgs/pkgs/build-support/docker/examples.nix45
-rw-r--r--nixpkgs/pkgs/build-support/docker/test-dummy/hello.txt1
-rw-r--r--nixpkgs/pkgs/build-support/emacs/generic.nix2
-rw-r--r--nixpkgs/pkgs/build-support/emacs/melpa2nix.el3
-rw-r--r--nixpkgs/pkgs/build-support/emacs/mk-wrapper-subdirs.el6
-rw-r--r--nixpkgs/pkgs/build-support/emacs/wrapper.nix9
-rw-r--r--nixpkgs/pkgs/build-support/fetchgit/default.nix13
-rwxr-xr-xnixpkgs/pkgs/build-support/fetchgit/nix-prefetch-git2
-rw-r--r--nixpkgs/pkgs/build-support/fetchgithub/default.nix2
-rw-r--r--nixpkgs/pkgs/build-support/fetchgitlab/default.nix10
-rw-r--r--nixpkgs/pkgs/build-support/fetchmtn/builder.sh48
-rw-r--r--nixpkgs/pkgs/build-support/fetchnuget/default.nix6
-rw-r--r--nixpkgs/pkgs/build-support/fetchpatch/tests.nix8
-rw-r--r--nixpkgs/pkgs/build-support/fetchurl/default.nix2
-rw-r--r--nixpkgs/pkgs/build-support/fetchurl/mirrors.nix241
-rw-r--r--nixpkgs/pkgs/build-support/java/canonicalize-jar.nix9
-rw-r--r--nixpkgs/pkgs/build-support/java/canonicalize-jar.sh29
-rw-r--r--nixpkgs/pkgs/build-support/libredirect/default.nix2
-rw-r--r--nixpkgs/pkgs/build-support/libredirect/libredirect.c143
-rw-r--r--nixpkgs/pkgs/build-support/mono-dll-fixer/builder.sh4
-rw-r--r--nixpkgs/pkgs/build-support/mono-dll-fixer/default.nix7
-rw-r--r--nixpkgs/pkgs/build-support/node/fetch-yarn-deps/default.nix74
-rwxr-xr-xnixpkgs/pkgs/build-support/node/fetch-yarn-deps/index.js198
-rw-r--r--nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/default.nix16
-rw-r--r--nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/git.lock7
-rw-r--r--nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/github.lock7
-rw-r--r--nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/simple.lock8
-rwxr-xr-xnixpkgs/pkgs/build-support/nuget-to-nix/nuget-to-nix.sh2
-rw-r--r--nixpkgs/pkgs/build-support/ocaml/default.nix6
-rw-r--r--nixpkgs/pkgs/build-support/pkg-config-wrapper/default.nix3
-rw-r--r--nixpkgs/pkgs/build-support/pkg-config-wrapper/pkg-config-wrapper.sh8
-rw-r--r--nixpkgs/pkgs/build-support/release/ant-build.nix123
-rw-r--r--nixpkgs/pkgs/build-support/release/default.nix4
-rw-r--r--nixpkgs/pkgs/build-support/release/functions.sh23
-rw-r--r--nixpkgs/pkgs/build-support/rust/build-rust-package/default.nix (renamed from nixpkgs/pkgs/build-support/rust/default.nix)46
-rw-r--r--nixpkgs/pkgs/build-support/rust/build-rust-package/patch-registry-deps/pkg-config (renamed from nixpkgs/pkgs/build-support/rust/patch-registry-deps/pkg-config)0
-rw-r--r--nixpkgs/pkgs/build-support/rust/build-rust-package/sysroot/default.nix (renamed from nixpkgs/pkgs/build-support/rust/sysroot/default.nix)13
-rw-r--r--nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix28
-rwxr-xr-xnixpkgs/pkgs/build-support/rust/fetch-cargo-tarball/cargo-vendor-normalise.py (renamed from nixpkgs/pkgs/build-support/rust/cargo-vendor-normalise.py)0
-rw-r--r--nixpkgs/pkgs/build-support/rust/fetch-cargo-tarball/default.nix (renamed from nixpkgs/pkgs/build-support/rust/fetchCargoTarball.nix)10
-rw-r--r--nixpkgs/pkgs/build-support/rust/hooks/cargo-build-hook.sh10
-rw-r--r--nixpkgs/pkgs/build-support/rust/hooks/cargo-check-hook.sh15
-rw-r--r--nixpkgs/pkgs/build-support/rust/import-cargo-lock.nix29
-rw-r--r--nixpkgs/pkgs/build-support/rust/lib/default.nix37
-rw-r--r--nixpkgs/pkgs/build-support/rust/sysroot/Cargo.lock17
-rw-r--r--nixpkgs/pkgs/build-support/rust/sysroot/cargo.py16
-rw-r--r--nixpkgs/pkgs/build-support/rust/sysroot/src.nix26
-rwxr-xr-xnixpkgs/pkgs/build-support/rust/sysroot/update-lockfile.sh22
-rw-r--r--nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/default.nix1
-rw-r--r--nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/Cargo.lock638
-rw-r--r--nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/Cargo.toml8
-rw-r--r--nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/default.nix31
-rw-r--r--nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/src/main.rs3
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/canonicalize-jars.sh17
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/copy-desktop-items.sh4
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/make-binary-wrapper.sh391
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/role.bash4
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh14
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/shorten-perl-shebang.sh6
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/strip.sh2
-rw-r--r--nixpkgs/pkgs/build-support/setup-hooks/validate-pkg-config.sh2
-rw-r--r--nixpkgs/pkgs/build-support/singularity-tools/default.nix2
-rw-r--r--nixpkgs/pkgs/build-support/trivial-builders.nix143
-rwxr-xr-xnixpkgs/pkgs/build-support/trivial-builders/test/references-test.sh (renamed from nixpkgs/pkgs/build-support/trivial-builders/test.sh)16
-rw-r--r--nixpkgs/pkgs/build-support/trivial-builders/test/references.nix (renamed from nixpkgs/pkgs/build-support/trivial-builders/test.nix)21
-rw-r--r--nixpkgs/pkgs/build-support/trivial-builders/test/sample.nix12
-rw-r--r--nixpkgs/pkgs/build-support/trivial-builders/test/writeStringReferencesToFile.nix18
-rw-r--r--nixpkgs/pkgs/build-support/upstream-updater/update-walker-service-specific.sh2
-rwxr-xr-xnixpkgs/pkgs/build-support/upstream-updater/update-walker.sh4
-rw-r--r--nixpkgs/pkgs/build-support/vm/default.nix19
-rw-r--r--nixpkgs/pkgs/build-support/vm/test.nix19
-rw-r--r--nixpkgs/pkgs/build-support/wrapper-common/utils.bash16
-rw-r--r--nixpkgs/pkgs/build-support/writers/aliases.nix35
-rw-r--r--nixpkgs/pkgs/build-support/writers/default.nix58
-rw-r--r--nixpkgs/pkgs/build-support/writers/test.nix31
92 files changed, 2687 insertions, 604 deletions
diff --git a/nixpkgs/pkgs/build-support/appimage/default.nix b/nixpkgs/pkgs/build-support/appimage/default.nix
index 9df241a48cad..9ceaab88946d 100644
--- a/nixpkgs/pkgs/build-support/appimage/default.nix
+++ b/nixpkgs/pkgs/build-support/appimage/default.nix
@@ -1,5 +1,4 @@
 { lib
-
 , bash
 , binutils-unwrapped
 , coreutils
@@ -27,7 +26,7 @@ rec {
     ];
   };
 
-  extract = { name, src }: pkgs.runCommand "${name}-extracted" {
+  extract = args@{ name ? "${args.pname}-${args.version}", src, ... }: pkgs.runCommand "${name}-extracted" {
       buildInputs = [ appimage-exec ];
     } ''
       appimage-exec.sh -x $out ${src}
@@ -38,7 +37,7 @@ rec {
   extractType2 = extract;
   wrapType1 = wrapType2;
 
-  wrapAppImage = args@{ name, src, extraPkgs, ... }: buildFHSUserEnv
+  wrapAppImage = args@{ name ? "${args.pname}-${args.version}", src, extraPkgs, ... }: buildFHSUserEnv
     (defaultFhsEnvArgs // {
       inherit name;
 
@@ -46,9 +45,9 @@ rec {
         ++ defaultFhsEnvArgs.targetPkgs pkgs ++ extraPkgs pkgs;
 
       runScript = "appimage-exec.sh -w ${src} --";
-    } // (removeAttrs args (builtins.attrNames (builtins.functionArgs wrapAppImage))));
+    } // (removeAttrs args ([ "pname" "version" ] ++ (builtins.attrNames (builtins.functionArgs wrapAppImage)))));
 
-  wrapType2 = args@{ name, src, extraPkgs ? pkgs: [ ], ... }: wrapAppImage
+  wrapType2 = args@{ name ? "${args.pname}-${args.version}", src, extraPkgs ? pkgs: [ ], ... }: wrapAppImage
     (args // {
       inherit name extraPkgs;
       src = extract { inherit name src; };
@@ -107,7 +106,7 @@ rec {
       xorg.libICE
       gnome2.GConf
       freetype
-      (curl.override { gnutlsSupport = true; sslSupport = false; })
+      (curl.override { gnutlsSupport = true; opensslSupport = false; })
       nspr
       nss
       fontconfig
diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix
index 3d64639d33fa..c2d67169c9ca 100644
--- a/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix
+++ b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix
@@ -81,6 +81,8 @@ let
     else if targetPlatform.system == "aarch64-linux"  then "${sharedLibraryLoader}/lib/ld-linux-aarch64.so.1"
     else if targetPlatform.system == "powerpc-linux"  then "${sharedLibraryLoader}/lib/ld.so.1"
     else if targetPlatform.isMips                     then "${sharedLibraryLoader}/lib/ld.so.1"
+    # `ld-linux-riscv{32,64}-<abi>.so.1`
+    else if targetPlatform.isRiscV                    then "${sharedLibraryLoader}/lib/ld-linux-riscv*.so.1"
     else if targetPlatform.isDarwin                   then "/usr/lib/dyld"
     else if targetPlatform.isFreeBSD                  then "/libexec/ld-elf.so.1"
     else if lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1"
@@ -324,6 +326,16 @@ stdenv.mkDerivation {
       echo "-arch ${targetPlatform.darwinArch}" >> $out/nix-support/libc-ldflags
     ''
 
+    ##
+    ## GNU specific extra strip flags
+    ##
+
+    # TODO(@sternenseemann): make a generic strip wrapper?
+    + optionalString (bintools.isGNU or false) ''
+      wrap ${targetPrefix}strip ${./gnu-binutils-strip-wrapper.sh} \
+        "${bintools_bin}/bin/${targetPrefix}strip"
+    ''
+
     ###
     ### Remove LC_UUID
     ###
diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh
new file mode 100644
index 000000000000..5b5136e3d14c
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh
@@ -0,0 +1,4 @@
+#! @shell@
+# shellcheck shell=bash
+
+exec @prog@ --enable-deterministic-archives "$@"
diff --git a/nixpkgs/pkgs/build-support/build-bazel-package/default.nix b/nixpkgs/pkgs/build-support/build-bazel-package/default.nix
index 198b9c3f617f..74486e2e1003 100644
--- a/nixpkgs/pkgs/build-support/build-bazel-package/default.nix
+++ b/nixpkgs/pkgs/build-support/build-bazel-package/default.nix
@@ -214,6 +214,7 @@ in stdenv.mkDerivation (fBuildAttrs // {
       --output_base="$bazelOut" \
       --output_user_root="$bazelUserRoot" \
       build \
+      --curses=no \
       -j $NIX_BUILD_CORES \
       "''${copts[@]}" \
       "''${host_copts[@]}" \
diff --git a/nixpkgs/pkgs/build-support/build-dotnet-module/default.nix b/nixpkgs/pkgs/build-support/build-dotnet-module/default.nix
index 0161c101e5bf..0a5b17a4a363 100644
--- a/nixpkgs/pkgs/build-support/build-dotnet-module/default.nix
+++ b/nixpkgs/pkgs/build-support/build-dotnet-module/default.nix
@@ -1,7 +1,8 @@
-{ lib, stdenv, makeWrapper, dotnetCorePackages, dotnetPackages, cacert, linkFarmFromDrvs, fetchurl }:
+{ lib, stdenvNoCC, linkFarmFromDrvs, nuget-to-nix, writeScript, makeWrapper, fetchurl, xml2, dotnetCorePackages, dotnetPackages, cacert }:
 
 { name ? "${args.pname}-${args.version}"
 , enableParallelBuilding ? true
+, doCheck ? false
 # Flags to pass to `makeWrapper`. This is done to avoid double wrapping.
 , makeWrapperArgs ? []
 
@@ -9,8 +10,12 @@
 , dotnetRestoreFlags ? []
 # Flags to pass to `dotnet build`.
 , dotnetBuildFlags ? []
+# Flags to pass to `dotnet test`, if running tests is enabled.
+, dotnetTestFlags ? []
 # Flags to pass to `dotnet install`.
 , dotnetInstallFlags ? []
+# Flags to pass to `dotnet pack`.
+, dotnetPackFlags ? []
 # Flags to pass to dotnet in all phases.
 , dotnetFlags ? []
 
@@ -18,66 +23,151 @@
 # Unfortunately, dotnet has no method for doing this automatically.
 # If unset, all executables in the projects root will get installed. This may cause bloat!
 , executables ? null
-# The packages project file, which contains instructions on how to compile it.
+# Packs a project as a `nupkg`, and installs it to `$out/share`. If set to `true`, the derivation can be used as a dependency for another dotnet project by adding it to `projectReferences`.
+, packNupkg ? false
+# The packages project file, which contains instructions on how to compile it. This can be an array of multiple project files as well.
 , projectFile ? null
 # The NuGet dependency file. This locks all NuGet dependency versions, as otherwise they cannot be deterministically fetched.
-# This can be generated using the `nuget-to-nix` tool.
+# This can be generated by running the `passthru.fetch-deps` script.
 , nugetDeps ? null
+# A list of derivations containing nupkg packages for local project references.
+# Referenced derivations can be built with `buildDotnetModule` with `packNupkg=true` flag.
+# Since we are sharing them as nugets they must be added to csproj/fsproj files as `PackageReference` as well.
+# For example, your project has a local dependency:
+#     <ProjectReference Include="../foo/bar.fsproj" />
+# To enable discovery through `projectReferences` you would need to add a line:
+#     <ProjectReference Include="../foo/bar.fsproj" />
+#     <PackageReference Include="bar" Version="*" Condition=" '$(ContinuousIntegrationBuild)'=='true' "/>
+, projectReferences ? []
 # Libraries that need to be available at runtime should be passed through this.
 # These get wrapped into `LD_LIBRARY_PATH`.
 , runtimeDeps ? []
 
+# Tests to disable. This gets passed to `dotnet test --filter "FullyQualifiedName!={}"`, to ensure compatibility with all frameworks.
+# See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#filter-option-details for more details.
+, disabledTests ? []
+# The project file to run unit tests against. This is usually referenced in the regular project file, but sometimes it needs to be manually set.
+# It gets restored and build, but not installed. You may need to regenerate your nuget lockfile after setting this.
+, testProjectFile ? ""
+
 # The type of build to perform. This is passed to `dotnet` with the `--configuration` flag. Possible values are `Release`, `Debug`, etc.
 , buildType ? "Release"
 # The dotnet SDK to use.
 , dotnet-sdk ? dotnetCorePackages.sdk_5_0
 # The dotnet runtime to use.
 , dotnet-runtime ? dotnetCorePackages.runtime_5_0
+# The dotnet SDK to run tests against. This can differentiate from the SDK compiled against.
+, dotnet-test-sdk ? dotnet-sdk
 , ... } @ args:
 
 assert projectFile == null -> throw "Defining the `projectFile` attribute is required. This is usually an `.csproj`, or `.sln` file.";
 
 # TODO: Automatically generate a dependency file when a lockfile is present.
 # This file is unfortunately almost never present, as Microsoft recommands not to push this in upstream repositories.
-assert nugetDeps == null -> throw "Defining the `nugetDeps` attribute is required, as to lock the NuGet dependencies. This file can be generated using the `nuget-to-nix` tool.";
+assert nugetDeps == null -> throw "Defining the `nugetDeps` attribute is required, as to lock the NuGet dependencies. This file can be generated by running the `passthru.fetch-deps` script.";
 
 let
   _nugetDeps = linkFarmFromDrvs "${name}-nuget-deps" (import nugetDeps {
-    fetchNuGet = { name, version, sha256 }: fetchurl {
-      name = "nuget-${name}-${version}.nupkg";
-      url = "https://www.nuget.org/api/v2/package/${name}/${version}";
+    fetchNuGet = { pname, version, sha256 }: fetchurl {
+      name = "${pname}-${version}.nupkg";
+      url = "https://www.nuget.org/api/v2/package/${pname}/${version}";
       inherit sha256;
     };
   });
+  _localDeps = linkFarmFromDrvs "${name}-local-nuget-deps" projectReferences;
+
+  nuget-source = stdenvNoCC.mkDerivation rec {
+    name = "${args.pname}-nuget-source";
+    meta.description = "A Nuget source with the dependencies for ${args.pname}";
+
+    nativeBuildInputs = [ dotnetPackages.Nuget xml2 ];
+    buildCommand = ''
+      export HOME=$(mktemp -d)
+      mkdir -p $out/{lib,share}
+
+      nuget sources Add -Name nixos -Source "$out/lib"
+      nuget init "${_nugetDeps}" "$out/lib"
+      ${lib.optionalString (projectReferences != [])
+        "nuget init \"${_localDeps}\" \"$out/lib\""}
+
+      # Generates a list of all unique licenses' spdx ids.
+      find "$out/lib" -name "*.nuspec" -exec sh -c \
+        "xml2 < {} | grep "license=" | cut -d'=' -f2" \; | sort -u > $out/share/licenses
+    '';
+  } // { # This is done because we need data from `$out` for `meta`. We have to use overrides as to not hit infinite recursion.
+    meta.licence = let
+      depLicenses = lib.splitString "\n" (builtins.readFile "${nuget-source}/share/licenses");
+      getLicence = spdx: lib.filter (license: license.spdxId or null == spdx) (builtins.attrValues lib.licenses);
+    in (lib.flatten (lib.forEach depLicenses (spdx:
+      if (getLicence spdx) != [] then (getLicence spdx) else [] ++ lib.optional (spdx != "") spdx
+    )));
+  };
 
-  package = stdenv.mkDerivation (args // {
-    nativeBuildInputs = args.nativeBuildInputs or [] ++ [ dotnet-sdk dotnetPackages.Nuget cacert makeWrapper ];
+  package = stdenvNoCC.mkDerivation (args // {
+    inherit buildType;
+
+    nativeBuildInputs = args.nativeBuildInputs or [] ++ [ dotnet-sdk cacert makeWrapper ];
 
     # Stripping breaks the executable
     dontStrip = true;
 
+    # gappsWrapperArgs gets included when wrapping for dotnet, as to avoid double wrapping
+    dontWrapGApps = true;
+
     DOTNET_NOLOGO = true; # This disables the welcome message.
     DOTNET_CLI_TELEMETRY_OPTOUT = true;
 
+    passthru = {
+      fetch-deps = writeScript "fetch-${args.pname}-deps" ''
+        set -euo pipefail
+        cd "$(dirname "''${BASH_SOURCE[0]}")"
+
+        export HOME=$(mktemp -d)
+        deps_file="/tmp/${args.pname}-deps.nix"
+
+        store_src="${package.src}"
+        src="$(mktemp -d /tmp/${args.pname}.XXX)"
+        cp -rT "$store_src" "$src"
+        chmod -R +w "$src"
+
+        trap "rm -rf $src $HOME" EXIT
+        pushd "$src"
+
+        export DOTNET_NOLOGO=1
+        export DOTNET_CLI_TELEMETRY_OPTOUT=1
+
+        mkdir -p "$HOME/nuget_pkgs"
+
+        for project in "${lib.concatStringsSep "\" \"" ((lib.toList projectFile) ++ lib.optionals (testProjectFile != "") (lib.toList testProjectFile))}"; do
+          ${dotnet-sdk}/bin/dotnet restore "$project" \
+            ${lib.optionalString (!enableParallelBuilding) "--disable-parallel"} \
+            -p:ContinuousIntegrationBuild=true \
+            -p:Deterministic=true \
+            --packages "$HOME/nuget_pkgs" \
+            "''${dotnetRestoreFlags[@]}" \
+            "''${dotnetFlags[@]}"
+        done
+
+        echo "Writing lockfile..."
+        ${nuget-to-nix}/bin/nuget-to-nix "$HOME/nuget_pkgs" > "$deps_file"
+        echo "Succesfully wrote lockfile to: $deps_file"
+      '';
+    } // args.passthru or {};
+
     configurePhase = args.configurePhase or ''
       runHook preConfigure
 
       export HOME=$(mktemp -d)
 
-      nuget sources Add -Name nixos -Source "$PWD/nixos"
-      nuget init "${_nugetDeps}" "$PWD/nixos"
-
-      # This is required due to https://github.com/NuGet/Home/issues/4413.
-      mkdir -p $HOME/.nuget/NuGet
-      cp $HOME/.config/NuGet/NuGet.Config $HOME/.nuget/NuGet
-
-      dotnet restore ${lib.escapeShellArg projectFile} \
-        ${lib.optionalString (!enableParallelBuilding) "--disable-parallel"} \
-        -p:ContinuousIntegrationBuild=true \
-        -p:Deterministic=true \
-        --source "$PWD/nixos" \
-        "''${dotnetRestoreFlags[@]}" \
-        "''${dotnetFlags[@]}"
+      for project in ''${projectFile[@]} ''${testProjectFile[@]}; do
+        dotnet restore "$project" \
+          ${lib.optionalString (!enableParallelBuilding) "--disable-parallel"} \
+          -p:ContinuousIntegrationBuild=true \
+          -p:Deterministic=true \
+          --source "${nuget-source}/lib" \
+          "''${dotnetRestoreFlags[@]}" \
+          "''${dotnetFlags[@]}"
+      done
 
       runHook postConfigure
     '';
@@ -85,34 +175,68 @@ let
     buildPhase = args.buildPhase or ''
       runHook preBuild
 
-      dotnet build ${lib.escapeShellArg projectFile} \
-        -maxcpucount:${if enableParallelBuilding then "$NIX_BUILD_CORES" else "1"} \
-        -p:BuildInParallel=${if enableParallelBuilding then "true" else "false"} \
-        -p:ContinuousIntegrationBuild=true \
-        -p:Deterministic=true \
-        -p:Version=${args.version} \
-        --configuration ${buildType} \
-        --no-restore \
-        "''${dotnetBuildFlags[@]}"  \
-        "''${dotnetFlags[@]}"
+      for project in ''${projectFile[@]} ''${testProjectFile[@]}; do
+        dotnet build "$project" \
+          -maxcpucount:${if enableParallelBuilding then "$NIX_BUILD_CORES" else "1"} \
+          -p:BuildInParallel=${if enableParallelBuilding then "true" else "false"} \
+          -p:ContinuousIntegrationBuild=true \
+          -p:Deterministic=true \
+          -p:Version=${args.version} \
+          --configuration "$buildType" \
+          --no-restore \
+          "''${dotnetBuildFlags[@]}"  \
+          "''${dotnetFlags[@]}"
+      done
 
       runHook postBuild
     '';
 
+    checkPhase = args.checkPhase or ''
+      runHook preCheck
+
+      for project in ''${testProjectFile[@]}; do
+        ${lib.getBin dotnet-test-sdk}/bin/dotnet test "$project" \
+          -maxcpucount:${if enableParallelBuilding then "$NIX_BUILD_CORES" else "1"} \
+          -p:ContinuousIntegrationBuild=true \
+          -p:Deterministic=true \
+          --configuration "$buildType" \
+          --no-build \
+          --logger "console;verbosity=normal" \
+          ${lib.optionalString (disabledTests != []) "--filter \"FullyQualifiedName!=${lib.concatStringsSep "&FullyQualifiedName!=" disabledTests}\""} \
+          "''${dotnetTestFlags[@]}"  \
+          "''${dotnetFlags[@]}"
+      done
+
+      runHook postCheck
+    '';
+
     installPhase = args.installPhase or ''
       runHook preInstall
 
-      dotnet publish ${lib.escapeShellArg projectFile} \
-        -p:ContinuousIntegrationBuild=true \
-        -p:Deterministic=true \
-        --output $out/lib/${args.pname} \
-        --configuration ${buildType} \
-        --no-build \
-        --no-self-contained \
-        "''${dotnetInstallFlags[@]}"  \
-        "''${dotnetFlags[@]}"
-    '' + (if executables != null then ''
-      for executable in ''${executables}; do
+      for project in ''${projectFile[@]}; do
+        dotnet publish "$project" \
+          -p:ContinuousIntegrationBuild=true \
+          -p:Deterministic=true \
+          --output $out/lib/${args.pname} \
+          --configuration "$buildType" \
+          --no-build \
+          --no-self-contained \
+          "''${dotnetInstallFlags[@]}"  \
+          "''${dotnetFlags[@]}"
+      done
+    '' + (lib.optionalString packNupkg ''
+      for project in ''${projectFile[@]}; do
+        dotnet pack "$project" \
+          -p:ContinuousIntegrationBuild=true \
+          -p:Deterministic=true \
+          --output $out/share \
+          --configuration "$buildType" \
+          --no-build \
+          "''${dotnetPackFlags[@]}"  \
+          "''${dotnetFlags[@]}"
+      done
+    '') + (if executables != null then ''
+      for executable in $executables; do
         execPath="$out/lib/${args.pname}/$executable"
 
         if [[ -f "$execPath" && -x "$execPath" ]]; then
@@ -120,7 +244,7 @@ let
             --set DOTNET_ROOT "${dotnet-runtime}" \
             --suffix LD_LIBRARY_PATH : "${lib.makeLibraryPath runtimeDeps}" \
             "''${gappsWrapperArgs[@]}" \
-            ''${makeWrapperArgs}
+            "''${makeWrapperArgs[@]}"
         else
           echo "Specified binary \"$executable\" is either not an executable, or does not exist!"
           exit 1
@@ -133,7 +257,7 @@ let
             --set DOTNET_ROOT "${dotnet-runtime}" \
             --suffix LD_LIBRARY_PATH : "${lib.makeLibraryPath runtimeDeps}" \
             "''${gappsWrapperArgs[@]}" \
-            ''${makeWrapperArgs}
+            "''${makeWrapperArgs[@]}"
         fi
       done
     '') + ''
diff --git a/nixpkgs/pkgs/build-support/build-dotnet-package/default.nix b/nixpkgs/pkgs/build-support/build-dotnet-package/default.nix
index 440b10044f0f..14446ef05e72 100644
--- a/nixpkgs/pkgs/build-support/build-dotnet-package/default.nix
+++ b/nixpkgs/pkgs/build-support/build-dotnet-package/default.nix
@@ -1,9 +1,9 @@
 { stdenv, lib, makeWrapper, pkg-config, mono, dotnetbuildhelpers }:
 
 attrsOrig @
-{ baseName
+{ pname
 , version
-, buildInputs ? []
+, nativeBuildInputs ? []
 , xBuildFiles ? [ ]
 , xBuildFlags ? [ "/p:Configuration=Release" ]
 , outputFiles ? [ "bin/Release/*" ]
@@ -17,14 +17,14 @@ attrsOrig @
     arrayToShell = (a: toString (map (lib.escape (lib.stringToCharacters "\\ ';$`()|<>\t") ) a));
 
     attrs = {
-      name = "${baseName}-${version}";
+      inherit pname version;
 
-      nativeBuildInputs = [ pkg-config ];
-      buildInputs = [
-        mono
-        dotnetbuildhelpers
+      nativeBuildInputs = [
+        pkg-config
         makeWrapper
-      ] ++ buildInputs;
+        dotnetbuildhelpers
+        mono
+      ] ++ nativeBuildInputs;
 
       configurePhase = ''
         runHook preConfigure
@@ -64,7 +64,7 @@ attrsOrig @
       installPhase = ''
         runHook preInstall
 
-        target="$out/lib/dotnet/${baseName}"
+        target="$out/lib/dotnet/${pname}"
         mkdir -p "$target"
 
         cp -rv ${arrayToShell outputFiles} "''${outputFilesArray[@]}" "$target"
@@ -87,7 +87,7 @@ attrsOrig @
             then
               echo "$dll already exported by a buildInputs, not re-exporting"
             else
-              ${dotnetbuildhelpers}/bin/create-pkg-config-for-dll.sh "$out/lib/pkgconfig" "$dll"
+              create-pkg-config-for-dll.sh "$out/lib/pkgconfig" "$dll"
             fi
           done
         done
@@ -113,4 +113,4 @@ attrsOrig @
       '';
     };
   in
-    stdenv.mkDerivation (attrs // (builtins.removeAttrs attrsOrig [ "buildInputs" ] ))
+    stdenv.mkDerivation (attrs // (builtins.removeAttrs attrsOrig [ "nativeBuildInputs" ] ))
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 23718bf636c6..ae7151c31c3c 100644
--- a/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix
+++ b/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix
@@ -8,6 +8,7 @@ args @ {
 , extraInstallCommands ? ""
 , meta ? {}
 , passthru ? {}
+, extraBwrapArgs ? []
 , unshareUser ? true
 , unshareIpc ? true
 , unsharePid ? true
@@ -23,7 +24,7 @@ let
   buildFHSEnv = callPackage ./env.nix { };
 
   env = buildFHSEnv (removeAttrs args [
-    "runScript" "extraInstallCommands" "meta" "passthru" "dieWithParent"
+    "runScript" "extraInstallCommands" "meta" "passthru" "extraBwrapArgs" "dieWithParent"
     "unshareUser" "unshareCgroup" "unshareUts" "unshareNet" "unsharePid" "unshareIpc"
   ]);
 
@@ -66,6 +67,7 @@ let
       "asound.conf"
       # SSL
       "ssl/certs"
+      "ca-certificates"
       "pki"
     ];
   in concatStringsSep "\n  "
@@ -168,6 +170,7 @@ let
       "''${ro_mounts[@]}"
       "''${symlinks[@]}"
       "''${auto_mounts[@]}"
+      ${concatStringsSep "\n  " extraBwrapArgs}
       ${init runScript}/bin/${name}-init ${initArgs}
     )
     exec "''${cmd[@]}"
diff --git a/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix b/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
index b9c719a4c78b..0051961d9f17 100644
--- a/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
+++ b/nixpkgs/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
@@ -156,7 +156,7 @@ let
     done
     cd ..
 
-    for i in var etc; do
+    for i in var etc opt; do
       if [ -d "${staticUsrProfileTarget}/$i" ]; then
         cp -rsHf "${staticUsrProfileTarget}/$i" "$i"
       fi
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 324c9d24ba04..c109d7297e17 100644
--- a/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c
+++ b/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c
@@ -18,7 +18,7 @@
   if (expr)                                                                    \
     fail(#expr, errno);
 
-const gchar *bind_blacklist[] = {"bin", "etc", "host", "real-host", "usr", "lib", "lib64", "lib32", "sbin", NULL};
+const gchar *bind_blacklist[] = {"bin", "etc", "host", "real-host", "usr", "lib", "lib64", "lib32", "sbin", "opt", NULL};
 
 int pivot_root(const char *new_root, const char *put_old) {
   return syscall(SYS_pivot_root, new_root, put_old);
diff --git a/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/default.nix b/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/default.nix
index 15d7b3153580..b9d2de7277eb 100644
--- a/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/default.nix
+++ b/nixpkgs/pkgs/build-support/build-fhs-userenv/chrootenv/default.nix
@@ -10,7 +10,7 @@ stdenv.mkDerivation {
   meta = with lib; {
     description = "Setup mount/user namespace for FHS emulation";
     license = licenses.mit;
-    maintainers = with maintainers; [ yegortimoshenko ];
+    maintainers = with maintainers; [ yana ];
     platforms = platforms.linux;
   };
 }
diff --git a/nixpkgs/pkgs/build-support/build-fhs-userenv/env.nix b/nixpkgs/pkgs/build-support/build-fhs-userenv/env.nix
index da4521b4de3b..44c8adb06e18 100644
--- a/nixpkgs/pkgs/build-support/build-fhs-userenv/env.nix
+++ b/nixpkgs/pkgs/build-support/build-fhs-userenv/env.nix
@@ -184,7 +184,7 @@ let
     done
     cd ..
 
-    for i in var etc; do
+    for i in var etc opt; do
       if [ -d "${staticUsrProfileTarget}/$i" ]; then
         cp -rsHf "${staticUsrProfileTarget}/$i" "$i"
       fi
diff --git a/nixpkgs/pkgs/build-support/build-graalvm-native-image/default.nix b/nixpkgs/pkgs/build-support/build-graalvm-native-image/default.nix
new file mode 100644
index 000000000000..09b2d9f73a2b
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/build-graalvm-native-image/default.nix
@@ -0,0 +1,57 @@
+{ lib, stdenv, graalvmCEPackages, glibcLocales }:
+
+{ name ? "${args.pname}-${args.version}"
+  # Final executable name
+, executable ? args.pname
+  # JAR used as input for GraalVM derivation, defaults to src
+, jar ? args.src
+, dontUnpack ? (jar == args.src)
+  # Default native-image arguments. You probably don't want to set this,
+  # except in special cases. In most cases, use extraNativeBuildArgs instead
+, nativeImageBuildArgs ? [
+    "-jar" jar
+    "-H:CLibraryPath=${lib.getLib graalvm}/lib"
+    (lib.optionalString stdenv.isDarwin "-H:-CheckToolchain")
+    "-H:Name=${executable}"
+    "--verbose"
+  ]
+  # Extra arguments to be passed to the native-image
+, extraNativeImageBuildArgs ? [ ]
+  # XMX size of GraalVM during build
+, graalvmXmx ? "-J-Xmx6g"
+  # The GraalVM to use
+, graalvm ? graalvmCEPackages.graalvm11-ce
+, meta ? { }
+, ...
+} @ args:
+
+stdenv.mkDerivation (args // {
+  inherit dontUnpack;
+
+  nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ graalvm glibcLocales ];
+
+  nativeImageBuildArgs = nativeImageBuildArgs ++ extraNativeImageBuildArgs ++ [ graalvmXmx ];
+
+  buildPhase = args.buildPhase or ''
+    runHook preBuild
+
+    native-image ''${nativeImageBuildArgs[@]}
+
+    runHook postBuild
+  '';
+
+  installPhase = args.installPhase or ''
+    runHook preInstall
+
+    install -Dm755 ${executable} -t $out/bin
+
+    runHook postInstall
+  '';
+
+  meta = {
+    # default to graalvm's platforms
+    platforms = graalvm.meta.platforms;
+    # default to executable name
+    mainProgram = executable;
+  } // meta;
+})
diff --git a/nixpkgs/pkgs/build-support/buildenv/default.nix b/nixpkgs/pkgs/build-support/buildenv/default.nix
index c2186cf6bfa0..006fc2aff923 100644
--- a/nixpkgs/pkgs/build-support/buildenv/default.nix
+++ b/nixpkgs/pkgs/build-support/buildenv/default.nix
@@ -62,7 +62,7 @@ runCommand name
         # and otherwise use `meta.outputsToInstall`. The attribute is guaranteed
         # to exist in mkDerivation-created cases. The other cases (e.g. runCommand)
         # aren't expected to have multiple outputs.
-        (if drv.outputUnspecified or false
+        (if (! drv ? outputSpecified || ! drv.outputSpecified)
             && drv.meta.outputsToInstall or null != null
           then map (outName: drv.${outName}) drv.meta.outputsToInstall
           else [ drv ])
diff --git a/nixpkgs/pkgs/build-support/dhall/directory-to-nix.nix b/nixpkgs/pkgs/build-support/dhall/directory-to-nix.nix
new file mode 100644
index 000000000000..d751e19df3fc
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/dhall/directory-to-nix.nix
@@ -0,0 +1,25 @@
+{ dhallPackages, dhallPackageToNix}:
+
+# `dhallDirectoryToNix is a utility function to take a directory of Dhall files
+# and read them in as a Nix expression.
+#
+# This function is similar to `dhallToNix`, but takes a Nixpkgs Dhall package
+# as input instead of raw Dhall code.
+#
+# Note that this uses "import from derivation" (IFD), meaning that Nix will
+# perform a build during the evaluation phase if you use this
+# `dhallDirectoryToNix` utility.  It is not possible to use
+# `dhallDirectoryToNix` in Nixpkgs, since the Nixpkgs Hydra doesn't allow IFD.
+
+{ src
+, # The file to import, relative to the src root directory
+  file ? "package.dhall"
+}@args:
+
+let
+  generatedPkg = dhallPackages.generateDhallDirectoryPackage args;
+
+  builtPkg = dhallPackages.callPackage generatedPkg { };
+
+in
+  dhallPackageToNix builtPkg
diff --git a/nixpkgs/pkgs/build-support/dhall/package-to-nix.nix b/nixpkgs/pkgs/build-support/dhall/package-to-nix.nix
new file mode 100644
index 000000000000..301501ad49df
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/dhall/package-to-nix.nix
@@ -0,0 +1,36 @@
+
+# `dhallPackageToNix` is a utility function to take a Nixpkgs Dhall package
+# (created with a function like `dhallPackages.buildDhallDirectoryPackage`)
+# and read it in as a Nix expression.
+#
+# This function is similar to `dhallToNix`, but takes a Nixpkgs Dhall package
+# as input instead of raw Dhall code.
+#
+# Note that this uses "import from derivation" (IFD), meaning that Nix will
+# perform a build during the evaluation phase if you use this
+# `dhallPackageToNix` utility.  It is not possible to use `dhallPackageToNix`
+# in Nixpkgs, since the Nixpkgs Hydra doesn't allow IFD.
+
+{ stdenv, dhall-nix }:
+
+dhallPackage:
+  let
+    drv = stdenv.mkDerivation {
+      name = "dhall-compiled-package.nix";
+
+      buildCommand = ''
+        # Dhall requires that the cache is writable, even if it is never written to.
+        # We copy the cache from the input package to the current directory and
+        # set the cache as writable.
+        cp -r "${dhallPackage}/.cache" ./
+        export XDG_CACHE_HOME=$PWD/.cache
+        chmod -R +w ./.cache
+
+        dhall-to-nix <<< "${dhallPackage}/binary.dhall" > $out
+      '';
+
+      nativeBuildInputs = [ dhall-nix ];
+    };
+
+  in
+    import drv
diff --git a/nixpkgs/pkgs/build-support/dhall-to-nix.nix b/nixpkgs/pkgs/build-support/dhall/to-nix.nix
index 96cc16e16f36..96cc16e16f36 100644
--- a/nixpkgs/pkgs/build-support/dhall-to-nix.nix
+++ b/nixpkgs/pkgs/build-support/dhall/to-nix.nix
diff --git a/nixpkgs/pkgs/build-support/docker/default.nix b/nixpkgs/pkgs/build-support/docker/default.nix
index a42b025bc7f2..1b6c340f7f0c 100644
--- a/nixpkgs/pkgs/build-support/docker/default.nix
+++ b/nixpkgs/pkgs/build-support/docker/default.nix
@@ -5,6 +5,7 @@
 , closureInfo
 , coreutils
 , e2fsprogs
+, fakechroot
 , fakeroot
 , findutils
 , go
@@ -31,11 +32,13 @@
 , writeText
 , writeTextDir
 , writePython3
-, system
-, # Note: This is the cross system we're compiling for
 }:
 
 let
+  inherit (lib)
+    optionals
+    optionalString
+    ;
 
   inherit (lib)
     escapeShellArgs
@@ -237,7 +240,7 @@ rec {
           # Unpack all of the parent layers into the image.
           lowerdir=""
           extractionID=0
-          for layerTar in $(tac layer-list); do
+          for layerTar in $(cat layer-list); do
             echo "Unpacking layer $layerTar"
             extractionID=$((extractionID + 1))
 
@@ -813,6 +816,10 @@ rec {
     , # Optional bash script to run inside fakeroot environment.
       # Could be used for changing ownership of files in customisation layer.
       fakeRootCommands ? ""
+    , # Whether to run fakeRootCommands in fakechroot as well, so that they
+      # appear to run inside the image, but have access to the normal Nix store.
+      # Perhaps this could be enabled on by default on pkgs.stdenv.buildPlatform.isLinux
+      enableFakechroot ? false
     , # We pick 100 to ensure there is plenty of room for extension. I
       # believe the actual maximum is 128.
       maxLayers ? 100
@@ -844,16 +851,26 @@ rec {
           name = "${baseName}-customisation-layer";
           paths = contentsList;
           inherit extraCommands fakeRootCommands;
-          nativeBuildInputs = [ fakeroot ];
+          nativeBuildInputs = [
+            fakeroot
+          ] ++ optionals enableFakechroot [
+            fakechroot
+            # for chroot
+            coreutils
+            # fakechroot needs getopt, which is provided by util-linux
+            util-linux
+          ];
           postBuild = ''
             mv $out old_out
             (cd old_out; eval "$extraCommands" )
 
             mkdir $out
-
-            fakeroot bash -c '
+            ${optionalString enableFakechroot ''
+              export FAKECHROOT_EXCLUDE_PATH=/dev:/proc:/sys:${builtins.storeDir}:$out/layer.tar
+            ''}
+            ${optionalString enableFakechroot ''fakechroot chroot $PWD/old_out ''}fakeroot bash -c '
               source $stdenv/setup
-              cd old_out
+              ${optionalString (!enableFakechroot) ''cd old_out''}
               eval "$fakeRootCommands"
               tar \
                 --sort name \
@@ -869,13 +886,13 @@ rec {
         };
 
         closureRoots = lib.optionals includeStorePaths /* normally true */ (
-          [ baseJson ] ++ contentsList
+          [ baseJson customisationLayer ]
         );
         overallClosure = writeText "closure" (lib.concatStringsSep " " closureRoots);
 
         # These derivations are only created as implementation details of docker-tools,
         # so they'll be excluded from the created images.
-        unnecessaryDrvs = [ baseJson overallClosure ];
+        unnecessaryDrvs = [ baseJson overallClosure customisationLayer ];
 
         conf = runCommand "${baseName}-conf.json"
           {
diff --git a/nixpkgs/pkgs/build-support/docker/examples.nix b/nixpkgs/pkgs/build-support/docker/examples.nix
index 141c2ba0ea45..941ee048666d 100644
--- a/nixpkgs/pkgs/build-support/docker/examples.nix
+++ b/nixpkgs/pkgs/build-support/docker/examples.nix
@@ -350,6 +350,9 @@ rec {
       # This removes sharing of busybox and is not recommended. We do this
       # to make the example suitable as a test case with working binaries.
       cp -r ${pkgs.pkgsStatic.busybox}/* .
+
+      # This is a "build" dependency that will not appear in the image
+      ${pkgs.hello}/bin/hello
     '';
   };
 
@@ -402,6 +405,29 @@ rec {
     created = "now";
   };
 
+  # 23. Ensure that layers are unpacked in the correct order before the
+  # runAsRoot script is executed.
+  layersUnpackOrder =
+  let
+    layerOnTopOf = parent: layerName:
+      pkgs.dockerTools.buildImage {
+        name = "layers-unpack-order-${layerName}";
+        tag = "latest";
+        fromImage = parent;
+        contents = [ pkgs.coreutils ];
+        runAsRoot = ''
+          #!${pkgs.runtimeShell}
+          echo -n "${layerName}" >> /layer-order
+        '';
+      };
+    # When executing the runAsRoot script when building layer C, if layer B is
+    # not unpacked on top of layer A, the contents of /layer-order will not be
+    # "ABC".
+    layerA = layerOnTopOf null   "a";
+    layerB = layerOnTopOf layerA "b";
+    layerC = layerOnTopOf layerB "c";
+  in layerC;
+
   # buildImage without explicit tag
   bashNoTag = pkgs.dockerTools.buildImage {
     name = "bash-no-tag";
@@ -504,6 +530,11 @@ rec {
     fakeRootCommands = ''
       mkdir -p ./home/jane
       chown 1000 ./home/jane
+      ln -s ${pkgs.hello.overrideAttrs (o: {
+        # A unique `hello` to make sure that it isn't included via another mechanism by accident.
+        configureFlags = o.configureFlags or "" + " --program-prefix=layeredImageWithFakeRootCommands-";
+        doCheck = false;
+      })} ./hello
     '';
   };
 
@@ -554,6 +585,20 @@ rec {
   # Example export of the bash image
   exportBash = pkgs.dockerTools.exportImage { fromImage = bash; };
 
+  imageViaFakeChroot = pkgs.dockerTools.streamLayeredImage {
+    name = "image-via-fake-chroot";
+    tag = "latest";
+    config.Cmd = [ "hello" ];
+    enableFakechroot = true;
+    # Crucially, instead of a relative path, this creates /bin, which is
+    # intercepted by fakechroot.
+    # This functionality is not available on darwin as of 2021.
+    fakeRootCommands = ''
+      mkdir /bin
+      ln -s ${pkgs.hello}/bin/hello /bin/hello
+    '';
+  };
+
   build-image-with-path = buildImage {
     name = "build-image-with-path";
     tag = "latest";
diff --git a/nixpkgs/pkgs/build-support/docker/test-dummy/hello.txt b/nixpkgs/pkgs/build-support/docker/test-dummy/hello.txt
new file mode 100644
index 000000000000..495cc9fa8f9c
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/docker/test-dummy/hello.txt
@@ -0,0 +1 @@
+Hello there!
diff --git a/nixpkgs/pkgs/build-support/emacs/generic.nix b/nixpkgs/pkgs/build-support/emacs/generic.nix
index ef154982ad06..1b81dbcf9ed7 100644
--- a/nixpkgs/pkgs/build-support/emacs/generic.nix
+++ b/nixpkgs/pkgs/build-support/emacs/generic.nix
@@ -86,7 +86,7 @@ stdenv.mkDerivation ({
 
     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"
+          "emacs --batch --eval '(setq large-file-warning-threshold nil)' -f batch-native-compile {} || true"
   '';
 }
 
diff --git a/nixpkgs/pkgs/build-support/emacs/melpa2nix.el b/nixpkgs/pkgs/build-support/emacs/melpa2nix.el
index bd2aadd5aeb5..383423af0818 100644
--- a/nixpkgs/pkgs/build-support/emacs/melpa2nix.el
+++ b/nixpkgs/pkgs/build-support/emacs/melpa2nix.el
@@ -8,6 +8,9 @@
 (setq package-build-archive-dir (expand-file-name "packages/"))
 (setq package-build-recipes-dir (expand-file-name "recipes/"))
 
+;; Allow installing package tarfiles larger than 10MB
+(setq large-file-warning-threshold nil)
+
 (defun melpa2nix-build-package ()
   (if (not noninteractive)
       (error "`melpa2nix-build-package' is to be used only with -batch"))
diff --git a/nixpkgs/pkgs/build-support/emacs/mk-wrapper-subdirs.el b/nixpkgs/pkgs/build-support/emacs/mk-wrapper-subdirs.el
new file mode 100644
index 000000000000..7d30400a5c65
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/emacs/mk-wrapper-subdirs.el
@@ -0,0 +1,6 @@
+(defmacro mk-subdirs-expr (path)
+  `(setq load-path
+         (delete-dups (append '(,path)
+                              ',(let ((default-directory path))
+                                  (normal-top-level-add-subdirs-to-load-path))
+                              load-path))))
diff --git a/nixpkgs/pkgs/build-support/emacs/wrapper.nix b/nixpkgs/pkgs/build-support/emacs/wrapper.nix
index ccbd58485ea8..2aa61d6d2f62 100644
--- a/nixpkgs/pkgs/build-support/emacs/wrapper.nix
+++ b/nixpkgs/pkgs/build-support/emacs/wrapper.nix
@@ -165,8 +165,13 @@ runCommand
           (add-to-list 'native-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
+
+        # Generate a subdirs.el that statically adds all subdirectories to load-path.
+        $emacs/bin/emacs \
+          --batch \
+          --load ${./mk-wrapper-subdirs.el} \
+          --eval "(prin1 (macroexpand-1 '(mk-subdirs-expr \"$out/share/emacs/site-lisp\")))" \
+          > "$subdirs"
 
         # Byte-compiling improves start-up time only slightly, but costs nothing.
         $emacs/bin/emacs --batch -f batch-byte-compile "$siteStart" "$subdirs"
diff --git a/nixpkgs/pkgs/build-support/fetchgit/default.nix b/nixpkgs/pkgs/build-support/fetchgit/default.nix
index c139030ea973..3a05008dacb5 100644
--- a/nixpkgs/pkgs/build-support/fetchgit/default.nix
+++ b/nixpkgs/pkgs/build-support/fetchgit/default.nix
@@ -12,7 +12,7 @@
       else "";
   in "${if matched == null then base else builtins.head matched}${appendShort}";
 in
-{ url, rev ? "HEAD", md5 ? "", sha256 ? "", leaveDotGit ? deepClone
+{ url, rev ? "HEAD", md5 ? "", sha256 ? "", hash ? "", leaveDotGit ? deepClone
 , fetchSubmodules ? true, deepClone ? false
 , branchName ? null
 , name ? urlToName url rev
@@ -54,6 +54,8 @@ assert deepClone -> leaveDotGit;
 
 if md5 != "" then
   throw "fetchgit does not support md5 anymore, please use sha256"
+else if hash != "" && sha256 != "" then
+  throw "Only one of sha256 or hash can be set"
 else
 stdenvNoCC.mkDerivation {
   inherit name;
@@ -63,9 +65,14 @@ stdenvNoCC.mkDerivation {
   nativeBuildInputs = [ git ]
     ++ lib.optionals fetchLFS [ git-lfs ];
 
-  outputHashAlgo = "sha256";
+  outputHashAlgo = if hash != "" then null else "sha256";
   outputHashMode = "recursive";
-  outputHash = sha256;
+  outputHash = if hash != "" then
+    hash
+  else if sha256 != "" then
+    sha256
+  else
+    lib.fakeSha256;
 
   inherit url rev leaveDotGit fetchLFS fetchSubmodules deepClone branchName postFetch;
 
diff --git a/nixpkgs/pkgs/build-support/fetchgit/nix-prefetch-git b/nixpkgs/pkgs/build-support/fetchgit/nix-prefetch-git
index 10b402de6145..be5068c7ad31 100755
--- a/nixpkgs/pkgs/build-support/fetchgit/nix-prefetch-git
+++ b/nixpkgs/pkgs/build-support/fetchgit/nix-prefetch-git
@@ -304,7 +304,7 @@ clone_user_rev() {
     local rev="${3:-HEAD}"
 
     if [ -n "$fetchLFS" ]; then
-        tmpHomePath="$(mktemp -d -p nix-prefetch-git-tmp-home-XXXXXXXXXX)"
+        tmpHomePath="$(mktemp -d "${TMPDIR:-/tmp}/nix-prefetch-git-tmp-home-XXXXXXXXXX")"
         exit_handlers+=(remove_tmpHomePath)
         HOME="$tmpHomePath"
         git lfs install
diff --git a/nixpkgs/pkgs/build-support/fetchgithub/default.nix b/nixpkgs/pkgs/build-support/fetchgithub/default.nix
index ea95bbb47931..d40a0478baba 100644
--- a/nixpkgs/pkgs/build-support/fetchgithub/default.nix
+++ b/nixpkgs/pkgs/build-support/fetchgithub/default.nix
@@ -8,7 +8,7 @@
 }@args:
 let
   baseUrl = "https://${githubBase}/${owner}/${repo}";
-  passthruAttrs = removeAttrs args [ "owner" "repo" "rev" "fetchSubmodules" "private" "githubBase" "varPrefix" ];
+  passthruAttrs = removeAttrs args [ "owner" "repo" "rev" "fetchSubmodules" "forceFetchGit" "private" "githubBase" "varPrefix" ];
   varBase = "NIX${if varPrefix == null then "" else "_${varPrefix}"}_GITHUB_PRIVATE_";
   useFetchGit = fetchSubmodules || (leaveDotGit == true) || deepClone || forceFetchGit;
   # We prefer fetchzip in cases we don't need submodules as the hash
diff --git a/nixpkgs/pkgs/build-support/fetchgitlab/default.nix b/nixpkgs/pkgs/build-support/fetchgitlab/default.nix
index 5b9dbd71c595..5c82a8f8587d 100644
--- a/nixpkgs/pkgs/build-support/fetchgitlab/default.nix
+++ b/nixpkgs/pkgs/build-support/fetchgitlab/default.nix
@@ -1,7 +1,7 @@
 { fetchgit, fetchzip, lib }:
 
 # gitlab example
-{ owner, repo, rev, domain ? "gitlab.com", name ? "source", group ? null
+{ owner, repo, rev, protocol ? "https", domain ? "gitlab.com", name ? "source", group ? null
 , fetchSubmodules ? false, leaveDotGit ? false, deepClone ? false
 , ... # For hash agility
 } @ args:
@@ -10,17 +10,17 @@ let
   slug = lib.concatStringsSep "/" ((lib.optional (group != null) group) ++ [ owner repo ]);
   escapedSlug = lib.replaceStrings [ "." "/" ] [ "%2E" "%2F" ] slug;
   escapedRev = lib.replaceStrings [ "+" "%" "/" ] [ "%2B" "%25" "%2F" ] rev;
-  passthruAttrs = removeAttrs args [ "domain" "owner" "group" "repo" "rev" ];
+  passthruAttrs = removeAttrs args [ "protocol" "domain" "owner" "group" "repo" "rev" ];
 
   useFetchGit = deepClone || fetchSubmodules || leaveDotGit;
   fetcher = if useFetchGit then fetchgit else fetchzip;
 
   fetcherArgs = (if useFetchGit then {
     inherit rev deepClone fetchSubmodules leaveDotGit;
-    url = "https://${domain}/${slug}.git";
+    url = "${protocol}://${domain}/${slug}.git";
   } else {
-    url = "https://${domain}/api/v4/projects/${escapedSlug}/repository/archive.tar.gz?sha=${escapedRev}";
+    url = "${protocol}://${domain}/api/v4/projects/${escapedSlug}/repository/archive.tar.gz?sha=${escapedRev}";
   }) // passthruAttrs // { inherit name; };
 in
 
-fetcher fetcherArgs // { meta.homepage = "https://${domain}/${slug}/"; inherit rev; }
+fetcher fetcherArgs // { meta.homepage = "${protocol}://${domain}/${slug}/"; inherit rev; }
diff --git a/nixpkgs/pkgs/build-support/fetchmtn/builder.sh b/nixpkgs/pkgs/build-support/fetchmtn/builder.sh
index c1b0db895bc1..73eff9c27252 100644
--- a/nixpkgs/pkgs/build-support/fetchmtn/builder.sh
+++ b/nixpkgs/pkgs/build-support/fetchmtn/builder.sh
@@ -2,33 +2,33 @@ source $stdenv/setup
 
 set -x
 
-if ! [ -f "$cacheDB" ]; then 
-	echo "Creating cache DB $cacheDB"
-	mtn --db "$cacheDB" db init
+if ! [ -f "$cacheDB" ]; then
+    echo "Creating cache DB $cacheDB"
+    mtn --db "$cacheDB" db init
 fi
 
 header "getting revision $selector";
 
 done=;
 for source in $dbs; do
-	if mtn pull --db "$cacheDB" "$source" "${branch}"; then
-		revision="$(mtn --db "$cacheDB" au toposort $(mtn --db "$cacheDB" au select "$selector") | tail -1)";
-		if [ -n "$revision" ]; then
-			if mtn --db "$cacheDB" au get_revision "$revision"; then
-				echo "found revision $revision"
-				done=1;
-			else
-				echo "revision $revision does not exist";
-			fi
-		else
-			echo "selector $selector does not match any revision";
-		fi
-	else
-		echo "pulling branch $branch wasn't successful";
-	fi;
-	if test -n "$done"; then
-		break;
-	fi;
+    if mtn pull --db "$cacheDB" "$source" "${branch}"; then
+        revision="$(mtn --db "$cacheDB" au toposort $(mtn --db "$cacheDB" au select "$selector") | tail -1)";
+        if [ -n "$revision" ]; then
+            if mtn --db "$cacheDB" au get_revision "$revision"; then
+                echo "found revision $revision"
+                done=1;
+            else
+                echo "revision $revision does not exist";
+            fi
+        else
+            echo "selector $selector does not match any revision";
+        fi
+    else
+        echo "pulling branch $branch wasn't successful";
+    fi;
+    if test -n "$done"; then
+        break;
+    fi;
 done;
 
 stopNest;
@@ -36,10 +36,10 @@ stopNest;
 header "checking out the revision $revision";
 
 if test -n "$done"; then
-	mtn checkout --db "$cacheDB" -r "$revision" "$out" -b "${branch}"
+    mtn checkout --db "$cacheDB" -r "$revision" "$out" -b "${branch}"
 else
-	echo "Needed revision still not found. Exiting";
-	exit 1;
+    echo "Needed revision still not found. Exiting";
+    exit 1;
 fi;
 
 stopNest
diff --git a/nixpkgs/pkgs/build-support/fetchnuget/default.nix b/nixpkgs/pkgs/build-support/fetchnuget/default.nix
index ad61b9a51d2b..061da746cead 100644
--- a/nixpkgs/pkgs/build-support/fetchnuget/default.nix
+++ b/nixpkgs/pkgs/build-support/fetchnuget/default.nix
@@ -1,9 +1,9 @@
 { fetchurl, buildDotnetPackage, unzip }:
 
 attrs @
-{ baseName
+{ pname
 , version
-, url ? "https://www.nuget.org/api/v2/package/${baseName}/${version}"
+, url ? "https://www.nuget.org/api/v2/package/${pname}/${version}"
 , sha256 ? ""
 , md5 ? ""
 , ...
@@ -14,7 +14,7 @@ else
   buildDotnetPackage ({
     src = fetchurl {
       inherit url sha256;
-      name = "${baseName}.${version}.zip";
+      name = "${pname}.${version}.zip";
     };
 
     sourceRoot = ".";
diff --git a/nixpkgs/pkgs/build-support/fetchpatch/tests.nix b/nixpkgs/pkgs/build-support/fetchpatch/tests.nix
new file mode 100644
index 000000000000..4240b325d656
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/fetchpatch/tests.nix
@@ -0,0 +1,8 @@
+{ invalidateFetcherByDrvHash, fetchpatch, ... }:
+
+{
+  simple = invalidateFetcherByDrvHash fetchpatch {
+    url = "https://github.com/facebook/zstd/pull/2724/commits/e1f85dbca3a0ed5ef06c8396912a0914db8dea6a.patch";
+    sha256 = "sha256-PuYAqnJWAE+L9bsroOnnBGJhERW8LHrGSLtIEkKU9vg=";
+  };
+}
diff --git a/nixpkgs/pkgs/build-support/fetchurl/default.nix b/nixpkgs/pkgs/build-support/fetchurl/default.nix
index 8ce69a7f1878..72af03e03d98 100644
--- a/nixpkgs/pkgs/build-support/fetchurl/default.nix
+++ b/nixpkgs/pkgs/build-support/fetchurl/default.nix
@@ -139,7 +139,7 @@ stdenvNoCC.mkDerivation {
   # New-style output content requirements.
   inherit (hash_) outputHashAlgo outputHash;
 
-  SSL_CERT_FILE = if hash_.outputHash == ""
+  SSL_CERT_FILE = if (hash_.outputHash == "" || hash_.outputHash == lib.fakeSha256 || hash_.outputHash == lib.fakeSha512 || hash_.outputHash == lib.fakeHash)
                   then "${cacert}/etc/ssl/certs/ca-bundle.crt"
                   else "/no-cert-file.crt";
 
diff --git a/nixpkgs/pkgs/build-support/fetchurl/mirrors.nix b/nixpkgs/pkgs/build-support/fetchurl/mirrors.nix
index 8dc4f4207b6c..e4d6f02a94bd 100644
--- a/nixpkgs/pkgs/build-support/fetchurl/mirrors.nix
+++ b/nixpkgs/pkgs/build-support/fetchurl/mirrors.nix
@@ -2,7 +2,7 @@
 
   # Content-addressable Nix mirrors.
   hashedMirrors = [
-    "http://tarballs.nixos.org"
+    "https://tarballs.nixos.org"
   ];
 
   # Mirrors for mirror://site/filename URIs, where "site" is
@@ -11,7 +11,7 @@
   luarocks = [
     "https://luarocks.org/"
     "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/"
-    "http://luafr.org/moonrocks/"
+    "https://luafr.org/moonrocks/"
     "http://luarocks.logiceditor.com/rocks/"
   ];
 
@@ -41,21 +41,22 @@
     # mirror.
     "https://ftpmirror.gnu.org/"
 
-    "http://ftp.nluug.nl/pub/gnu/"
-    "http://mirrors.kernel.org/gnu/"
-    "http://mirror.ibcp.fr/pub/gnu/"
-    "http://mirror.dogado.de/gnu/"
-    "http://mirror.tochlab.net/pub/gnu/"
-    "ftp://ftp.funet.fi/pub/mirrors/ftp.gnu.org/gnu/"
+    "https://ftp.nluug.nl/pub/gnu/"
+    "https://mirrors.kernel.org/gnu/"
+    "https://mirror.ibcp.fr/pub/gnu/"
+    "https://mirror.dogado.de/gnu/"
+    "https://mirror.tochlab.net/pub/gnu/"
 
     # This one is the master repository, and thus it's always up-to-date.
-    "http://ftp.gnu.org/pub/gnu/"
+    "https://ftp.gnu.org/pub/gnu/"
+
+    "ftp://ftp.funet.fi/pub/mirrors/ftp.gnu.org/gnu/"
   ];
 
   # GCC.
   gcc = [
     "https://bigsearcher.com/mirrors/gcc/"
-    "http://mirror.koddos.net/gcc/"
+    "https://mirror.koddos.net/gcc/"
     "ftp://ftp.nluug.nl/mirror/languages/gcc/"
     "ftp://ftp.fu-berlin.de/unix/languages/gcc/"
     "ftp://ftp.irisa.fr/pub/mirrors/gcc.gnu.org/gcc/"
@@ -65,18 +66,16 @@
   # GnuPG.
   gnupg = [
     "https://gnupg.org/ftp/gcrypt/"
+    "https://mirrors.dotsrc.org/gcrypt/"
+    "https://ftp.heanet.ie/mirrors/ftp.gnupg.org/gcrypt/"
+    "https://www.mirrorservice.org/sites/ftp.gnupg.org/gcrypt/"
     "http://www.ring.gr.jp/pub/net/"
-    "http://mirrors.dotsrc.org/gcrypt/"
-    "http://ftp.heanet.ie/mirrors/ftp.gnupg.org/gcrypt/"
-    "http://www.mirrorservice.org/sites/ftp.gnupg.org/gcrypt/"
   ];
 
   # kernel.org's /pub (/pub/{linux,software}) tree.
   kernel = [
-    "http://cdn.kernel.org/pub/"
-    "http://ramses.wh2.tu-dresden.de/pub/mirrors/kernel.org/"
+    "https://cdn.kernel.org/pub/"
     "http://linux-kernel.uio.no/pub/"
-    "http://kernel.osuosl.org/pub/"
     "ftp://ftp.funet.fi/pub/mirrors/ftp.kernel.org/pub/"
   ];
 
@@ -85,52 +84,46 @@
     "https://download.kde.org/download.php?url="
     "https://ftp.gwdg.de/pub/linux/kde/"
     "https://mirrors.ocf.berkeley.edu/kde/"
-    "http://mirrors.mit.edu/kde/"
+    "https://mirrors.mit.edu/kde/"
     "https://mirrors.ustc.edu.cn/kde/"
-    "http://ftp.funet.fi/pub/mirrors/ftp.kde.org/pub/kde/"
+    "https://ftp.funet.fi/pub/mirrors/ftp.kde.org/pub/kde/"
   ];
 
   # Gentoo files.
   gentoo = [
-    "http://ftp.snt.utwente.nl/pub/os/linux/gentoo/"
-    "http://distfiles.gentoo.org/"
-    "ftp://mirrors.kernel.org/gentoo/"
+    "https://ftp.snt.utwente.nl/pub/os/linux/gentoo/"
+    "https://distfiles.gentoo.org/"
+    "https://mirrors.kernel.org/gentoo/"
   ];
 
   savannah = [
     # Mirrors from https://download-mirror.savannah.gnu.org/releases/00_MIRRORS.html
-    "http://mirror.easyname.at/nongnu/"
+    "https://mirror.easyname.at/nongnu/"
+    "https://savannah.c3sl.ufpr.br/"
+    "https://mirror.csclub.uwaterloo.ca/nongnu/"
+    "https://mirror.cedia.org.ec/nongnu/"
+    "https://ftp.igh.cnrs.fr/pub/nongnu/"
+    "https://mirror6.layerjet.com/nongnu"
+    "https://mirror.netcologne.de/savannah/"
+    "https://ftp.cc.uoc.gr/mirrors/nongnu.org/"
+    "https://nongnu.uib.no/"
+    "https://ftp.acc.umu.se/mirror/gnu.org/savannah/"
     "http://mirror2.klaus-uwe.me/nongnu/"
-    "http://savannah.c3sl.ufpr.br/"
-    "http://mirror.csclub.uwaterloo.ca/nongnu/"
-    "http://mirror.cedia.org.ec/nongnu/"
-    "http://ftp.igh.cnrs.fr/pub/nongnu/"
-    "http://mirror6.layerjet.com/nongnu"
-    "http://mirror.netcologne.de/savannah/"
-    "http://ftp.cc.uoc.gr/mirrors/nongnu.org/"
-    "http://nongnu.uib.no/"
     "http://mirrors.fe.up.pt/pub/nongnu/"
-    "http://ftp.acc.umu.se/mirror/gnu.org/savannah/"
     "http://ftp.twaren.net/Unix/NonGNU/"
-    "http://ftp.yzu.edu.tw/pub/nongnu/"
-    "http://mirror.rackdc.com/savannah/"
     "http://savannah-nongnu-org.ip-connect.vn.ua/"
     "http://www.mirrorservice.org/sites/download.savannah.gnu.org/releases/"
     "http://gnu.mirrors.pair.com/savannah/savannah/"
     "ftp://mirror.easyname.at/nongnu/"
     "ftp://mirror2.klaus-uwe.me/nongnu/"
-    "ftp://savannah.c3sl.ufpr.br/savannah-nongnu/"
     "ftp://mirror.csclub.uwaterloo.ca/nongnu/"
-    "ftp://mirror.cedia.org.ec/nongnu"
     "ftp://ftp.igh.cnrs.fr/pub/nongnu/"
     "ftp://mirror.netcologne.de/savannah/"
     "ftp://nongnu.uib.no/pub/nongnu/"
     "ftp://mirrors.fe.up.pt/pub/nongnu/"
     "ftp://ftp.twaren.net/Unix/NonGNU/"
-    "ftp://ftp.yzu.edu.tw/pub/nongnu/"
     "ftp://savannah-nongnu-org.ip-connect.vn.ua/mirror/savannah.nongnu.org/"
     "ftp://ftp.mirrorservice.org/sites/download.savannah.gnu.org/releases/"
-    "ftp://spinellicreations.com/gnu_dot_org_savannah_mirror/"
   ];
 
   samba = [
@@ -140,8 +133,8 @@
 
   # BitlBee mirrors, see https://www.bitlbee.org/main.php/mirrors.html .
   bitlbee = [
-    "http://get.bitlbee.org/"
-    "http://ftp.snt.utwente.nl/pub/software/bitlbee/"
+    "https://get.bitlbee.org/"
+    "https://ftp.snt.utwente.nl/pub/software/bitlbee/"
     "http://bitlbee.intergenia.de/"
   ];
 
@@ -150,109 +143,96 @@
     "https://www.imagemagick.org/download/"
     "https://mirror.checkdomain.de/imagemagick/"
     "https://ftp.nluug.nl/ImageMagick/"
-    "ftp://ftp.sunet.se/pub/multimedia/graphics/ImageMagick/" # also contains older versions removed from most mirrors
-    "http://ftp.sunet.se/pub/multimedia/graphics/ImageMagick/"
-    "ftp://ftp.imagemagick.org/pub/ImageMagick/"
-    "http://ftp.fifi.org/ImageMagick/"
-    "ftp://ftp.fifi.org/ImageMagick/"
+    "https://ftp.sunet.se/mirror/imagemagick.org/ftp/"
+    "ftp://ftp.sunet.se/mirror/imagemagick.org/ftp/" # also contains older versions removed from most mirrors
   ];
 
   # CPAN mirrors.
   cpan = [
     "https://cpan.metacpan.org/"
     "https://cpan.perl.org/"
-    "http://backpan.perl.org/"  # for old releases
+    "https://mirrors.kernel.org/CPAN/"
+    "https://backpan.perl.org/"  # for old releases
   ];
 
   # CentOS.
   centos = [
-    "http://mirror.centos.org/centos/"
     # For old releases
-    "http://vault.centos.org/"
+    "https://vault.centos.org/"
     "https://archive.kernel.org/centos-vault/"
-    "http://ftp.jaist.ac.jp/pub/Linux/CentOS-vault/"
-    "http://mirrors.aliyun.com/centos-vault/"
+    "https://ftp.jaist.ac.jp/pub/Linux/CentOS-vault/"
+    "https://mirrors.aliyun.com/centos-vault/"
     "https://mirror.chpc.utah.edu/pub/vault.centos.org/"
     "https://mirror.math.princeton.edu/pub/centos-vault/"
     "https://mirrors.tripadvisor.com/centos-vault/"
+    "http://mirror.centos.org/centos/"
   ];
 
   # Debian.
   debian = [
-    "http://httpredir.debian.org/debian/"
+    "https://httpredir.debian.org/debian/"
+    "https://ftp.debian.org/debian/"
+    "https://mirrors.edge.kernel.org/debian/"
     "ftp://ftp.de.debian.org/debian/"
     "ftp://ftp.fr.debian.org/debian/"
     "ftp://ftp.nl.debian.org/debian/"
     "ftp://ftp.ru.debian.org/debian/"
-    "http://ftp.debian.org/debian/"
     "http://archive.debian.org/debian-archive/debian/"
     "ftp://ftp.funet.fi/pub/mirrors/ftp.debian.org/debian/"
   ];
 
   # Ubuntu.
   ubuntu = [
-    "http://nl.archive.ubuntu.com/ubuntu/"
+    "https://nl.archive.ubuntu.com/ubuntu/"
+    "https://old-releases.ubuntu.com/ubuntu/"
+    "https://mirrors.edge.kernel.org/ubuntu/"
     "http://de.archive.ubuntu.com/ubuntu/"
     "http://archive.ubuntu.com/ubuntu/"
-    "http://old-releases.ubuntu.com/ubuntu/"
   ];
 
   # Fedora (please only add full mirrors that carry old Fedora distributions as well).
   # See: https://mirrors.fedoraproject.org/publiclist (but not all carry old content).
   fedora = [
-    "http://archives.fedoraproject.org/pub/fedora/"
-    "http://fedora.osuosl.org/"
+    "https://archives.fedoraproject.org/pub/fedora/"
+    "https://fedora.osuosl.org/"
+    "https://ftp.funet.fi/pub/mirrors/ftp.redhat.com/pub/fedora/"
+    "https://ftp.linux.cz/pub/linux/fedora/"
+    "https://archives.fedoraproject.org/pub/archive/fedora/"
     "http://ftp.nluug.nl/pub/os/Linux/distr/fedora/"
-    "http://ftp.funet.fi/pub/mirrors/ftp.redhat.com/pub/fedora/"
-    "http://fedora.bhs.mirrors.ovh.net/"
     "http://mirror.csclub.uwaterloo.ca/fedora/"
-    "http://ftp.linux.cz/pub/linux/fedora/"
-    "http://ftp.heanet.ie/pub/fedora/"
     "http://mirror.1000mbps.com/fedora/"
-    "http://archives.fedoraproject.org/pub/archive/fedora/"
   ];
 
   # openSUSE.
   opensuse = [
-    "http://opensuse.hro.nl/opensuse/distribution/"
-    "http://ftp.funet.fi/pub/linux/mirrors/opensuse/distribution/"
-    "http://ftp.belnet.be/mirror/ftp.opensuse.org/distribution/"
-    "http://ftp.uni-kassel.de/opensuse/distribution/"
-    "http://ftp.opensuse.org/pub/opensuse/distribution/"
-    "http://ftp5.gwdg.de/pub/opensuse/discontinued/distribution/"
+    "https://opensuse.hro.nl/opensuse/distribution/"
+    "https://ftp.funet.fi/pub/linux/mirrors/opensuse/distribution/"
+    "https://ftp.opensuse.org/pub/opensuse/distribution/"
+    "https://ftp5.gwdg.de/pub/opensuse/discontinued/distribution/"
+    "https://mirrors.edge.kernel.org/opensuse/distribution/"
     "http://ftp.hosteurope.de/mirror/ftp.opensuse.org/discontinued/"
-    "http://opensuse.mirror.server4you.net/distribution/"
-    "http://ftp.nsysu.edu.tw/Linux/OpenSuSE/distribution/"
   ];
 
-  # Gnome (see http://ftp.gnome.org/pub/GNOME/MIRRORS).
   gnome = [
     # This one redirects to some mirror closeby, so it should be all you need.
-    "http://download.gnome.org/"
-
-    "http://ftp.unina.it/pub/linux/GNOME/"
-    "http://fr2.rpmfind.net/linux/gnome.org/"
-    "ftp://ftp.dit.upm.es/pub/GNOME/"
-    "http://ftp.acc.umu.se/pub/GNOME/"
-    "http://ftp.belnet.be/mirror/ftp.gnome.org/"
-    "http://linorg.usp.br/gnome/"
-    "http://mirror.aarnet.edu.au/pub/GNOME/"
+    "https://download.gnome.org/"
+
+    "https://fr2.rpmfind.net/linux/gnome.org/"
+    "https://ftp.acc.umu.se/pub/GNOME/"
+    "https://ftp.belnet.be/mirror/ftp.gnome.org/"
     "ftp://ftp.cse.buffalo.edu/pub/Gnome/"
     "ftp://ftp.nara.wide.ad.jp/pub/X11/GNOME/"
   ];
 
   xfce = [
-    "http://archive.xfce.org/"
-    "http://mirror.netcologne.de/xfce/"
+    "https://archive.xfce.org/"
+    "https://mirror.netcologne.de/xfce/"
+    "https://archive.be.xfce.org/xfce/"
+    "https://archive.al-us.xfce.org/"
     "http://archive.se.xfce.org/xfce/"
-    "http://archive.be.xfce.org/xfce/"
     "http://mirror.perldude.de/archive.xfce.org/"
     "http://archive.be2.xfce.org/"
     "http://ftp.udc.es/xfce/"
-    "http://archive.al-us.xfce.org/"
-    "http://mirror.yongbok.net/X11/xfce-mirror/"
-    "http://mirrors.tummy.com/pub/archive.xfce.org/"
-    "http://xfce.mirror.uber.com.au/"
   ];
 
   # X.org.
@@ -261,24 +241,19 @@
     "https://ftp.x.org/archive/"
   ];
 
-  # Apache mirrors (see http://www.apache.org/mirrors/).
   apache = [
     "https://www-eu.apache.org/dist/"
     "https://ftp.wayne.edu/apache/"
-    "http://www.eu.apache.org/dist/"
-    "ftp://ftp.fu-berlin.de/unix/www/apache/"
-    "http://ftp.tudelft.nl/apache/"
-    "http://mirror.cc.columbia.edu/pub/software/apache/"
     "https://www.apache.org/dist/"
     "https://archive.apache.org/dist/" # fallback for old releases
+    "https://apache.cs.uu.nl/"
+    "https://apache.cs.utah.edu/"
+    "http://ftp.tudelft.nl/apache/"
     "ftp://ftp.funet.fi/pub/mirrors/apache.org/"
-    "http://apache.cs.uu.nl/"
-    "http://apache.cs.utah.edu/"
   ];
 
   postgresql = [
-    "http://ftp.postgresql.org/pub/"
-    "ftp://ftp.postgresql.org/pub/"
+    "https://ftp.postgresql.org/pub/"
   ];
 
   metalab = [
@@ -286,7 +261,7 @@
     "ftp://ftp.metalab.unc.edu/pub/linux/"
   ];
 
-  # Bioconductor mirrors (from http://bioconductor.org/about/mirrors)
+  # Bioconductor mirrors (from https://bioconductor.org/about/mirrors/)
   # The commented-out ones don't seem to allow direct package downloads;
   # they serve error messages that result in hash mismatches instead.
   bioc = [
@@ -295,82 +270,80 @@
     # http://bioconductor.fmrp.usp.br/
     # http://mirror.aarnet.edu.au/pub/bioconductor/
     # http://watson.nci.nih.gov/bioc_mirror/
+    "https://bioconductor.statistik.tu-dortmund.de/packages/"
+    "https://mirrors.ustc.edu.cn/bioc/"
     "http://bioconductor.jp/packages/"
-    "http://bioconductor.statistik.tu-dortmund.de/packages/"
-    "http://mirrors.ustc.edu.cn/bioc/"
   ];
 
   # Hackage mirrors
   hackage = [
-    "http://hackage.haskell.org/package/"
-    "http://hdiff.luite.com/packages/archive/package/"
-    "http://hackage.fpcomplete.com/package/"
-    "http://objects-us-east-1.dream.io/hackage-mirror/package/"
+    "https://hackage.haskell.org/package/"
   ];
 
   # Roy marples mirrors
   roy = [
-    "http://roy.marples.name/downloads/"
-    "http://cflags.cc/roy/"
+    "https://roy.marples.name/downloads/"
+    "https://cflags.cc/roy/"
   ];
 
-  # Sage mirrors (http://www.sagemath.org/mirrors.html)
+  # Sage mirrors (https://www.sagemath.org/mirrors.html)
   sageupstream = [
-    # Africa
+    # Africa (HTTPS)
+    "https://sagemath.mirror.ac.za/spkg/upstream/"
+    "https://mirror.ufs.ac.za/sagemath/spkg/upstream/"
+
+    # America, North (HTTPS)
+    "https://mirrors.mit.edu/sage/spkg/upstream/"
+    "https://mirrors.xmission.com/sage/spkg/upstream/"
+
+    # Asia (HTTPS)
+    "https://mirrors.tuna.tsinghua.edu.cn/sagemath/spkg/upstream/"
+    "https://mirrors.ustc.edu.cn/sagemath/spkg/upstream/"
+    "http://ftp.tsukuba.wide.ad.jp/software/sage/spkg/upstream/"
+    "https://ftp.yz.yamagata-u.ac.jp/pub/math/sage/spkg/upstream/"
+    "https://mirror.yandex.ru/mirrors/sage.math.washington.edu/spkg/upstream/"
+
+    # Australia (HTTPS)
+    "https://mirror.aarnet.edu.au/pub/sage/spkg/upstream/"
+
+    # Europe (HTTPS)
+    "https://sage.mirror.garr.it/mirrors/sage/spkg/upstream/"
+    "https://www-ftp.lip6.fr/pub/math/sagemath/spkg/upstream/"
+
+    # Africa (non-HTTPS)
     "ftp://ftp.sun.ac.za/pub/mirrors/www.sagemath.org/spkg/upstream/"
-    "http://sagemath.mirror.ac.za/spkg/upstream/"
-    "https://ftp.leg.uct.ac.za/pub/packages/sage/spkg/upstream/"
-    "http://mirror.ufs.ac.za/sagemath/spkg/upstream/"
 
-    # America, North
-    "http://mirrors-usa.go-parts.com/sage/sagemath/spkg/upstream/"
-    "http://mirrors.mit.edu/sage/spkg/upstream/"
+    # America, North (non-HTTPS)
     "http://www.cecm.sfu.ca/sage/spkg/upstream/"
-    "http://files.sagemath.org/spkg/upstream/"
-    "http://mirror.clibre.uqam.ca/sage/spkg/upstream/"
-    "https://mirrors.xmission.com/sage/spkg/upstream/"
 
-    # America, South
+    # America, South (non-HTTPS)
     "http://sagemath.c3sl.ufpr.br/spkg/upstream/"
     "http://linorg.usp.br/sage/spkg/upstream"
 
-    # Asia
-    "http://mirror.hust.edu.cn/sagemath/spkg/upstream/"
-    "https://ftp.iitm.ac.in/sage/spkg/upstream/"
+    # Asia (non-HTTPS)
     "http://ftp.kaist.ac.kr/sage/spkg/upstream/"
     "http://ftp.riken.jp/sagemath/spkg/upstream/"
-    "https://mirrors.tuna.tsinghua.edu.cn/sagemath/spkg/upstream/"
-    "https://mirrors.ustc.edu.cn/sagemath/spkg/upstream/"
-    "http://ftp.tsukuba.wide.ad.jp/software/sage/spkg/upstream/"
-    "http://ftp.yz.yamagata-u.ac.jp/pub/math/sage/spkg/upstream/"
-    "https://mirror.yandex.ru/mirrors/sage.math.washington.edu/spkg/upstream/"
-
-    # Australia
-    "http://mirror.aarnet.edu.au/pub/sage/spkg/upstream/"
 
-    # Europe
-    "http://sage.mirror.garr.it/mirrors/sage/spkg/upstream/"
-    "http://mirror.switch.ch/mirror/sagemath/spkg/upstream/"
+    # Europe (non-HTTPS)
     "http://mirrors.fe.up.pt/pub/sage/spkg/upstream/"
-    "http://www-ftp.lip6.fr/pub/math/sagemath/spkg/upstream/"
     "http://ftp.ntua.gr/pub/sagemath/spkg/upstream/"
   ];
 
   # MySQL mirrors
   mysql = [
-    "http://cdn.mysql.com/Downloads/"
+    "https://cdn.mysql.com/Downloads/"
   ];
 
   # OpenBSD mirrors
   openbsd = [
-    "http://ftp.openbsd.org/pub/OpenBSD/"
+    "https://ftp.openbsd.org/pub/OpenBSD/"
     "ftp://ftp.nluug.nl/pub/OpenBSD/"
     "ftp://ftp-stud.fht-esslingen.de/pub/OpenBSD/"
   ];
 
   # Steam Runtime mirrors
   steamrt = [
-    "http://repo.steampowered.com/steamrt/"
+    "https://repo.steampowered.com/steamrt/"
     "https://public.abbradar.moe/steamrt/"
   ];
 
@@ -389,7 +362,7 @@
 
   # Mozilla projects.
   mozilla = [
-    "http://download.cdn.mozilla.net/pub/mozilla.org/"
+    "https://download.cdn.mozilla.net/pub/mozilla.org/"
     "https://archive.mozilla.org/pub/"
   ];
 
diff --git a/nixpkgs/pkgs/build-support/java/canonicalize-jar.nix b/nixpkgs/pkgs/build-support/java/canonicalize-jar.nix
new file mode 100644
index 000000000000..1edd9a6e0d20
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/java/canonicalize-jar.nix
@@ -0,0 +1,9 @@
+{ substituteAll, unzip, zip }:
+
+substituteAll {
+  name = "canonicalize-jar";
+  src = ./canonicalize-jar.sh;
+
+  unzip = "${unzip}/bin/unzip";
+  zip = "${zip}/bin/zip";
+}
diff --git a/nixpkgs/pkgs/build-support/java/canonicalize-jar.sh b/nixpkgs/pkgs/build-support/java/canonicalize-jar.sh
new file mode 100644
index 000000000000..af010bcd2b26
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/java/canonicalize-jar.sh
@@ -0,0 +1,29 @@
+# Canonicalize the manifest & repack with deterministic timestamps.
+canonicalizeJar() {
+    local input='' outer=''
+    input="$(realpath -sm -- "$1")"
+    outer="$(pwd)"
+    # -qq: even quieter
+    @unzip@ -qq "$input" -d "$input-tmp"
+    canonicalizeJarManifest "$input-tmp/META-INF/MANIFEST.MF"
+    # Sets all timestamps to Jan 1 1980, the earliest mtime zips support.
+    find -- "$input-tmp" -exec touch -t 198001010000.00 {} +
+    rm "$input"
+    pushd "$input-tmp" 2>/dev/null
+    # -q|--quiet, -r|--recurse-paths
+    # -o|--latest-time: canonicalizes overall archive mtime
+    # -X|--no-extra: don't store platform-specific extra file attribute fields
+    @zip@ -qroX "$outer/tmp-out.jar" . 2> /dev/null
+    popd 2>/dev/null
+    rm -rf "$input-tmp"
+    mv "$outer/tmp-out.jar" "$input"
+}
+
+# See also the Java specification's JAR requirements:
+# https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Notes_on_Manifest_and_Signature_Files
+canonicalizeJarManifest() {
+    local input=''
+    input="$(realpath -sm -- "$1")"
+    (head -n 1 "$input" && tail -n +2 "$input" | sort | grep -v '^\s*$') > "$input-tmp"
+    mv "$input-tmp" "$input"
+}
diff --git a/nixpkgs/pkgs/build-support/libredirect/default.nix b/nixpkgs/pkgs/build-support/libredirect/default.nix
index 42525ec98a7e..f87c6d23dd79 100644
--- a/nixpkgs/pkgs/build-support/libredirect/default.nix
+++ b/nixpkgs/pkgs/build-support/libredirect/default.nix
@@ -38,11 +38,11 @@ stdenv.mkDerivation rec {
 
     install -vD "$libName" "$out/lib/$libName"
 
+    # Provide a setup hook that injects our library into every process.
     mkdir -p "$hook/nix-support"
     cat <<SETUP_HOOK > "$hook/nix-support/setup-hook"
     ${if stdenv.isDarwin then ''
     export DYLD_INSERT_LIBRARIES="$out/lib/$libName"
-    export DYLD_FORCE_FLAT_NAMESPACE=1
     '' else ''
     export LD_PRELOAD="$out/lib/$libName"
     ''}
diff --git a/nixpkgs/pkgs/build-support/libredirect/libredirect.c b/nixpkgs/pkgs/build-support/libredirect/libredirect.c
index c7058ce123c5..7dac4684722f 100644
--- a/nixpkgs/pkgs/build-support/libredirect/libredirect.c
+++ b/nixpkgs/pkgs/build-support/libredirect/libredirect.c
@@ -2,6 +2,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <dlfcn.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -13,6 +14,22 @@
 
 #define MAX_REDIRECTS 128
 
+#ifdef __APPLE__
+  struct dyld_interpose {
+    const void * replacement;
+    const void * replacee;
+  };
+  #define WRAPPER(ret, name) static ret _libredirect_wrapper_##name
+  #define LOOKUP_REAL(name) &name
+  #define WRAPPER_DEF(name) \
+    __attribute__((used)) static struct dyld_interpose _libredirect_interpose_##name \
+      __attribute__((section("__DATA,__interpose"))) = { &_libredirect_wrapper_##name, &name };
+#else
+  #define WRAPPER(ret, name) ret name
+  #define LOOKUP_REAL(name) dlsym(RTLD_NEXT, #name)
+  #define WRAPPER_DEF(name)
+#endif
+
 static int nrRedirects = 0;
 static char * from[MAX_REDIRECTS];
 static char * to[MAX_REDIRECTS];
@@ -80,9 +97,9 @@ static int open_needs_mode(int flags)
    it contains only what we needed for programs in Nixpkgs. Just add
    more functions as needed. */
 
-int open(const char * path, int flags, ...)
+WRAPPER(int, open)(const char * path, int flags, ...)
 {
-    int (*open_real) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open");
+    int (*open_real) (const char *, int, mode_t) = LOOKUP_REAL(open);
     mode_t mode = 0;
     if (open_needs_mode(flags)) {
         va_list ap;
@@ -93,10 +110,12 @@ int open(const char * path, int flags, ...)
     char buf[PATH_MAX];
     return open_real(rewrite(path, buf), flags, mode);
 }
+WRAPPER_DEF(open)
 
-int open64(const char * path, int flags, ...)
+#ifndef __APPLE__
+WRAPPER(int, open64)(const char * path, int flags, ...)
 {
-    int (*open64_real) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open64");
+    int (*open64_real) (const char *, int, mode_t) = LOOKUP_REAL(open64);
     mode_t mode = 0;
     if (open_needs_mode(flags)) {
         va_list ap;
@@ -107,10 +126,12 @@ int open64(const char * path, int flags, ...)
     char buf[PATH_MAX];
     return open64_real(rewrite(path, buf), flags, mode);
 }
+WRAPPER_DEF(open64)
+#endif
 
-int openat(int dirfd, const char * path, int flags, ...)
+WRAPPER(int, openat)(int dirfd, const char * path, int flags, ...)
 {
-    int (*openat_real) (int, const char *, int, mode_t) = dlsym(RTLD_NEXT, "openat");
+    int (*openat_real) (int, const char *, int, mode_t) = LOOKUP_REAL(openat);
     mode_t mode = 0;
     if (open_needs_mode(flags)) {
         va_list ap;
@@ -121,57 +142,73 @@ int openat(int dirfd, const char * path, int flags, ...)
     char buf[PATH_MAX];
     return openat_real(dirfd, rewrite(path, buf), flags, mode);
 }
+WRAPPER_DEF(openat)
 
-FILE * fopen(const char * path, const char * mode)
+WRAPPER(FILE *, fopen)(const char * path, const char * mode)
 {
-    FILE * (*fopen_real) (const char *, const char *) = dlsym(RTLD_NEXT, "fopen");
+    FILE * (*fopen_real) (const char *, const char *) = LOOKUP_REAL(fopen);
     char buf[PATH_MAX];
     return fopen_real(rewrite(path, buf), mode);
 }
+WRAPPER_DEF(fopen)
 
-FILE * __nss_files_fopen(const char * path)
+#ifndef __APPLE__
+WRAPPER(FILE *, __nss_files_fopen)(const char * path)
 {
-    FILE * (*__nss_files_fopen_real) (const char *) = dlsym(RTLD_NEXT, "__nss_files_fopen");
+    FILE * (*__nss_files_fopen_real) (const char *) = LOOKUP_REAL(__nss_files_fopen);
     char buf[PATH_MAX];
     return __nss_files_fopen_real(rewrite(path, buf));
 }
+WRAPPER_DEF(__nss_files_fopen)
+#endif
 
-FILE * fopen64(const char * path, const char * mode)
+#ifndef __APPLE__
+WRAPPER(FILE *, fopen64)(const char * path, const char * mode)
 {
-    FILE * (*fopen64_real) (const char *, const char *) = dlsym(RTLD_NEXT, "fopen64");
+    FILE * (*fopen64_real) (const char *, const char *) = LOOKUP_REAL(fopen64);
     char buf[PATH_MAX];
     return fopen64_real(rewrite(path, buf), mode);
 }
+WRAPPER_DEF(fopen64)
+#endif
 
-int __xstat(int ver, const char * path, struct stat * st)
+#ifndef __APPLE__
+WRAPPER(int, __xstat)(int ver, const char * path, struct stat * st)
 {
-    int (*__xstat_real) (int ver, const char *, struct stat *) = dlsym(RTLD_NEXT, "__xstat");
+    int (*__xstat_real) (int ver, const char *, struct stat *) = LOOKUP_REAL(__xstat);
     char buf[PATH_MAX];
     return __xstat_real(ver, rewrite(path, buf), st);
 }
+WRAPPER_DEF(__xstat)
+#endif
 
-int __xstat64(int ver, const char * path, struct stat64 * st)
+#ifndef __APPLE__
+WRAPPER(int, __xstat64)(int ver, const char * path, struct stat64 * st)
 {
-    int (*__xstat64_real) (int ver, const char *, struct stat64 *) = dlsym(RTLD_NEXT, "__xstat64");
+    int (*__xstat64_real) (int ver, const char *, struct stat64 *) = LOOKUP_REAL(__xstat64);
     char buf[PATH_MAX];
     return __xstat64_real(ver, rewrite(path, buf), st);
 }
+WRAPPER_DEF(__xstat64)
+#endif
 
-int stat(const char * path, struct stat * st)
+WRAPPER(int, stat)(const char * path, struct stat * st)
 {
-    int (*__stat_real) (const char *, struct stat *) = dlsym(RTLD_NEXT, "stat");
+    int (*__stat_real) (const char *, struct stat *) = LOOKUP_REAL(stat);
     char buf[PATH_MAX];
     return __stat_real(rewrite(path, buf), st);
 }
+WRAPPER_DEF(stat)
 
-int access(const char * path, int mode)
+WRAPPER(int, access)(const char * path, int mode)
 {
-    int (*access_real) (const char *, int mode) = dlsym(RTLD_NEXT, "access");
+    int (*access_real) (const char *, int mode) = LOOKUP_REAL(access);
     char buf[PATH_MAX];
     return access_real(rewrite(path, buf), mode);
 }
+WRAPPER_DEF(access)
 
-int posix_spawn(pid_t * pid, const char * path,
+WRAPPER(int, posix_spawn)(pid_t * pid, const char * path,
     const posix_spawn_file_actions_t * file_actions,
     const posix_spawnattr_t * attrp,
     char * const argv[], char * const envp[])
@@ -179,12 +216,13 @@ int posix_spawn(pid_t * pid, const char * path,
     int (*posix_spawn_real) (pid_t *, const char *,
         const posix_spawn_file_actions_t *,
         const posix_spawnattr_t *,
-        char * const argv[], char * const envp[]) = dlsym(RTLD_NEXT, "posix_spawn");
+        char * const argv[], char * const envp[]) = LOOKUP_REAL(posix_spawn);
     char buf[PATH_MAX];
     return posix_spawn_real(pid, rewrite(path, buf), file_actions, attrp, argv, envp);
 }
+WRAPPER_DEF(posix_spawn)
 
-int posix_spawnp(pid_t * pid, const char * file,
+WRAPPER(int, posix_spawnp)(pid_t * pid, const char * file,
     const posix_spawn_file_actions_t * file_actions,
     const posix_spawnattr_t * attrp,
     char * const argv[], char * const envp[])
@@ -192,43 +230,48 @@ int posix_spawnp(pid_t * pid, const char * file,
     int (*posix_spawnp_real) (pid_t *, const char *,
         const posix_spawn_file_actions_t *,
         const posix_spawnattr_t *,
-        char * const argv[], char * const envp[]) = dlsym(RTLD_NEXT, "posix_spawnp");
+        char * const argv[], char * const envp[]) = LOOKUP_REAL(posix_spawnp);
     char buf[PATH_MAX];
     return posix_spawnp_real(pid, rewrite(file, buf), file_actions, attrp, argv, envp);
 }
+WRAPPER_DEF(posix_spawnp)
 
-int execv(const char * path, char * const argv[])
+WRAPPER(int, execv)(const char * path, char * const argv[])
 {
-    int (*execv_real) (const char * path, char * const argv[]) = dlsym(RTLD_NEXT, "execv");
+    int (*execv_real) (const char * path, char * const argv[]) = LOOKUP_REAL(execv);
     char buf[PATH_MAX];
     return execv_real(rewrite(path, buf), argv);
 }
+WRAPPER_DEF(execv)
 
-int execvp(const char * path, char * const argv[])
+WRAPPER(int, execvp)(const char * path, char * const argv[])
 {
-    int (*_execvp) (const char *, char * const argv[]) = dlsym(RTLD_NEXT, "execvp");
+    int (*_execvp) (const char *, char * const argv[]) = LOOKUP_REAL(execvp);
     char buf[PATH_MAX];
     return _execvp(rewrite(path, buf), argv);
 }
+WRAPPER_DEF(execvp)
 
-int execve(const char * path, char * const argv[], char * const envp[])
+WRAPPER(int, execve)(const char * path, char * const argv[], char * const envp[])
 {
-    int (*_execve) (const char *, char * const argv[], char * const envp[]) = dlsym(RTLD_NEXT, "execve");
+    int (*_execve) (const char *, char * const argv[], char * const envp[]) = LOOKUP_REAL(execve);
     char buf[PATH_MAX];
     return _execve(rewrite(path, buf), argv, envp);
 }
+WRAPPER_DEF(execve)
 
-DIR * opendir(const char * path)
+WRAPPER(DIR *, opendir)(const char * path)
 {
     char buf[PATH_MAX];
-    DIR * (*_opendir) (const char*) = dlsym(RTLD_NEXT, "opendir");
+    DIR * (*_opendir) (const char*) = LOOKUP_REAL(opendir);
 
     return _opendir(rewrite(path, buf));
 }
+WRAPPER_DEF(opendir)
 
 #define SYSTEM_CMD_MAX 512
 
-char *replace_substring(char * source, char * buf, char * replace_string, char * start_ptr, char * suffix_ptr) {
+static char * replace_substring(char * source, char * buf, char * replace_string, char * start_ptr, char * suffix_ptr) {
     char head[SYSTEM_CMD_MAX] = {0};
     strncpy(head, source, start_ptr - source);
 
@@ -241,7 +284,7 @@ char *replace_substring(char * source, char * buf, char * replace_string, char *
     return buf;
 }
 
-char *replace_string(char * buf, char * from, char * to) {
+static char * replace_string(char * buf, char * from, char * to) {
     int num_matches = 0;
     char * matches[SYSTEM_CMD_MAX];
     int from_len = strlen(from);
@@ -264,32 +307,48 @@ char *replace_string(char * buf, char * from, char * to) {
     return buf;
 }
 
-void rewriteSystemCall(const char * command, char * buf) {
-    strcpy(buf, command);
+static void rewriteSystemCall(const char * command, char * buf) {
+    char * p = buf;
+
+    #ifdef __APPLE__
+    // The dyld environment variable is not inherited by the subprocess spawned
+    // by system(), so this hack redefines it.
+    Dl_info info;
+    dladdr(&rewriteSystemCall, &info);
+    p = stpcpy(p, "export DYLD_INSERT_LIBRARIES=");
+    p = stpcpy(p, info.dli_fname);
+    p = stpcpy(p, ";");
+    #endif
+
+    stpcpy(p, command);
+
     for (int n = 0; n < nrRedirects; ++n) {
        replace_string(buf, from[n], to[n]);
     }
 }
 
-int system(const char *command)
+WRAPPER(int, system)(const char *command)
 {
-    int (*_system) (const char*) = dlsym(RTLD_NEXT, "system");
+    int (*_system) (const char*) = LOOKUP_REAL(system);
 
     char newCommand[SYSTEM_CMD_MAX];
     rewriteSystemCall(command, newCommand);
     return _system(newCommand);
 }
+WRAPPER_DEF(system)
 
-int mkdir(const char *path, mode_t mode)
+WRAPPER(int, mkdir)(const char *path, mode_t mode)
 {
-    int (*mkdir_real) (const char *path, mode_t mode) = dlsym(RTLD_NEXT, "mkdir");
+    int (*mkdir_real) (const char *path, mode_t mode) = LOOKUP_REAL(mkdir);
     char buf[PATH_MAX];
     return mkdir_real(rewrite(path, buf), mode);
 }
+WRAPPER_DEF(mkdir)
 
-int mkdirat(int dirfd, const char *path, mode_t mode)
+WRAPPER(int, mkdirat)(int dirfd, const char *path, mode_t mode)
 {
-    int (*mkdirat_real) (int dirfd, const char *path, mode_t mode) = dlsym(RTLD_NEXT, "mkdirat");
+    int (*mkdirat_real) (int dirfd, const char *path, mode_t mode) = LOOKUP_REAL(mkdirat);
     char buf[PATH_MAX];
     return mkdirat_real(dirfd, rewrite(path, buf), mode);
 }
+WRAPPER_DEF(mkdirat)
diff --git a/nixpkgs/pkgs/build-support/mono-dll-fixer/builder.sh b/nixpkgs/pkgs/build-support/mono-dll-fixer/builder.sh
deleted file mode 100644
index 67abc465a9bd..000000000000
--- a/nixpkgs/pkgs/build-support/mono-dll-fixer/builder.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-source $stdenv/setup
-
-substitute $dllFixer $out --subst-var-by perl $perl/bin/perl
-chmod +x $out
diff --git a/nixpkgs/pkgs/build-support/mono-dll-fixer/default.nix b/nixpkgs/pkgs/build-support/mono-dll-fixer/default.nix
index 8f7d1e795d79..09a986015eed 100644
--- a/nixpkgs/pkgs/build-support/mono-dll-fixer/default.nix
+++ b/nixpkgs/pkgs/build-support/mono-dll-fixer/default.nix
@@ -1,8 +1,11 @@
 {stdenv, perl}:
-
 stdenv.mkDerivation {
   name = "mono-dll-fixer";
-  builder = ./builder.sh;
   dllFixer = ./dll-fixer.pl;
+  dontUnpack = true;
+  installPhase = ''
+    substitute $dllFixer $out --subst-var-by perl $perl/bin/perl
+    chmod +x $out
+  '';
   inherit perl;
 }
diff --git a/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/default.nix b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/default.nix
new file mode 100644
index 000000000000..6d67b87915ac
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/default.nix
@@ -0,0 +1,74 @@
+{ stdenv, lib, makeWrapper, coreutils, nix-prefetch-git, fetchurl, nodejs-slim, prefetch-yarn-deps, cacert, callPackage, nix }:
+
+let
+  yarnpkg-lockfile-tar = fetchurl {
+    url = "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz";
+    sha512 = "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==";
+  };
+
+in {
+  prefetch-yarn-deps = stdenv.mkDerivation {
+    name = "prefetch-yarn-deps";
+
+    dontUnpack = true;
+
+    nativeBuildInputs = [ makeWrapper ];
+    buildInputs = [ coreutils nix-prefetch-git nodejs-slim nix ];
+
+    buildPhase = ''
+      runHook preBuild
+
+      mkdir libexec
+      tar --strip-components=1 -xf ${yarnpkg-lockfile-tar} package/index.js
+      mv index.js libexec/yarnpkg-lockfile.js
+      cp ${./index.js} libexec/index.js
+      patchShebangs libexec/index.js
+
+      runHook postBuild
+    '';
+
+    installPhase = ''
+      runHook preInstall
+
+      mkdir -p $out/bin
+      cp -r libexec $out
+      makeWrapper $out/libexec/index.js $out/bin/prefetch-yarn-deps \
+        --prefix PATH : ${lib.makeBinPath [ coreutils nix-prefetch-git nix ]}
+
+      runHook postInstall
+    '';
+  };
+
+  fetchYarnDeps = let
+    f = {
+      name ? "offline",
+      yarnLock,
+      hash ? "",
+      sha256 ? "",
+    }: let
+      hash_ =
+        if hash != "" then { outputHashAlgo = null; outputHash = hash; }
+        else if sha256 != "" then { outputHashAlgo = "sha256"; outputHash = sha256; }
+        else { outputHashAlgo = "sha256"; outputHash = lib.fakeSha256; };
+    in stdenv.mkDerivation {
+      inherit name;
+
+      dontUnpack = true;
+      dontInstall = true;
+
+      nativeBuildInputs = [ prefetch-yarn-deps ];
+      GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt";
+
+      buildPhase = ''
+        mkdir -p $out
+        (cd $out; prefetch-yarn-deps --verbose --builder ${yarnLock})
+      '';
+
+      outputHashMode = "recursive";
+      inherit (hash_) outputHashAlgo outputHash;
+    };
+
+  in lib.setFunctionArgs f (lib.functionArgs f) // {
+    tests = callPackage ./tests {};
+  };
+}
diff --git a/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/index.js b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/index.js
new file mode 100755
index 000000000000..f3662a543616
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/index.js
@@ -0,0 +1,198 @@
+#!/usr/bin/env node
+'use strict'
+
+const fs = require('fs')
+const crypto = require('crypto')
+const process = require('process')
+const https = require('https')
+const child_process = require('child_process')
+const path = require('path')
+const lockfile = require('./yarnpkg-lockfile.js')
+const { promisify } = require('util')
+const url = require('url')
+
+const execFile = promisify(child_process.execFile)
+
+const exec = async (...args) => {
+	const res = await execFile(...args)
+	if (res.error) throw new Error(res.stderr)
+	return res
+}
+
+// This has to match the logic in pkgs/development/tools/yarn2nix-moretea/yarn2nix/lib/urlToName.js
+// so that fixup_yarn_lock produces the same paths
+const urlToName = url => {
+	const isCodeloadGitTarballUrl = url.startsWith('https://codeload.github.com/') && url.includes('/tar.gz/')
+
+	if (url.startsWith('git+') || isCodeloadGitTarballUrl) {
+		return path.basename(url)
+	} else {
+		return url
+			.replace(/https:\/\/(.)*(.com)\//g, '') // prevents having long directory names
+			.replace(/[@/%:-]/g, '_') // replace @ and : and - and % characters with underscore
+	}
+}
+
+const downloadFileHttps = (fileName, url, expectedHash) => {
+	return new Promise((resolve, reject) => {
+		https.get(url, (res) => {
+			const file = fs.createWriteStream(fileName)
+			const hash = crypto.createHash('sha1')
+			res.pipe(file)
+			res.pipe(hash).setEncoding('hex')
+			res.on('end', () => {
+				file.close()
+				const h = hash.read()
+				if (h != expectedHash) return reject(new Error(`hash mismatch, expected ${expectedHash}, got ${h}`))
+				resolve()
+			})
+                        res.on('error', e => reject(e))
+		})
+	})
+}
+
+const downloadGit = async (fileName, url, rev) => {
+	await exec('nix-prefetch-git', [
+		'--out', fileName + '.tmp',
+		'--url', url,
+		'--rev', rev,
+		'--builder'
+	])
+
+	await exec('tar', [
+		// hopefully make it reproducible across runs and systems
+		'--owner=0', '--group=0', '--numeric-owner', '--format=gnu', '--sort=name', '--mtime=@1',
+
+		// Set u+w because tar-fs can't unpack archives with read-only dirs: https://github.com/mafintosh/tar-fs/issues/79
+		'--mode', 'u+w',
+
+		'-C', fileName + '.tmp',
+		'-cf', fileName, '.'
+	])
+
+	await exec('rm', [ '-rf', fileName + '.tmp', ])
+}
+
+const isGitUrl = pattern => {
+	// https://github.com/yarnpkg/yarn/blob/3119382885ea373d3c13d6a846de743eca8c914b/src/resolvers/exotics/git-resolver.js#L15-L47
+	const GIT_HOSTS = ['github.com', 'gitlab.com', 'bitbucket.com', 'bitbucket.org']
+	const GIT_PATTERN_MATCHERS = [/^git:/, /^git\+.+:/, /^ssh:/, /^https?:.+\.git$/, /^https?:.+\.git#.+/]
+
+	for (const matcher of GIT_PATTERN_MATCHERS) if (matcher.test(pattern)) return true
+
+	const {hostname, path} = url.parse(pattern)
+	if (hostname && path && GIT_HOSTS.indexOf(hostname) >= 0
+		// only if dependency is pointing to a git repo,
+		// e.g. facebook/flow and not file in a git repo facebook/flow/archive/v1.0.0.tar.gz
+		&& path.split('/').filter(p => !!p).length === 2
+	) return true
+
+	return false
+}
+
+const downloadPkg = (pkg, verbose) => {
+	const [ url, hash ] = pkg.resolved.split('#')
+	if (verbose) console.log('downloading ' + url)
+	const fileName = urlToName(url)
+	if (url.startsWith('https://codeload.github.com/') && url.includes('/tar.gz/')) {
+		const s = url.split('/')
+		downloadGit(fileName, `https://github.com/${s[3]}/${s[4]}.git`, s[6])
+	} else if (isGitUrl(url)) {
+		return downloadGit(fileName, url.replace(/^git\+/, ''), hash)
+	} else if (url.startsWith('https://')) {
+		return downloadFileHttps(fileName, url, hash)
+	} else if (url.startsWith('file:')) {
+		console.warn(`ignoring unsupported file:path url "${url}"`)
+	} else {
+		throw new Error('don\'t know how to download "' + url + '"')
+	}
+}
+
+const performParallel = tasks => {
+	const worker = async () => {
+		while (tasks.length > 0) await tasks.shift()()
+	}
+
+	const workers = []
+	for (let i = 0; i < 4; i++) {
+		workers.push(worker())
+	}
+
+	return Promise.all(workers)
+}
+
+const prefetchYarnDeps = async (lockContents, verbose) => {
+	const lockData = lockfile.parse(lockContents)
+	const tasks = Object.values(
+		Object.entries(lockData.object)
+		.map(([key, value]) => {
+			return { key, ...value }
+		})
+		.reduce((out, pkg) => {
+			out[pkg.resolved] = pkg
+			return out
+		}, {})
+	)
+		.map(pkg => () => downloadPkg(pkg, verbose))
+
+	await performParallel(tasks)
+	await fs.promises.writeFile('yarn.lock', lockContents)
+	if (verbose) console.log('Done')
+}
+
+const showUsage = async () => {
+	process.stderr.write(`
+syntax: prefetch-yarn-deps [path to yarn.lock] [options]
+
+Options:
+  -h --help         Show this help
+  -v --verbose      Verbose output
+  --builder         Only perform the download to current directory, then exit
+`)
+	process.exit(1)
+}
+
+const main = async () => {
+	const args = process.argv.slice(2)
+	let next, lockFile, verbose, isBuilder
+	while (next = args.shift()) {
+		if (next == '--builder') {
+			isBuilder = true
+		} else if (next == '--verbose' || next == '-v') {
+			verbose = true
+		} else if (next == '--help' || next == '-h') {
+			showUsage()
+		} else if (!lockFile) {
+			lockFile = next
+		} else {
+			showUsage()
+		}
+	}
+	let lockContents
+	try {
+		lockContents = await fs.promises.readFile(lockFile || 'yarn.lock', 'utf-8')
+	} catch {
+		showUsage()
+	}
+
+	if (isBuilder) {
+		await prefetchYarnDeps(lockContents, verbose)
+	} else {
+		const { stdout: tmpDir } = await exec('mktemp', [ '-d' ])
+
+		try {
+			process.chdir(tmpDir.trim())
+			await prefetchYarnDeps(lockContents, verbose)
+			const { stdout: hash } = await exec('nix-hash', [ '--type', 'sha256', '--base32', tmpDir.trim() ])
+			console.log(hash)
+		} finally {
+			await exec('rm', [ '-rf', tmpDir.trim() ])
+		}
+	}
+}
+
+main()
+	.catch(e => {
+		console.error(e)
+		process.exit(1)
+	})
diff --git a/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/default.nix b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/default.nix
new file mode 100644
index 000000000000..a781dad83072
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/default.nix
@@ -0,0 +1,16 @@
+{ invalidateFetcherByDrvHash, fetchYarnDeps, ... }:
+
+{
+  simple = invalidateFetcherByDrvHash fetchYarnDeps {
+    yarnLock = ./simple.lock;
+    sha256 = "sha256-Erdkw2E8wWT09jFNLXGkrdwKl0HuSZWnUDJUrV95vSE=";
+  };
+  gitDep = invalidateFetcherByDrvHash fetchYarnDeps {
+    yarnLock = ./git.lock;
+    sha256 = "sha256-lAqN4LpoE+jgsQO1nDtuORwcVEO7ogEV53jCu2jFJUI=";
+  };
+  githubDep = invalidateFetcherByDrvHash fetchYarnDeps {
+    yarnLock = ./github.lock;
+    sha256 = "sha256-Tsfgyjxz8x6gNmfN0xR7G/NQNoEs4svxRN/N+26vfJU=";
+  };
+}
diff --git a/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/git.lock b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/git.lock
new file mode 100644
index 000000000000..9eda5b2c409d
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/git.lock
@@ -0,0 +1,7 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"async@git+https://github.com/caolan/async":
+  version "3.2.1"
+  resolved "git+https://github.com/caolan/async#fc9ba651341af5ab974aade6b1640e345912be83"
diff --git a/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/github.lock b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/github.lock
new file mode 100644
index 000000000000..057e043a5390
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/github.lock
@@ -0,0 +1,7 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"async@github:caolan/async":
+  version "3.2.1"
+  resolved "https://codeload.github.com/caolan/async/tar.gz/fc9ba651341af5ab974aade6b1640e345912be83"
diff --git a/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/simple.lock b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/simple.lock
new file mode 100644
index 000000000000..db2f4b2be4b7
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/node/fetch-yarn-deps/tests/simple.lock
@@ -0,0 +1,8 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+lit-html@1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-1.4.1.tgz#0c6f3ee4ad4eb610a49831787f0478ad8e9ae5e0"
+  integrity sha512-B9btcSgPYb1q4oSOb/PrOT6Z/H+r6xuNzfH4lFli/AWhYwdtrgQkQWBbIc6mdnf6E2IL3gDXdkkqNktpU0OZQA==
diff --git a/nixpkgs/pkgs/build-support/nuget-to-nix/nuget-to-nix.sh b/nixpkgs/pkgs/build-support/nuget-to-nix/nuget-to-nix.sh
index c14844bec59e..55a499370181 100755
--- a/nixpkgs/pkgs/build-support/nuget-to-nix/nuget-to-nix.sh
+++ b/nixpkgs/pkgs/build-support/nuget-to-nix/nuget-to-nix.sh
@@ -17,7 +17,7 @@ while read pkg_spec; do
     sed -nE 's/.*<id>([^<]*).*/\1/p; s/.*<version>([^<+]*).*/\1/p' "$pkg_spec")
   pkg_sha256="$(nix-hash --type sha256 --flat --base32 "$(dirname "$pkg_spec")"/*.nupkg)"
 
-  echo "  (fetchNuGet { name = \"$pkg_name\"; version = \"$pkg_version\"; sha256 = \"$pkg_sha256\"; })"
+  echo "  (fetchNuGet { pname = \"$pkg_name\"; version = \"$pkg_version\"; sha256 = \"$pkg_sha256\"; })"
 done < <(find $1 -name '*.nuspec' | sort)
 
 echo "]"
diff --git a/nixpkgs/pkgs/build-support/ocaml/default.nix b/nixpkgs/pkgs/build-support/ocaml/default.nix
index cd17eb688c2e..1fe99bb6320e 100644
--- a/nixpkgs/pkgs/build-support/ocaml/default.nix
+++ b/nixpkgs/pkgs/build-support/ocaml/default.nix
@@ -1,6 +1,6 @@
 { lib, stdenv, writeText, ocaml, findlib, ocamlbuild, camlp4 }:
 
-{ name, version, nativeBuildInputs ? [],
+{ pname ? args.name, version, nativeBuildInputs ? [],
   createFindlibDestdir ?  true,
   dontStrip ? true,
   minimumSupportedOcamlVersion ? null,
@@ -17,13 +17,13 @@ in
           lib.versionOlder minimumSupportedOcamlVersion ocaml.version;
 
 stdenv.mkDerivation (args // {
-  name = "ocaml-${name}-${version}";
+  name = "ocaml-${pname}-${version}";
 
   nativeBuildInputs = [ ocaml findlib ocamlbuild camlp4 ] ++ nativeBuildInputs;
 
   setupHook = if setupHook == null && hasSharedObjects
   then writeText "setupHook.sh" ''
-    export CAML_LD_LIBRARY_PATH="''${CAML_LD_LIBRARY_PATH-}''${CAML_LD_LIBRARY_PATH:+:}''$1/lib/ocaml/${ocaml.version}/site-lib/${name}/"
+    export CAML_LD_LIBRARY_PATH="''${CAML_LD_LIBRARY_PATH-}''${CAML_LD_LIBRARY_PATH:+:}''$1/lib/ocaml/${ocaml.version}/site-lib/${pname}/"
     ''
   else setupHook;
 
diff --git a/nixpkgs/pkgs/build-support/pkg-config-wrapper/default.nix b/nixpkgs/pkgs/build-support/pkg-config-wrapper/default.nix
index bbc49d6728c9..aa8f57ffb04d 100644
--- a/nixpkgs/pkgs/build-support/pkg-config-wrapper/default.nix
+++ b/nixpkgs/pkgs/build-support/pkg-config-wrapper/default.nix
@@ -47,6 +47,9 @@ stdenv.mkDerivation {
   dontBuild = true;
   dontConfigure = true;
 
+  # Additional flags passed to pkg-config.
+  addFlags = lib.optional stdenv.targetPlatform.isStatic "--static";
+
   unpackPhase = ''
     src=$PWD
   '';
diff --git a/nixpkgs/pkgs/build-support/pkg-config-wrapper/pkg-config-wrapper.sh b/nixpkgs/pkgs/build-support/pkg-config-wrapper/pkg-config-wrapper.sh
index f7c7429eb0b3..1aa14cfeb7cc 100644
--- a/nixpkgs/pkgs/build-support/pkg-config-wrapper/pkg-config-wrapper.sh
+++ b/nixpkgs/pkgs/build-support/pkg-config-wrapper/pkg-config-wrapper.sh
@@ -12,10 +12,12 @@ if [ -z "${NIX_PKG_CONFIG_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
     source @out@/nix-support/add-flags.sh
 fi
 
+set -- "$@" @addFlags@
+
 if (( ${#role_suffixes[@]} > 0 )); then
-	# replace env var with nix-modified one
+    # replace env var with nix-modified one
     PKG_CONFIG_PATH=$PKG_CONFIG_PATH_@suffixSalt@ exec @prog@ "$@"
 else
-	# pkg-config isn't a bonafied dependency so ignore setup hook entirely
-	exec @prog@ "$@"
+    # pkg-config isn't a real dependency so ignore setup hook entirely
+    exec @prog@ "$@"
 fi
diff --git a/nixpkgs/pkgs/build-support/release/ant-build.nix b/nixpkgs/pkgs/build-support/release/ant-build.nix
deleted file mode 100644
index 6b59241e01ed..000000000000
--- a/nixpkgs/pkgs/build-support/release/ant-build.nix
+++ /dev/null
@@ -1,123 +0,0 @@
-{ src
-, pkgs
-, lib
-, stdenv ? pkgs.stdenv
-, name
-, antTargets ? []
-, jars ? []
-, jarWrappers ? []
-, antProperties ? []
-, antBuildInputs ? []
-, buildfile ? "build.xml"
-, ant ? pkgs.ant
-, jre ? pkgs.jdk
-, hydraAntLogger ? pkgs.hydraAntLogger
-, zip ? pkgs.zip
-, unzip ? pkgs.unzip
-, ... } @ args:
-
-let
-  antFlags = "-f ${buildfile} " + lib.concatMapStrings ({name, value}: "-D${name}=${value} " ) antProperties ;
-in
-stdenv.mkDerivation (
-
-  {
-    inherit jre ant;
-    showBuildStats = true;
-
-    postPhases =
-      ["generateWrappersPhase" "finalPhase"];
-
-    prePhases =
-      ["antSetupPhase"];
-
-    antSetupPhase = with lib; ''
-      if test "$hydraAntLogger" != "" ; then
-        export ANT_ARGS="-logger org.hydra.ant.HydraLogger -lib `ls $hydraAntLogger/share/java/*.jar | head -1`"
-      fi
-      for abi in ${concatStringsSep " " (map (f: "`find ${f} -name '*.jar'`") antBuildInputs)}; do
-        export ANT_ARGS="$ANT_ARGS -lib $abi"
-      done
-    '';
-
-    installPhase = ''
-      runHook preInstall
-
-      mkdir -p $out/share/java
-      ${ if jars == [] then ''
-           find . -name "*.jar" | xargs -I{} cp -v {} $out/share/java
-         '' else lib.concatMapStrings (j: ''
-           cp -v ${j} $out/share/java
-         '') jars }
-
-      . ${./functions.sh}
-      for j in $out/share/java/*.jar ; do
-        canonicalizeJar $j
-        echo file jar $j >> $out/nix-support/hydra-build-products
-      done
-
-      runHook postInstall
-    '';
-
-    generateWrappersPhase =
-      let
-        cp = w: "-cp '${lib.optionalString (w ? classPath) w.classPath}${lib.optionalString (w ? mainClass) ":$out/share/java/*"}'";
-      in
-      ''
-      header "Generating jar wrappers"
-    '' + (lib.concatMapStrings (w: ''
-
-      mkdir -p $out/bin
-      cat >> $out/bin/${w.name} <<EOF
-      #!${pkgs.runtimeShell}
-      export JAVA_HOME=$jre
-      $jre/bin/java ${cp w} ${if w ? mainClass then w.mainClass else "-jar ${w.jar}"} \$@
-      EOF
-
-      chmod a+x $out/bin/${w.name} || exit 1
-    '') jarWrappers) + ''
-      closeNest
-    '';
-
-    buildPhase = ''
-      runHook preBuild
-    '' + (if antTargets == [] then ''
-      header "Building default ant target"
-      ant ${antFlags}
-      closeNest
-    '' else lib.concatMapStrings (t: ''
-      header "Building '${t}' target"
-      ant ${antFlags} ${t}
-      closeNest
-    '') antTargets) + ''
-      runHook postBuild
-    '';
-
-    finalPhase =
-      ''
-        # Propagate the release name of the source tarball.  This is
-        # to get nice package names in channels.
-        if test -e $origSrc/nix-support/hydra-release-name; then
-          cp $origSrc/nix-support/hydra-release-name $out/nix-support/hydra-release-name
-        fi
-      '';
-  }
-
-  // removeAttrs args ["antProperties" "buildInputs" "pkgs" "lib" "jarWrappers"] //
-
-  {
-    name = name + (if src ? version then "-" + src.version else "");
-
-    nativeBuildInputs = [ unzip ];
-    buildInputs = [ant jre zip] ++ lib.optional (args ? buildInputs) args.buildInputs ;
-
-    postHook = ''
-      mkdir -p $out/nix-support
-      echo "$system" > $out/nix-support/system
-      . ${./functions.sh}
-
-      origSrc=$src
-      src=$(findTarball $src)
-    '';
-  }
-)
diff --git a/nixpkgs/pkgs/build-support/release/default.nix b/nixpkgs/pkgs/build-support/release/default.nix
index 83f755b2bece..d593ec81197e 100644
--- a/nixpkgs/pkgs/build-support/release/default.nix
+++ b/nixpkgs/pkgs/build-support/release/default.nix
@@ -14,10 +14,6 @@ rec {
     { inherit stdenv;
     } // args);
 
-  antBuild = args: import ./ant-build.nix (
-    { inherit lib pkgs;
-    } // args);
-
   mvnBuild = args: import ./maven-build.nix (
     { inherit stdenv;
     } // args);
diff --git a/nixpkgs/pkgs/build-support/release/functions.sh b/nixpkgs/pkgs/build-support/release/functions.sh
index 120d19685427..0c4b81edf822 100644
--- a/nixpkgs/pkgs/build-support/release/functions.sh
+++ b/nixpkgs/pkgs/build-support/release/functions.sh
@@ -11,29 +11,6 @@ findTarball() {
     fi
 }
 
-canonicalizeJarManifest() {
-    local input=$1
-    # http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Notes_on_Manifest_and_Signature_Files
-    (head -n 1 $input && tail -n +2 $input | sort | grep -v '^\s*$') > $input-tmp
-    mv $input-tmp $input
-}
-
-# Post-process a jar file to contain canonical timestamps and metadata ordering
-canonicalizeJar() {
-    local input=$1
-    local outer=$(pwd)
-    unzip -qq $input -d $input-tmp
-    canonicalizeJarManifest $input-tmp/META-INF/MANIFEST.MF
-    # Set all timestamps to Jan 1 1980, which is the earliest date the zip format supports...
-    find $input-tmp -exec touch -t 198001010000.00 {} +
-    rm $input
-    pushd $input-tmp
-    zip -q -r -o -X $outer/tmp-out.jar . 2> /dev/null
-    popd
-    rm -rf $input-tmp
-    mv $outer/tmp-out.jar $input
-}
-
 propagateImageName() {
     mkdir -p $out/nix-support
     cat "$diskImage"/nix-support/full-name > $out/nix-support/full-name
diff --git a/nixpkgs/pkgs/build-support/rust/default.nix b/nixpkgs/pkgs/build-support/rust/build-rust-package/default.nix
index 845437d46757..85fb0e950410 100644
--- a/nixpkgs/pkgs/build-support/rust/default.nix
+++ b/nixpkgs/pkgs/build-support/rust/build-rust-package/default.nix
@@ -1,17 +1,15 @@
-{ stdenv
-, lib
-, buildPackages
+{ lib
+, importCargoLock
+, fetchCargoTarball
+, rust
+, stdenv
+, callPackage
 , cacert
+, git
 , cargoBuildHook
 , cargoCheckHook
 , cargoInstallHook
 , cargoSetupHook
-, fetchCargoTarball
-, importCargoLock
-, rustPlatform
-, callPackage
-, git
-, rust
 , rustc
 , libiconv
 , windows
@@ -21,12 +19,6 @@ let
   buildRustPackage =
     { name ? "${args.pname}-${args.version}"
 
-      # SRI hash
-    , cargoHash ? ""
-
-      # Legacy hash
-    , cargoSha256 ? ""
-
       # Name for the vendored dependencies tarball
     , cargoDepsName ? name
 
@@ -46,6 +38,10 @@ let
     , cargoLock ? null
     , cargoVendorDir ? null
     , checkType ? buildType
+    , buildNoDefaultFeatures ? false
+    , checkNoDefaultFeatures ? buildNoDefaultFeatures
+    , buildFeatures ? [ ]
+    , checkFeatures ? buildFeatures
     , depsExtraArgs ? {}
 
     # Toggles whether a custom sysroot is created when the target is a .json file.
@@ -58,7 +54,7 @@ let
     , buildAndTestSubdir ? null
     , ... } @ args:
 
-    assert cargoVendorDir == null && cargoLock == null -> cargoSha256 == "" && cargoHash == ""
+    assert cargoVendorDir == null && cargoLock == null -> !(args ? cargoSha256) && !(args ? cargoHash)
       -> throw "cargoSha256, cargoHash, cargoVendorDir, or cargoLock must be set";
     assert buildType == "release" || buildType == "debug";
 
@@ -70,15 +66,17 @@ let
         else fetchCargoTarball ({
           inherit src srcs sourceRoot unpackPhase cargoUpdateHook;
           name = cargoDepsName;
-          hash = cargoHash;
           patches = cargoPatches;
-          sha256 = cargoSha256;
+        } // lib.optionalAttrs (args ? cargoHash) {
+          hash = args.cargoHash;
+        } // lib.optionalAttrs (args ? cargoSha256) {
+          sha256 = args.cargoSha256;
         } // depsExtraArgs)
         else null;
 
       # If we have a cargoSha256 fixed-output derivation, validate it at build time
       # against the src fixed-output derivation to check consistency.
-      validateCargoDeps = !(cargoHash == "" && cargoSha256 == "");
+      validateCargoDeps = args ? cargoHash || args ? cargoSha256;
 
       target = rust.toRustTargetSpec stdenv.hostPlatform;
       targetIsJSON = lib.hasSuffix ".json" target;
@@ -90,7 +88,7 @@ let
           (lib.removeSuffix ".json" (builtins.baseNameOf "${target}"))
         else target;
 
-      sysroot = (callPackage ./sysroot {}) {
+      sysroot = callPackage ./sysroot { } {
         inherit target shortTarget;
         RUSTFLAGS = args.RUSTFLAGS or "";
         originalCargoToml = src + /Cargo.toml; # profile info is later extracted
@@ -111,6 +109,14 @@ let
 
       cargoCheckType = checkType;
 
+      cargoBuildNoDefaultFeatures = buildNoDefaultFeatures;
+
+      cargoCheckNoDefaultFeatures = checkNoDefaultFeatures;
+
+      cargoBuildFeatures = buildFeatures;
+
+      cargoCheckFeatures = checkFeatures;
+
       patchRegistryDeps = ./patch-registry-deps;
 
       nativeBuildInputs = nativeBuildInputs ++ [
diff --git a/nixpkgs/pkgs/build-support/rust/patch-registry-deps/pkg-config b/nixpkgs/pkgs/build-support/rust/build-rust-package/patch-registry-deps/pkg-config
index fbb094304587..fbb094304587 100644
--- a/nixpkgs/pkgs/build-support/rust/patch-registry-deps/pkg-config
+++ b/nixpkgs/pkgs/build-support/rust/build-rust-package/patch-registry-deps/pkg-config
diff --git a/nixpkgs/pkgs/build-support/rust/sysroot/default.nix b/nixpkgs/pkgs/build-support/rust/build-rust-package/sysroot/default.nix
index 4db7cf0dc392..1e0b901105cd 100644
--- a/nixpkgs/pkgs/build-support/rust/sysroot/default.nix
+++ b/nixpkgs/pkgs/build-support/rust/build-rust-package/sysroot/default.nix
@@ -3,17 +3,8 @@
 { 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
-    '';
+  cargoSrc = import ../../sysroot/src.nix {
+    inherit stdenv rustPlatform buildPackages originalCargoToml;
   };
 in rustPlatform.buildRustPackage {
   inherit target RUSTFLAGS;
diff --git a/nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix b/nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix
index 4050afe8dde1..841cad09efa1 100644
--- a/nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix
+++ b/nixpkgs/pkgs/build-support/rust/default-crate-overrides.nix
@@ -22,7 +22,11 @@
 , clang
 , llvmPackages
 , linux-pam
+, cmake
+, glib
+, freetype
 , rdkafka
+, udev
 , ...
 }:
 
@@ -61,6 +65,10 @@ in
     buildInputs = [ dbus ];
   };
 
+  expat-sys = attrs: {
+    nativeBuildInputs = [ cmake ];
+  };
+
   foundationdb-sys = attrs: {
     buildInputs = [ foundationdb ];
     # needed for 0.4+ release, when the FFI bindings are auto-generated
@@ -75,6 +83,16 @@ in
     buildInputs = [ foundationdb ];
   };
 
+  freetype-sys = attrs: {
+    nativeBuildInputs = [ cmake ];
+    buildInputs = [ freetype ];
+  };
+
+  glib-sys = attrs: {
+    nativeBuildInputs = [ pkg-config ];
+    buildInputs = [ glib ];
+  };
+
   gobject-sys = attrs: {
     buildInputs = [ dbus-glib ];
   };
@@ -112,6 +130,11 @@ in
     buildInputs = [ dbus ];
   };
 
+  libudev-sys = attrs: {
+    nativeBuildInputs = [ pkg-config ];
+    buildInputs = [ udev ];
+  };
+
   nettle-sys = attrs: {
     nativeBuildInputs = [ pkg-config ];
     buildInputs = [ nettle clang ];
@@ -184,6 +207,11 @@ in
     buildInputs = lib.optional stdenv.isDarwin Security;
   };
 
+  servo-fontconfig-sys = attrs: {
+    nativeBuildInputs = [ pkg-config ];
+    buildInputs = [ freetype ];
+  };
+
   thrussh-libsodium = attrs: {
     nativeBuildInputs = [ pkg-config ];
     buildInputs = [ libsodium ];
diff --git a/nixpkgs/pkgs/build-support/rust/cargo-vendor-normalise.py b/nixpkgs/pkgs/build-support/rust/fetch-cargo-tarball/cargo-vendor-normalise.py
index 2d7a18957184..2d7a18957184 100755
--- a/nixpkgs/pkgs/build-support/rust/cargo-vendor-normalise.py
+++ b/nixpkgs/pkgs/build-support/rust/fetch-cargo-tarball/cargo-vendor-normalise.py
diff --git a/nixpkgs/pkgs/build-support/rust/fetchCargoTarball.nix b/nixpkgs/pkgs/build-support/rust/fetch-cargo-tarball/default.nix
index 2e8830b47574..d36200aa5f90 100644
--- a/nixpkgs/pkgs/build-support/rust/fetchCargoTarball.nix
+++ b/nixpkgs/pkgs/build-support/rust/fetch-cargo-tarball/default.nix
@@ -9,8 +9,8 @@ let cargo-vendor-normalise = stdenv.mkDerivation {
   postFixup = "wrapPythonPrograms";
   doInstallCheck = true;
   installCheckPhase = ''
-    # check that ./fetchcargo-default-config.toml is a fix point
-    reference=${./fetchcargo-default-config.toml}
+    # check that ../fetchcargo-default-config.toml is a fix point
+    reference=${../fetchcargo-default-config.toml}
     < $reference $out/bin/cargo-vendor-normalise > test;
     cmp test $reference
   '';
@@ -22,15 +22,13 @@ in
 , srcs ? []
 , patches ? []
 , sourceRoot ? ""
-, hash ? ""
-, sha256 ? ""
 , cargoUpdateHook ? ""
 , ...
 } @ args:
 
 let hash_ =
-  if hash != "" then { outputHashAlgo = null; outputHash = hash; }
-  else if sha256 != "" then { outputHashAlgo = "sha256"; outputHash = sha256; }
+  if args ? hash then { outputHashAlgo = null; outputHash = args.hash; }
+  else if args ? sha256 then { outputHashAlgo = "sha256"; outputHash = args.sha256; }
   else throw "fetchCargoTarball requires a hash for ${name}";
 in stdenv.mkDerivation ({
   name = "${name}-vendor.tar.gz";
diff --git a/nixpkgs/pkgs/build-support/rust/hooks/cargo-build-hook.sh b/nixpkgs/pkgs/build-support/rust/hooks/cargo-build-hook.sh
index c10120c5aa19..54ed765012b9 100644
--- a/nixpkgs/pkgs/build-support/rust/hooks/cargo-build-hook.sh
+++ b/nixpkgs/pkgs/build-support/rust/hooks/cargo-build-hook.sh
@@ -13,6 +13,14 @@ cargoBuildHook() {
         cargoBuildProfileFlag="--${cargoBuildType}"
     fi
 
+    if [ -n "${cargoBuildNoDefaultFeatures-}" ]; then
+        cargoBuildNoDefaultFeaturesFlag=--no-default-features
+    fi
+
+    if [ -n "${cargoBuildFeatures-}" ]; then
+        cargoBuildFeaturesFlag="--features=${cargoBuildFeatures// /,}"
+    fi
+
     (
     set -x
     env \
@@ -24,6 +32,8 @@ cargoBuildHook() {
         --target @rustTargetPlatformSpec@ \
         --frozen \
         ${cargoBuildProfileFlag} \
+        ${cargoBuildNoDefaultFeaturesFlag} \
+        ${cargoBuildFeaturesFlag} \
         ${cargoBuildFlags}
     )
 
diff --git a/nixpkgs/pkgs/build-support/rust/hooks/cargo-check-hook.sh b/nixpkgs/pkgs/build-support/rust/hooks/cargo-check-hook.sh
index f0339afb38fa..57fc2779cfe9 100644
--- a/nixpkgs/pkgs/build-support/rust/hooks/cargo-check-hook.sh
+++ b/nixpkgs/pkgs/build-support/rust/hooks/cargo-check-hook.sh
@@ -16,11 +16,20 @@ cargoCheckHook() {
         threads=1
     fi
 
-    if [ "${cargoBuildType}" != "debug" ]; then
-        cargoBuildProfileFlag="--${cargoBuildType}"
+    if [ "${cargoCheckType}" != "debug" ]; then
+        cargoCheckProfileFlag="--${cargoCheckType}"
     fi
 
-    argstr="${cargoBuildProfileFlag} --target @rustTargetPlatformSpec@ --frozen ${cargoTestFlags}";
+    if [ -n "${cargoCheckNoDefaultFeatures-}" ]; then
+        cargoCheckNoDefaultFeaturesFlag=--no-default-features
+    fi
+
+    if [ -n "${cargoCheckFeatures-}" ]; then
+        cargoCheckFeaturesFlag="--features=${cargoCheckFeatures// /,}"
+    fi
+
+    argstr="${cargoCheckProfileFlag} ${cargoCheckNoDefaultFeaturesFlag} ${cargoCheckFeaturesFlag}
+        --target @rustTargetPlatformSpec@ --frozen ${cargoTestFlags}"
 
     (
         set -x
diff --git a/nixpkgs/pkgs/build-support/rust/import-cargo-lock.nix b/nixpkgs/pkgs/build-support/rust/import-cargo-lock.nix
index fe070e9638d4..fd3608741ea3 100644
--- a/nixpkgs/pkgs/build-support/rust/import-cargo-lock.nix
+++ b/nixpkgs/pkgs/build-support/rust/import-cargo-lock.nix
@@ -125,20 +125,31 @@ let
         };
       in runCommand "${pkg.name}-${pkg.version}" {} ''
         tree=${tree}
-        if grep --quiet '\[workspace\]' "$tree/Cargo.toml"; then
-          # If the target package is in a workspace, find the crate path
-          # using `cargo metadata`.
-          crateCargoTOML=$(${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path $tree/Cargo.toml | \
-            ${jq}/bin/jq -r '.packages[] | select(.name == "${pkg.name}") | .manifest_path')
 
+        # If the target package is in a workspace, or if it's the top-level
+        # crate, we should find the crate path using `cargo metadata`.
+        crateCargoTOML=$(${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path $tree/Cargo.toml | \
+          ${jq}/bin/jq -r '.packages[] | select(.name == "${pkg.name}") | .manifest_path')
+
+        # If the repository is not a workspace the package might be in a subdirectory.
+        if [[ -z $crateCargoTOML ]]; then
+          for manifest in $(find $tree -name "Cargo.toml"); do
+            echo Looking at $manifest
+            crateCargoTOML=$(${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path "$manifest" | ${jq}/bin/jq -r '.packages[] | select(.name == "${pkg.name}") | .manifest_path' || :)
             if [[ ! -z $crateCargoTOML ]]; then
-              tree=$(dirname $crateCargoTOML)
-            else
-              >&2 echo "Cannot find path for crate '${pkg.name}-${pkg.version}' in the Cargo workspace in: $tree"
-              exit 1
+              break
             fi
+          done
+
+          if [[ -z $crateCargoTOML ]]; then
+            >&2 echo "Cannot find path for crate '${pkg.name}-${pkg.version}' in the tree in: $tree"
+            exit 1
+          fi
         fi
 
+        echo Found crate ${pkg.name} at $crateCargoTOML
+        tree=$(dirname $crateCargoTOML)
+
         cp -prvd "$tree/" $out
         chmod u+w $out
 
diff --git a/nixpkgs/pkgs/build-support/rust/lib/default.nix b/nixpkgs/pkgs/build-support/rust/lib/default.nix
new file mode 100644
index 000000000000..24adcf2cb4e2
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/lib/default.nix
@@ -0,0 +1,37 @@
+{ lib }:
+
+rec {
+  # https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch
+  toTargetArch = platform:
+    if platform.isAarch32 then "arm"
+    else platform.parsed.cpu.name;
+
+  # https://doc.rust-lang.org/reference/conditional-compilation.html#target_os
+  toTargetOs = platform:
+    if platform.isDarwin then "macos"
+    else platform.parsed.kernel.name;
+
+  # Returns the name of the rust target, even if it is custom. Adjustments are
+  # because rust has slightly different naming conventions than we do.
+  toRustTarget = platform: let
+    inherit (platform.parsed) cpu vendor kernel abi;
+    cpu_ = platform.rustc.platform.arch or {
+      "armv7a" = "armv7";
+      "armv7l" = "armv7";
+      "armv6l" = "arm";
+      "armv5tel" = "armv5te";
+      "riscv64" = "riscv64gc";
+    }.${cpu.name} or cpu.name;
+    vendor_ = platform.rustc.platform.vendor or {
+      "w64" = "pc";
+    }.${vendor.name} or vendor.name;
+  in platform.rustc.config
+    or "${cpu_}-${vendor_}-${kernel.name}${lib.optionalString (abi.name != "unknown") "-${abi.name}"}";
+
+  # Returns the name of the rust target if it is standard, or the json file
+  # containing the custom target spec.
+  toRustTargetSpec = platform:
+    if (platform.rustc or {}) ? platform
+    then builtins.toFile (toRustTarget platform + ".json") (builtins.toJSON platform.rustc.platform)
+    else toRustTarget platform;
+}
diff --git a/nixpkgs/pkgs/build-support/rust/sysroot/Cargo.lock b/nixpkgs/pkgs/build-support/rust/sysroot/Cargo.lock
index 61fcef61744e..6ec6da6ae6e2 100644
--- a/nixpkgs/pkgs/build-support/rust/sysroot/Cargo.lock
+++ b/nixpkgs/pkgs/build-support/rust/sysroot/Cargo.lock
@@ -10,9 +10,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.36"
+version = "0.1.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cd0782e0a7da7598164153173e5a5d4d9b1da094473c98dce0ff91406112369"
+checksum = "b6591c2442ee984e2b264638a8b5e7ae44fd47b32d28e3a08e2e9c3cdb0c2fb0"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -22,8 +22,21 @@ name = "core"
 version = "0.0.0"
 
 [[package]]
+name = "nixpkgs-sysroot-stub-crate"
+version = "0.0.0"
+dependencies = [
+ "alloc",
+ "compiler_builtins",
+ "core",
+]
+
+[[package]]
 name = "rustc-std-workspace-core"
 version = "1.99.0"
 dependencies = [
  "core",
 ]
+
+[[patch.unused]]
+name = "rustc-std-workspace-alloc"
+version = "1.99.0"
diff --git a/nixpkgs/pkgs/build-support/rust/sysroot/cargo.py b/nixpkgs/pkgs/build-support/rust/sysroot/cargo.py
index 09f6fba6d1c8..9d970eff79e8 100644
--- a/nixpkgs/pkgs/build-support/rust/sysroot/cargo.py
+++ b/nixpkgs/pkgs/build-support/rust/sysroot/cargo.py
@@ -6,7 +6,7 @@ orig_cargo = os.environ['ORIG_CARGO'] if 'ORIG_CARGO' in os.environ else None
 
 base = {
   'package': {
-    'name': 'alloc',
+    'name': 'nixpkgs-sysroot-stub-crate',
     'version': '0.0.0',
     'authors': ['The Rust Project Developers'],
     'edition': '2018',
@@ -17,17 +17,19 @@ base = {
       'features': ['rustc-dep-of-std', 'mem'],
     },
     'core': {
-      'path': os.path.join(rust_src, 'libcore'),
+      'path': os.path.join(rust_src, 'core'),
+    },
+    'alloc': {
+      'path': os.path.join(rust_src, 'alloc'),
     },
-  },
-  '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'),
+        'path': os.path.join(rust_src, 'rustc-std-workspace-core'),
+      },
+      'rustc-std-workspace-alloc': {
+        'path': os.path.join(rust_src, 'rustc-std-workspace-alloc'),
       },
     },
   },
diff --git a/nixpkgs/pkgs/build-support/rust/sysroot/src.nix b/nixpkgs/pkgs/build-support/rust/sysroot/src.nix
new file mode 100644
index 000000000000..3d11b62dd315
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/sysroot/src.nix
@@ -0,0 +1,26 @@
+{ lib, stdenv, rustPlatform, buildPackages
+, originalCargoToml ? null
+}:
+
+stdenv.mkDerivation {
+  name = "cargo-src";
+  preferLocalBuild = true;
+
+  unpackPhase = "true";
+  dontConfigure = true;
+  dontBuild = true;
+
+  installPhase = ''
+    export RUSTC_SRC=${rustPlatform.rustLibSrc.override { }}
+  ''
+  + lib.optionalString (originalCargoToml != null) ''
+    export ORIG_CARGO=${originalCargoToml}
+  ''
+  + ''
+    ${buildPackages.python3.withPackages (ps: with ps; [ toml ])}/bin/python3 ${./cargo.py}
+    mkdir -p $out/src
+    touch $out/src/lib.rs
+    cp Cargo.toml $out/Cargo.toml
+    cp ${./Cargo.lock} $out/Cargo.lock
+  '';
+}
diff --git a/nixpkgs/pkgs/build-support/rust/sysroot/update-lockfile.sh b/nixpkgs/pkgs/build-support/rust/sysroot/update-lockfile.sh
index 83d29832384f..d0596d1e5a62 100755
--- a/nixpkgs/pkgs/build-support/rust/sysroot/update-lockfile.sh
+++ b/nixpkgs/pkgs/build-support/rust/sysroot/update-lockfile.sh
@@ -1,21 +1,27 @@
 #!/usr/bin/env nix-shell
 #!nix-shell -i bash -p python3 python3.pkgs.toml cargo
 
-set -e
+set -eu pipefile
 
-HERE=$(dirname "${BASH_SOURCE[0]}")
+HERE=$(readlink -e $(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."
+mkdir -p src
+touch src/lib.rs
 
-cp Cargo.lock "$HERE"
+RUSTC_SRC=$(nix-build "${NIXPKGS_ROOT}" -A pkgs.rustPlatform.rustLibSrc --no-out-link)
 
-rm -rf "$tempdir"
+ln -s $RUSTC_SRC/{core,alloc} ./
+
+export RUSTC_SRC
+python3 "$HERE/cargo.py"
 
+export RUSTC_BOOTSTRAP=1
+cargo generate-lockfile
 
+cp Cargo.lock "$HERE"
+
+rm -rf "$tempdir"
diff --git a/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/default.nix b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/default.nix
index 24e07099c058..c5c7b2f1c931 100644
--- a/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/default.nix
+++ b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/default.nix
@@ -7,6 +7,7 @@
   basicDynamic = callPackage ./basic-dynamic { };
   gitDependency = callPackage ./git-dependency { };
   gitDependencyRev = callPackage ./git-dependency-rev { };
+  gitDependencyRevNonWorkspaceNestedCrate = callPackage ./git-dependency-rev-non-workspace-nested-crate { };
   gitDependencyTag = callPackage ./git-dependency-tag { };
   gitDependencyBranch = callPackage ./git-dependency-branch { };
   maturin = callPackage ./maturin { };
diff --git a/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/Cargo.lock b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/Cargo.lock
new file mode 100644
index 000000000000..63ff1b3c113c
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/Cargo.lock
@@ -0,0 +1,638 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "anyhow"
+version = "1.0.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cargo-test-macro"
+version = "0.1.0"
+source = "git+https://github.com/rust-lang/cargo?branch=rust-1.53.0#4369396ce7d270972955d876eaa4954bea56bcd9"
+
+[[package]]
+name = "cargo-test-support"
+version = "0.1.0"
+source = "git+https://github.com/rust-lang/cargo?branch=rust-1.53.0#4369396ce7d270972955d876eaa4954bea56bcd9"
+dependencies = [
+ "anyhow",
+ "cargo-test-macro",
+ "cargo-util",
+ "filetime",
+ "flate2",
+ "git2",
+ "glob",
+ "lazy_static",
+ "remove_dir_all",
+ "serde_json",
+ "tar",
+ "toml",
+ "url",
+]
+
+[[package]]
+name = "cargo-util"
+version = "0.1.0"
+source = "git+https://github.com/rust-lang/cargo?branch=rust-1.53.0#4369396ce7d270972955d876eaa4954bea56bcd9"
+dependencies = [
+ "anyhow",
+ "core-foundation",
+ "crypto-hash",
+ "filetime",
+ "hex 0.4.3",
+ "jobserver",
+ "libc",
+ "log",
+ "miow",
+ "same-file",
+ "shell-escape",
+ "tempfile",
+ "walkdir",
+ "winapi",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
+dependencies = [
+ "jobserver",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "commoncrypto"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
+dependencies = [
+ "commoncrypto-sys",
+]
+
+[[package]]
+name = "commoncrypto-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+
+[[package]]
+name = "crc32fast"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crypto-hash"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a77162240fd97248d19a564a565eb563a3f592b386e4136fb300909e67dddca"
+dependencies = [
+ "commoncrypto",
+ "hex 0.3.2",
+ "openssl",
+ "winapi",
+]
+
+[[package]]
+name = "filetime"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "winapi",
+]
+
+[[package]]
+name = "flate2"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
+dependencies = [
+ "cfg-if",
+ "crc32fast",
+ "libc",
+ "libz-sys",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
+dependencies = [
+ "matches",
+ "percent-encoding",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "git-dependency-rev-non-workspace-nested-crate"
+version = "0.1.0"
+dependencies = [
+ "cargo-test-support",
+]
+
+[[package]]
+name = "git2"
+version = "0.13.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a8057932925d3a9d9e4434ea016570d37420ddb1ceed45a174d577f24ed6700"
+dependencies = [
+ "bitflags",
+ "libc",
+ "libgit2-sys",
+ "log",
+ "openssl-probe",
+ "openssl-sys",
+ "url",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "hex"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "idna"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
+dependencies = [
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
+
+[[package]]
+name = "jobserver"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.105"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
+
+[[package]]
+name = "libgit2-sys"
+version = "0.12.24+1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddbd6021eef06fb289a8f54b3c2acfdd85ff2a585dfbb24b8576325373d2152c"
+dependencies = [
+ "cc",
+ "libc",
+ "libssh2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+]
+
+[[package]]
+name = "libssh2-sys"
+version = "0.2.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca"
+dependencies = [
+ "cc",
+ "libc",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "libz-sys"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "matches"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+dependencies = [
+ "adler",
+ "autocfg",
+]
+
+[[package]]
+name = "miow"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
+
+[[package]]
+name = "openssl"
+version = "0.10.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058"
+dependencies = [
+ "autocfg",
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10e2fcbb64ecbe64c8e040a386c3104d384583af58b956d870aaaf229df6e66d"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741"
+
+[[package]]
+name = "rand"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.130"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
+
+[[package]]
+name = "serde_json"
+version = "1.0.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "shell-escape"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
+
+[[package]]
+name = "tar"
+version = "0.4.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c"
+dependencies = [
+ "filetime",
+ "libc",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "rand",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
+
+[[package]]
+name = "toml"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "url"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "matches",
+ "percent-encoding",
+]
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "walkdir"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+dependencies = [
+ "same-file",
+ "winapi",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/Cargo.toml b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/Cargo.toml
new file mode 100644
index 000000000000..61f1a08dbe4f
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "git-dependency-rev-non-workspace-nested-crate"
+version = "0.1.0"
+authors = ["Stefan Junker <mail@stefanjunker.de>"]
+edition = "2018"
+
+[dependencies]
+cargo-test-support = { git = "https://github.com/rust-lang/cargo", branch = "rust-1.53.0" }
diff --git a/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/default.nix b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/default.nix
new file mode 100644
index 000000000000..dcf1e601c31c
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/default.nix
@@ -0,0 +1,31 @@
+{ rustPlatform, pkg-config, openssl, lib, darwin, stdenv }:
+
+rustPlatform.buildRustPackage {
+  pname = "git-dependency-rev-non-workspace-nested-crate";
+  version = "0.1.0";
+
+  src = ./.;
+
+  nativeBuildInputs = [
+    pkg-config
+  ];
+
+  buildInputs = [
+    openssl
+  ] ++ lib.optionals stdenv.isDarwin [
+    darwin.apple_sdk.frameworks.Security
+  ];
+
+  cargoLock = {
+    lockFile = ./Cargo.lock;
+    outputHashes = {
+      "cargo-test-macro-0.1.0" = "1yy1y1d523xdzwg1gc77pigbcwsbawmy4b7vw8v21m7q957sk0c4";
+    };
+  };
+
+  doInstallCheck = true;
+
+  installCheckPhase = ''
+    $out/bin/git-dependency-rev-non-workspace-nested-crate
+  '';
+}
diff --git a/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/src/main.rs b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/src/main.rs
new file mode 100644
index 000000000000..cb4bfb5d928b
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-rev-non-workspace-nested-crate/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+    println!("{}", cargo_test_support::t!(Result::<&str, &str>::Ok("msg")));
+}
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/canonicalize-jars.sh b/nixpkgs/pkgs/build-support/setup-hooks/canonicalize-jars.sh
new file mode 100644
index 000000000000..8c55810748ea
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/setup-hooks/canonicalize-jars.sh
@@ -0,0 +1,17 @@
+# This setup hook causes the fixup phase to repack all JAR files in a
+# canonical & deterministic fashion, e.g. resetting mtimes (like with normal
+# store files) and avoiding impure metadata.
+
+fixupOutputHooks+=('if [ -z "$dontCanonicalizeJars" -a -e "$prefix" ]; then canonicalizeJarsIn "$prefix"; fi')
+
+canonicalizeJarsIn() {
+  local dir="$1"
+  header "canonicalizing jars in $dir"
+  dir="$(realpath -sm -- "$dir")"
+  while IFS= read -rd '' f; do
+    canonicalizeJar "$f"
+  done < <(find -- "$dir" -type f -name '*.jar' -print0)
+  stopNest
+}
+
+source @canonicalize_jar@
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/copy-desktop-items.sh b/nixpkgs/pkgs/build-support/setup-hooks/copy-desktop-items.sh
index f96a10f33d5c..b5c5ed81eb97 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/copy-desktop-items.sh
+++ b/nixpkgs/pkgs/build-support/setup-hooks/copy-desktop-items.sh
@@ -30,8 +30,8 @@ copyDesktopItems() {
 
     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"
+            echo "Copying '$desktopItem' into '$out/share/applications'"
+            install -D -m 444 -t "$out"/share/applications "$desktopItem"
         else
             for f in "$desktopItem"/share/applications/*.desktop; do
                 echo "Copying '$f' into '$out/share/applications'"
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/make-binary-wrapper.sh b/nixpkgs/pkgs/build-support/setup-hooks/make-binary-wrapper.sh
new file mode 100644
index 000000000000..986be5b9e113
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/setup-hooks/make-binary-wrapper.sh
@@ -0,0 +1,391 @@
+
+set -euo pipefail
+
+# Assert that FILE exists and is executable
+#
+# assertExecutable FILE
+assertExecutable() {
+    local file="$1"
+    [[ -f "$file" && -x "$file" ]] || \
+        die "Cannot wrap '$file' because it is not an executable file"
+}
+
+# Generate a binary executable wrapper for wrapping an executable.
+# The binary is compiled from generated C-code using gcc.
+# makeWrapper EXECUTABLE OUT_PATH ARGS
+
+# ARGS:
+# --argv0       NAME    : set name of executed process to NAME
+#                         (otherwise it’s called …-wrapped)
+# --inherit-argv0       : the executable inherits argv0 from the wrapper.
+#                         (use instead of --argv0 '$0')
+# --set         VAR VAL : add VAR with value VAL to the executable’s
+#                         environment
+# --set-default VAR VAL : like --set, but only adds VAR if not already set in
+#                         the environment
+# --unset       VAR     : remove VAR from the environment
+# --chdir       DIR     : change working directory (use instead of --run "cd DIR")
+# --add-flags   FLAGS   : add FLAGS to invocation of executable
+
+# --prefix          ENV SEP VAL   : suffix/prefix ENV with VAL, separated by SEP
+# --suffix
+
+# To troubleshoot a binary wrapper after you compiled it,
+# use the `strings` command or open the binary file in a text editor.
+makeWrapper() {
+    local original="$1"
+    local wrapper="$2"
+    shift 2
+
+    assertExecutable "$original"
+
+    mkdir -p "$(dirname "$wrapper")"
+
+    makeDocumentedCWrapper "$original" "$@" | \
+      @CC@ \
+        -Wall -Werror -Wpedantic \
+        -Os \
+        -x c \
+        -o "$wrapper" -
+}
+
+# Syntax: wrapProgram <PROGRAM> <MAKE-WRAPPER FLAGS...>
+wrapProgram() {
+    local prog="$1"
+    local hidden
+
+    assertExecutable "$prog"
+
+    hidden="$(dirname "$prog")/.$(basename "$prog")"-wrapped
+    while [ -e "$hidden" ]; do
+      hidden="${hidden}_"
+    done
+    mv "$prog" "$hidden"
+    # Silence warning about unexpanded $0:
+    # shellcheck disable=SC2016
+    makeWrapper "$hidden" "$prog" --inherit-argv0 "${@:2}"
+}
+
+# Generate source code for the wrapper in such a way that the wrapper inputs
+# will still be readable even after compilation
+# makeDocumentedCWrapper EXECUTABLE ARGS
+# ARGS: same as makeWrapper
+makeDocumentedCWrapper() {
+    local src docs
+    src=$(makeCWrapper "$@")
+    docs=$(docstring "$@")
+    printf '%s\n\n' "$src"
+    printf '%s\n' "$docs"
+}
+
+# makeCWrapper EXECUTABLE ARGS
+# ARGS: same as makeWrapper
+makeCWrapper() {
+    local argv0 inherit_argv0 n params cmd main flagsBefore flags executable length
+    local uses_prefix uses_suffix uses_assert uses_assert_success uses_stdio uses_asprintf
+    executable=$(escapeStringLiteral "$1")
+    params=("$@")
+    length=${#params[*]}
+    for ((n = 1; n < length; n += 1)); do
+        p="${params[n]}"
+        case $p in
+            --set)
+                cmd=$(setEnv "${params[n + 1]}" "${params[n + 2]}")
+                main="$main$cmd"$'\n'
+                n=$((n + 2))
+                [ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 2 arguments"$'\n'
+            ;;
+            --set-default)
+                cmd=$(setDefaultEnv "${params[n + 1]}" "${params[n + 2]}")
+                main="$main$cmd"$'\n'
+                uses_stdio=1
+                uses_assert_success=1
+                n=$((n + 2))
+                [ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 2 arguments"$'\n'
+            ;;
+            --unset)
+                cmd=$(unsetEnv "${params[n + 1]}")
+                main="$main$cmd"$'\n'
+                uses_stdio=1
+                uses_assert_success=1
+                n=$((n + 1))
+                [ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 1 argument"$'\n'
+            ;;
+            --prefix)
+                cmd=$(setEnvPrefix "${params[n + 1]}" "${params[n + 2]}" "${params[n + 3]}")
+                main="$main$cmd"$'\n'
+                uses_prefix=1
+                uses_asprintf=1
+                uses_stdio=1
+                uses_assert_success=1
+                uses_assert=1
+                n=$((n + 3))
+                [ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 3 arguments"$'\n'
+            ;;
+            --suffix)
+                cmd=$(setEnvSuffix "${params[n + 1]}" "${params[n + 2]}" "${params[n + 3]}")
+                main="$main$cmd"$'\n'
+                uses_suffix=1
+                uses_asprintf=1
+                uses_stdio=1
+                uses_assert_success=1
+                uses_assert=1
+                n=$((n + 3))
+                [ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 3 arguments"$'\n'
+            ;;
+            --chdir)
+                cmd=$(changeDir "${params[n + 1]}")
+                main="$main$cmd"$'\n'
+                uses_stdio=1
+                uses_assert_success=1
+                n=$((n + 1))
+                [ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 1 argument"$'\n'
+            ;;
+            --add-flags)
+                flags="${params[n + 1]}"
+                flagsBefore="$flagsBefore $flags"
+                uses_assert=1
+                n=$((n + 1))
+                [ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 1 argument"$'\n'
+            ;;
+            --argv0)
+                argv0=$(escapeStringLiteral "${params[n + 1]}")
+                inherit_argv0=
+                n=$((n + 1))
+                [ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 1 argument"$'\n'
+            ;;
+            --inherit-argv0)
+                # Whichever comes last of --argv0 and --inherit-argv0 wins
+                inherit_argv0=1
+            ;;
+            *) # Using an error macro, we will make sure the compiler gives an understandable error message
+                main="$main#error makeCWrapper: Unknown argument ${p}"$'\n'
+            ;;
+        esac
+    done
+    # shellcheck disable=SC2086
+    [ -z "$flagsBefore" ] || main="$main"${main:+$'\n'}$(addFlags $flagsBefore)$'\n'$'\n'
+    [ -z "$inherit_argv0" ] && main="${main}argv[0] = \"${argv0:-${executable}}\";"$'\n'
+    main="${main}return execv(\"${executable}\", argv);"$'\n'
+
+    [ -z "$uses_asprintf" ] || printf '%s\n' "#define _GNU_SOURCE         /* See feature_test_macros(7) */"
+    printf '%s\n' "#include <unistd.h>"
+    printf '%s\n' "#include <stdlib.h>"
+    [ -z "$uses_assert" ]   || printf '%s\n' "#include <assert.h>"
+    [ -z "$uses_stdio" ]    || printf '%s\n' "#include <stdio.h>"
+    [ -z "$uses_assert_success" ] || printf '\n%s\n' "#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)"
+    [ -z "$uses_prefix" ] || printf '\n%s\n' "$(setEnvPrefixFn)"
+    [ -z "$uses_suffix" ] || printf '\n%s\n' "$(setEnvSuffixFn)"
+    printf '\n%s' "int main(int argc, char **argv) {"
+    printf '\n%s' "$(indent4 "$main")"
+    printf '\n%s\n' "}"
+}
+
+addFlags() {
+    local result n flag flags var
+    var="argv_tmp"
+    flags=("$@")
+    for ((n = 0; n < ${#flags[*]}; n += 1)); do
+        flag=$(escapeStringLiteral "${flags[$n]}")
+        result="$result${var}[$((n+1))] = \"$flag\";"$'\n'
+    done
+    printf '%s\n' "char **$var = calloc($((n+1)) + argc, sizeof(*$var));"
+    printf '%s\n' "assert($var != NULL);"
+    printf '%s\n' "${var}[0] = argv[0];"
+    printf '%s' "$result"
+    printf '%s\n' "for (int i = 1; i < argc; ++i) {"
+    printf '%s\n' "    ${var}[$n + i] = argv[i];"
+    printf '%s\n' "}"
+    printf '%s\n' "${var}[$n + argc] = NULL;"
+    printf '%s\n' "argv = $var;"
+}
+
+# chdir DIR
+changeDir() {
+    local dir
+    dir=$(escapeStringLiteral "$1")
+    printf '%s' "assert_success(chdir(\"$dir\"));"
+}
+
+# prefix ENV SEP VAL
+setEnvPrefix() {
+    local env sep val
+    env=$(escapeStringLiteral "$1")
+    sep=$(escapeStringLiteral "$2")
+    val=$(escapeStringLiteral "$3")
+    printf '%s' "set_env_prefix(\"$env\", \"$sep\", \"$val\");"
+    assertValidEnvName "$1"
+}
+
+# suffix ENV SEP VAL
+setEnvSuffix() {
+    local env sep val
+    env=$(escapeStringLiteral "$1")
+    sep=$(escapeStringLiteral "$2")
+    val=$(escapeStringLiteral "$3")
+    printf '%s' "set_env_suffix(\"$env\", \"$sep\", \"$val\");"
+    assertValidEnvName "$1"
+}
+
+# setEnv KEY VALUE
+setEnv() {
+    local key value
+    key=$(escapeStringLiteral "$1")
+    value=$(escapeStringLiteral "$2")
+    printf '%s' "putenv(\"$key=$value\");"
+    assertValidEnvName "$1"
+}
+
+# setDefaultEnv KEY VALUE
+setDefaultEnv() {
+    local key value
+    key=$(escapeStringLiteral "$1")
+    value=$(escapeStringLiteral "$2")
+    printf '%s' "assert_success(setenv(\"$key\", \"$value\", 0));"
+    assertValidEnvName "$1"
+}
+
+# unsetEnv KEY
+unsetEnv() {
+    local key
+    key=$(escapeStringLiteral "$1")
+    printf '%s' "assert_success(unsetenv(\"$key\"));"
+    assertValidEnvName "$1"
+}
+
+# Makes it safe to insert STRING within quotes in a C String Literal.
+# escapeStringLiteral STRING
+escapeStringLiteral() {
+    local result
+    result=${1//$'\\'/$'\\\\'}
+    result=${result//\"/'\"'}
+    result=${result//$'\n'/"\n"}
+    result=${result//$'\r'/"\r"}
+    printf '%s' "$result"
+}
+
+# Indents every non-empty line by 4 spaces. To avoid trailing whitespace, we don't indent empty lines
+# indent4 TEXT_BLOCK
+indent4() {
+    printf '%s' "$1" | awk '{ if ($0 != "") { print "    "$0 } else { print $0 }}'
+}
+
+assertValidEnvName() {
+    case "$1" in
+        *=*) printf '\n%s\n' "#error Illegal environment variable name \`$1\` (cannot contain \`=\`)";;
+        "")  printf '\n%s\n' "#error Environment variable name can't be empty.";;
+    esac
+}
+
+setEnvPrefixFn() {
+    printf '%s' "\
+void set_env_prefix(char *env, char *sep, char *prefix) {
+    char *existing = getenv(env);
+    if (existing) {
+        char *val;
+        assert_success(asprintf(&val, \"%s%s%s\", prefix, sep, existing));
+        assert_success(setenv(env, val, 1));
+        free(val);
+    } else {
+        assert_success(setenv(env, prefix, 1));
+    }
+}
+"
+}
+
+setEnvSuffixFn() {
+    printf '%s' "\
+void set_env_suffix(char *env, char *sep, char *suffix) {
+    char *existing = getenv(env);
+    if (existing) {
+        char *val;
+        assert_success(asprintf(&val, \"%s%s%s\", existing, sep, suffix));
+        assert_success(setenv(env, val, 1));
+        free(val);
+    } else {
+        assert_success(setenv(env, suffix, 1));
+    }
+}
+"
+}
+
+# Embed a C string which shows up as readable text in the compiled binary wrapper
+# documentationString ARGS
+docstring() {
+    printf '%s' "const char * DOCSTRING = \"$(escapeStringLiteral "
+
+
+# ------------------------------------------------------------------------------------
+# The C-code for this binary wrapper has been generated using the following command:
+
+
+makeCWrapper $(formatArgs "$@")
+
+
+# (Use \`nix-shell -p makeBinaryWrapper\` to get access to makeCWrapper in your shell)
+# ------------------------------------------------------------------------------------
+
+
+")\";"
+}
+
+# formatArgs EXECUTABLE ARGS
+formatArgs() {
+    printf '%s' "$1"
+    shift
+    while [ $# -gt 0 ]; do
+        case "$1" in
+            --set)
+                formatArgsLine 2 "$@"
+                shift 2
+            ;;
+            --set-default)
+                formatArgsLine 2 "$@"
+                shift 2
+            ;;
+            --unset)
+                formatArgsLine 1 "$@"
+                shift 1
+            ;;
+            --prefix)
+                formatArgsLine 3 "$@"
+                shift 3
+            ;;
+            --suffix)
+                formatArgsLine 3 "$@"
+                shift 3
+            ;;
+            --chdir)
+                formatArgsLine 1 "$@"
+                shift 1
+            ;;
+            --add-flags)
+                formatArgsLine 1 "$@"
+                shift 1
+            ;;
+            --argv0)
+                formatArgsLine 1 "$@"
+                shift 1
+            ;;
+            --inherit-argv0)
+                formatArgsLine 0 "$@"
+            ;;
+        esac
+        shift
+    done
+    printf '%s\n' ""
+}
+
+# formatArgsLine ARG_COUNT ARGS
+formatArgsLine() {
+    local ARG_COUNT LENGTH
+    ARG_COUNT=$1
+    LENGTH=$#
+    shift
+    printf '%s' $' \\\n    '"$1"
+    shift
+    while [ "$ARG_COUNT" -gt $((LENGTH - $# - 2)) ]; do
+        printf ' %s' "${1@Q}"
+        shift
+    done
+}
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/role.bash b/nixpkgs/pkgs/build-support/setup-hooks/role.bash
index cf69e732e7c3..b2d34a1f8606 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/role.bash
+++ b/nixpkgs/pkgs/build-support/setup-hooks/role.bash
@@ -17,7 +17,7 @@ function getRole() {
             role_post='_FOR_TARGET'
             ;;
         *)
-            echo "@name@: used as improper sort of dependency" >2
+            echo "@name@: used as improper sort of dependency" >&2
             return 1
             ;;
     esac
@@ -64,7 +64,7 @@ function getTargetRoleWrapper() {
             export NIX_@wrapperName@_TARGET_TARGET_@suffixSalt@=1
             ;;
         *)
-            echo "@name@: used as improper sort of dependency" >2
+            echo "@name@: used as improper sort of dependency" >&2
             return 1
             ;;
     esac
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh b/nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh
index 2481d8f50470..1a23e6b198ee 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh
+++ b/nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh
@@ -28,10 +28,16 @@ _separateDebugInfo() {
         # Extract the debug info.
         header "separating debug info from $i (build ID $id)"
         mkdir -p "$dst/${id:0:2}"
-        $OBJCOPY --only-keep-debug "$i" "$dst/${id:0:2}/${id:2}.debug"
-        $STRIP --strip-debug "$i"
 
-        # Also a create a symlink <original-name>.debug.
-        ln -sfn ".build-id/${id:0:2}/${id:2}.debug" "$dst/../$(basename "$i")"
+        # This may fail, e.g. if the binary is for a different
+        # architecture than we're building for.  (This happens with
+        # firmware blobs in QEMU.)
+        (
+            $OBJCOPY --only-keep-debug "$i" "$dst/${id:0:2}/${id:2}.debug"
+            $STRIP --strip-debug "$i"
+
+            # Also a create a symlink <original-name>.debug.
+            ln -sfn ".build-id/${id:0:2}/${id:2}.debug" "$dst/../$(basename "$i")"
+        ) || rmdir -p "$dst/${id:0:2}"
     done < <(find "$prefix" -type f -print0)
 }
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/shorten-perl-shebang.sh b/nixpkgs/pkgs/build-support/setup-hooks/shorten-perl-shebang.sh
index 4bf7c0ff1af4..825da1bde962 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/shorten-perl-shebang.sh
+++ b/nixpkgs/pkgs/build-support/setup-hooks/shorten-perl-shebang.sh
@@ -71,9 +71,9 @@ _shortenPerlShebang() {
             print
         }
     ' "$program" > "$temp" || die
-	# Preserve the mode of the original file
-	cp --preserve=mode --attributes-only "$program" "$temp"
-	mv "$temp" "$program"
+    # Preserve the mode of the original file
+    cp --preserve=mode --attributes-only "$program" "$temp"
+    mv "$temp" "$program"
 
     # Measure the new shebang line length and make sure it's okay. We subtract
     # one to account for the trailing newline that "head" included in its
diff --git a/nixpkgs/pkgs/build-support/setup-hooks/strip.sh b/nixpkgs/pkgs/build-support/setup-hooks/strip.sh
index c31a50eba57b..2d8e66a89fa3 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 -exec $cmd $commonStripFlags $stripFlags '{}' \; 2>/dev/null
+        find $dirs -type f -exec $cmd $stripFlags '{}' \; 2>/dev/null
         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 ada1b56760d6..c212a1f5301a 100644
--- a/nixpkgs/pkgs/build-support/setup-hooks/validate-pkg-config.sh
+++ b/nixpkgs/pkgs/build-support/setup-hooks/validate-pkg-config.sh
@@ -7,7 +7,7 @@ _validatePkgConfig() {
     for pc in $(find "$prefix" -name '*.pc'); do
         # Do not fail immediately. It's nice to see all errors when
         # there are multiple pkgconfig files.
-        if ! pkg-config --validate "$pc"; then
+        if ! $PKG_CONFIG --validate "$pc"; then
             bail=1
         fi
     done
diff --git a/nixpkgs/pkgs/build-support/singularity-tools/default.nix b/nixpkgs/pkgs/build-support/singularity-tools/default.nix
index 318f5b430fef..a6a3cd001b4a 100644
--- a/nixpkgs/pkgs/build-support/singularity-tools/default.nix
+++ b/nixpkgs/pkgs/build-support/singularity-tools/default.nix
@@ -73,7 +73,7 @@ rec {
             ''}
 
             # Build /bin and copy across closure
-            mkdir -p bin nix/store
+            mkdir -p bin ./${builtins.storeDir}
             for f in $(cat $layerClosure) ; do
               cp -ar $f ./$f
             done
diff --git a/nixpkgs/pkgs/build-support/trivial-builders.nix b/nixpkgs/pkgs/build-support/trivial-builders.nix
index f06d2136b8c6..3c9f3189d2cf 100644
--- a/nixpkgs/pkgs/build-support/trivial-builders.nix
+++ b/nixpkgs/pkgs/build-support/trivial-builders.nix
@@ -1,4 +1,4 @@
-{ lib, stdenv, stdenvNoCC, lndir, runtimeShell }:
+{ lib, stdenv, stdenvNoCC, lndir, runtimeShell, shellcheck }:
 
 rec {
 
@@ -111,9 +111,10 @@ rec {
     , executable ? false # run chmod +x ?
     , destination ? ""   # relative path appended to $out eg "/bin/foo"
     , checkPhase ? ""    # syntax checks, e.g. for scripts
+    , meta ? { }
     }:
     runCommand name
-      { inherit text executable checkPhase;
+      { inherit text executable checkPhase meta;
         passAsFile = [ "text" ];
         # Pointless to do this on a remote machine.
         preferLocalBuild = true;
@@ -249,6 +250,60 @@ rec {
       '';
     };
 
+  /*
+   * Similar to writeShellScriptBin and writeScriptBin.
+   * Writes an executable Shell script to /nix/store/<store path>/bin/<name> and
+   * checks its syntax with shellcheck and the shell's -n option.
+   * Automatically includes sane set of shellopts (errexit, nounset, pipefail)
+   * and handles creation of PATH based on runtimeInputs
+   *
+   * Note that the checkPhase uses stdenv.shell for the test run of the script,
+   * while the generated shebang uses runtimeShell. If, for whatever reason,
+   * those were to mismatch you might lose fidelity in the default checks.
+   *
+   * Example:
+   * # Writes my-file to /nix/store/<store path>/bin/my-file and makes executable.
+   * writeShellApplication {
+   *   name = "my-file";
+   *   runtimeInputs = [ curl w3m ];
+   *   text = ''
+   *     curl -s 'https://nixos.org' | w3m -dump -T text/html
+   *    '';
+   * }
+  */
+  writeShellApplication =
+    { name
+    , text
+    , runtimeInputs ? [ ]
+    , checkPhase ? null
+    }:
+    writeTextFile {
+      inherit name;
+      executable = true;
+      destination = "/bin/${name}";
+      text = ''
+        #!${runtimeShell}
+        set -o errexit
+        set -o nounset
+        set -o pipefail
+
+        export PATH="${lib.makeBinPath runtimeInputs}:$PATH"
+
+        ${text}
+      '';
+
+      checkPhase =
+        if checkPhase == null then ''
+          runHook preCheck
+          ${stdenv.shell} -n $out/bin/${name}
+          ${shellcheck}/bin/shellcheck $out/bin/${name}
+          runHook postCheck
+        ''
+        else checkPhase;
+
+      meta.mainProgram = name;
+    };
+
   # Create a C binary
   writeCBin = name: code:
     runCommandCC name
@@ -465,6 +520,88 @@ rec {
     '';
 
 
+  /*
+   * Extract a string's references to derivations and paths (its
+   * context) and write them to a text file, removing the input string
+   * itself from the dependency graph. This is useful when you want to
+   * make a derivation depend on the string's references, but not its
+   * contents (to avoid unnecessary rebuilds, for example).
+   *
+   * Note that this only works as intended on Nix >= 2.3.
+   */
+  writeStringReferencesToFile = string:
+    /*
+    * The basic operation this performs is to copy the string context
+    * from `string' to a second string and wrap that string in a
+    * derivation. However, that alone is not enough, since nothing in the
+    * string refers to the output paths of the derivations/paths in its
+    * context, meaning they'll be considered build-time dependencies and
+    * removed from the wrapper derivation's closure. Putting the
+    * necessary output paths in the new string is however not very
+    * straightforward - the attrset returned by `getContext' contains
+    * only references to derivations' .drv-paths, not their output
+    * paths. In order to "convert" them, we try to extract the
+    * corresponding paths from the original string using regex.
+    */
+    let
+      # Taken from https://github.com/NixOS/nix/blob/130284b8508dad3c70e8160b15f3d62042fc730a/src/libutil/hash.cc#L84
+      nixHashChars = "0123456789abcdfghijklmnpqrsvwxyz";
+      context = builtins.getContext string;
+      derivations = lib.filterAttrs (n: v: v ? outputs) context;
+      # Objects copied from outside of the store, such as paths and
+      # `builtins.fetch*`ed ones
+      sources = lib.attrNames (lib.filterAttrs (n: v: v ? path) context);
+      packages =
+        lib.mapAttrs'
+          (name: value:
+            {
+              inherit value;
+              name = lib.head (builtins.match "${builtins.storeDir}/[${nixHashChars}]+-(.*)\.drv" name);
+            })
+          derivations;
+      # The syntax of output paths differs between outputs named `out`
+      # and other, explicitly named ones. For explicitly named ones,
+      # the output name is suffixed as `-name`, but `out` outputs
+      # aren't suffixed at all, and thus aren't easily distinguished
+      # from named output paths. Therefore, we find all the named ones
+      # first so we can use them to remove false matches when looking
+      # for `out` outputs (see the definition of `outputPaths`).
+      namedOutputPaths =
+        lib.flatten
+          (lib.mapAttrsToList
+            (name: value:
+              (map
+                (output:
+                  lib.filter
+                    lib.isList
+                    (builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name}-${output})" string))
+                (lib.remove "out" value.outputs)))
+            packages);
+      # Only `out` outputs
+      outputPaths =
+        lib.flatten
+          (lib.mapAttrsToList
+            (name: value:
+              if lib.elem "out" value.outputs then
+                lib.filter
+                  (x: lib.isList x &&
+                      # If the matched path is in `namedOutputPaths`,
+                      # it's a partial match of an output path where
+                      # the output name isn't `out`
+                      lib.all (o: !lib.hasPrefix (lib.head x) o) namedOutputPaths)
+                  (builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name})" string)
+              else
+                [])
+            packages);
+      allPaths = lib.concatStringsSep "\n" (lib.unique (sources ++ namedOutputPaths ++ outputPaths));
+      allPathsWithContext = builtins.appendContext allPaths context;
+    in
+      if builtins ? getContext then
+        writeText "string-references" allPathsWithContext
+      else
+        writeDirectReferencesToFile (writeText "string-file" string);
+
+
   /* Print an error message if the file with the specified name and
    * hash doesn't exist in the Nix store. This function should only
    * be used by non-redistributable software with an unfree license
@@ -612,7 +749,7 @@ rec {
     { package,
       command ? "${package.meta.mainProgram or package.pname or package.name} --version",
       version ? package.version,
-    }: runCommand "test-version" { nativeBuildInputs = [ package ]; meta.timeout = 60; } ''
+    }: runCommand "${package.name}-test-version" { nativeBuildInputs = [ package ]; meta.timeout = 60; } ''
       ${command} |& grep -Fw ${version}
       touch $out
     '';
diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test.sh b/nixpkgs/pkgs/build-support/trivial-builders/test/references-test.sh
index b7c4726a9be0..473ca6e10769 100755
--- a/nixpkgs/pkgs/build-support/trivial-builders/test.sh
+++ b/nixpkgs/pkgs/build-support/trivial-builders/test/references-test.sh
@@ -8,11 +8,11 @@
 #
 #  This file can be run independently (quick):
 #
-#      $ pkgs/build-support/trivial-builders/test.sh
+#      $ pkgs/build-support/trivial-builders/references-test.sh
 #
 #  or in the build sandbox with a ~20s VM overhead
 #
-#      $ nix-build -A tests.trivial-builders
+#      $ nix-build -A tests.trivial-builders.references
 #
 # -------------------------------------------------------------------------- #
 
@@ -26,9 +26,15 @@ set -euo pipefail
 cd "$(dirname ${BASH_SOURCE[0]})"  # nixpkgs root
 
 if [[ -z ${SAMPLE:-} ]]; then
-  sample=( `nix-build test/sample.nix` )
-  directRefs=( `nix-build test/invoke-writeDirectReferencesToFile.nix` )
-  references=( `nix-build test/invoke-writeReferencesToFile.nix` )
+  echo "Running the script directly is currently not supported."
+  echo "If you need to iterate, remove the raw path, which is not returned by nix-build."
+  exit 1
+#   sample=( `nix-build --no-out-link sample.nix` )
+#   directRefs=( `nix-build --no-out-link invoke-writeDirectReferencesToFile.nix` )
+#   references=( `nix-build --no-out-link invoke-writeReferencesToFile.nix` )
+#   echo "sample: ${#sample[@]}"
+#   echo "direct: ${#directRefs[@]}"
+#   echo "indirect: ${#references[@]}"
 else
   # Injected by Nix (to avoid evaluating in a derivation)
   # turn them into arrays
diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/references.nix
index 204fb54fca3d..a2bee51b13e7 100644
--- a/nixpkgs/pkgs/build-support/trivial-builders/test.nix
+++ b/nixpkgs/pkgs/build-support/trivial-builders/test/references.nix
@@ -8,11 +8,11 @@
 #
 #  This file can be run independently (quick):
 #
-#      $ pkgs/build-support/trivial-builders/test.sh
+#      $ pkgs/build-support/trivial-builders/references-test.sh
 #
 #  or in the build sandbox with a ~20s VM overhead
 #
-#      $ nix-build -A tests.trivial-builders
+#      $ nix-build -A tests.trivial-builders.references
 #
 # -------------------------------------------------------------------------- #
 
@@ -33,16 +33,17 @@ nixosTest {
       builtins.toJSON [hello figlet stdenvNoCC]
     );
     environment.variables = {
-      SAMPLE = invokeSamples ./test/sample.nix;
-      REFERENCES = invokeSamples ./test/invoke-writeReferencesToFile.nix;
-      DIRECT_REFS = invokeSamples ./test/invoke-writeDirectReferencesToFile.nix;
+      SAMPLE = invokeSamples ./sample.nix;
+      REFERENCES = invokeSamples ./invoke-writeReferencesToFile.nix;
+      DIRECT_REFS = invokeSamples ./invoke-writeDirectReferencesToFile.nix;
     };
   };
-  testScript = ''
-    machine.succeed("""
-      ${./test.sh} 2>/dev/console
-    """)
-  '';
+  testScript =
+    ''
+      machine.succeed("""
+        ${./references-test.sh} 2>/dev/console
+      """)
+    '';
   meta = {
     license = lib.licenses.mit; # nixpkgs license
     maintainers = with lib.maintainers; [
diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/sample.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/sample.nix
index 27aee6b73dbe..a4eedce8417e 100644
--- a/nixpkgs/pkgs/build-support/trivial-builders/test/sample.nix
+++ b/nixpkgs/pkgs/build-support/trivial-builders/test/sample.nix
@@ -1,17 +1,27 @@
-{ pkgs ? import ../../../.. { config = {}; overlays = []; } }:
+{ pkgs ? import ../../../.. { config = { }; overlays = [ ]; } }:
 let
   inherit (pkgs)
     figlet
+    zlib
     hello
     writeText
+    runCommand
     ;
 in
 {
   hello = hello;
   figlet = figlet;
+  zlib = zlib;
+  zlib-dev = zlib.dev;
   norefs = writeText "hi" "hello";
+  norefsDup = writeText "hi" "hello";
   helloRef = writeText "hi" "hello ${hello}";
+  helloRefDup = writeText "hi" "hello ${hello}";
+  path = ./invoke-writeReferencesToFile.nix;
+  pathLike.outPath = ./invoke-writeReferencesToFile.nix;
   helloFigletRef = writeText "hi" "hello ${hello} ${figlet}";
+  selfRef = runCommand "self-ref-1" {} "echo $out >$out";
+  selfRef2 = runCommand "self-ref-2" {} ''echo "${figlet}, $out" >$out'';
   inherit (pkgs)
     emptyFile
     emptyDirectory
diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/writeStringReferencesToFile.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/writeStringReferencesToFile.nix
new file mode 100644
index 000000000000..b93b43b74aa4
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/trivial-builders/test/writeStringReferencesToFile.nix
@@ -0,0 +1,18 @@
+{ callPackage, lib, pkgs, runCommand, writeText, writeStringReferencesToFile }:
+let
+  sample = import ./sample.nix { inherit pkgs; };
+  samplePaths = lib.unique (lib.attrValues sample);
+  stri = x: "${x}";
+  sampleText = writeText "sample-text" (lib.concatStringsSep "\n" (lib.unique (map stri samplePaths)));
+  stringReferencesText =
+    writeStringReferencesToFile
+      ((lib.concatMapStringsSep "fillertext"
+        stri
+        (lib.attrValues sample)) + ''
+        STORE=${builtins.storeDir};\nsystemctl start bar-foo.service
+      '');
+in
+runCommand "test-writeStringReferencesToFile" { } ''
+  diff -U3 <(sort ${stringReferencesText}) <(sort ${sampleText})
+  touch $out
+''
diff --git a/nixpkgs/pkgs/build-support/upstream-updater/update-walker-service-specific.sh b/nixpkgs/pkgs/build-support/upstream-updater/update-walker-service-specific.sh
index fe439c5d11e3..d92d223845e6 100644
--- a/nixpkgs/pkgs/build-support/upstream-updater/update-walker-service-specific.sh
+++ b/nixpkgs/pkgs/build-support/upstream-updater/update-walker-service-specific.sh
@@ -1,5 +1,5 @@
 SF_redirect () {
-  redirect
+  redirect 99
   process 'http://[a-z]+[.]dl[.]sourceforge[.]net/' 'mirror://sourceforge/'
   process '[?].*' ''
 }
diff --git a/nixpkgs/pkgs/build-support/upstream-updater/update-walker.sh b/nixpkgs/pkgs/build-support/upstream-updater/update-walker.sh
index e60499b60f27..9172a41718c8 100755
--- a/nixpkgs/pkgs/build-support/upstream-updater/update-walker.sh
+++ b/nixpkgs/pkgs/build-support/upstream-updater/update-walker.sh
@@ -69,8 +69,8 @@ version_link () {
 
 redirect () {
   CURRENT_URL="$(curl -I -L --max-redirs "${1:-99}" "$CURRENT_URL" | 
-    grep -E '^Location: ' | position_choice "${2:-999999}" "$3" |
-    sed -e 's/^Location: //; s/\r//')"
+    grep -E '^[Ll]ocation: ' | position_choice "${2:-999999}" "$3" |
+    sed -e 's/^[Ll]ocation: //; s/\r//')"
   echo "Redirected: $*"
   echo "URL: $CURRENT_URL" >&2
 }
diff --git a/nixpkgs/pkgs/build-support/vm/default.nix b/nixpkgs/pkgs/build-support/vm/default.nix
index d2aeb784e7fd..e466ff7ecce8 100644
--- a/nixpkgs/pkgs/build-support/vm/default.nix
+++ b/nixpkgs/pkgs/build-support/vm/default.nix
@@ -5,7 +5,7 @@
 , storeDir ? builtins.storeDir
 , rootModules ?
     [ "virtio_pci" "virtio_mmio" "virtio_blk" "virtio_balloon" "virtio_rng" "ext4" "unix" "9p" "9pnet_virtio" "crc32c_generic" ]
-      ++ pkgs.lib.optional (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) "rtc_cmos"
+      ++ pkgs.lib.optional pkgs.stdenv.hostPlatform.isx86 "rtc_cmos"
 }:
 
 let
@@ -90,6 +90,10 @@ rec {
     done
 
     mount -t devtmpfs devtmpfs /dev
+    ln -s /proc/self/fd /dev/fd
+    ln -s /proc/self/fd/0 /dev/stdin
+    ln -s /proc/self/fd/1 /dev/stdout
+    ln -s /proc/self/fd/2 /dev/stderr
 
     ifconfig lo up
 
@@ -110,7 +114,7 @@ rec {
 
     echo "mounting Nix store..."
     mkdir -p /fs${storeDir}
-    mount -t 9p store /fs${storeDir} -o trans=virtio,version=9p2000.L,cache=loose
+    mount -t 9p store /fs${storeDir} -o trans=virtio,version=9p2000.L,cache=loose,msize=131072
 
     mkdir -p /fs/tmp /fs/run /fs/var
     mount -t tmpfs -o "mode=1777" none /fs/tmp
@@ -119,7 +123,7 @@ rec {
 
     echo "mounting host's temporary directory..."
     mkdir -p /fs/tmp/xchg
-    mount -t 9p xchg /fs/tmp/xchg -o trans=virtio,version=9p2000.L
+    mount -t 9p xchg /fs/tmp/xchg -o trans=virtio,version=9p2000.L,msize=131072
 
     mkdir -p /fs/proc
     mount -t proc none /fs/proc
@@ -390,7 +394,7 @@ rec {
       diskImage=$(pwd)/disk-image.qcow2
       origImage=${attrs.diskImage}
       if test -d "$origImage"; then origImage="$origImage/disk-image.qcow2"; fi
-      ${qemu}/bin/qemu-img create -b "$origImage" -f qcow2 $diskImage
+      ${qemu}/bin/qemu-img create -F ${attrs.diskImageFormat} -b "$origImage" -f qcow2 $diskImage
     '';
 
     /* Inside the VM, run the stdenv setup script normally, but at the
@@ -506,8 +510,7 @@ rec {
      tarball must contain an RPM specfile. */
 
   buildRPM = attrs: runInLinuxImage (stdenv.mkDerivation ({
-    prePhases = [ pkgs.prepareImagePhase pkgs.sysInfoPhase ];
-    dontUnpack = true;
+    prePhases = [ "prepareImagePhase" "sysInfoPhase" ];
     dontConfigure = true;
 
     outDir = "rpms/${attrs.diskImage.name}";
@@ -532,9 +535,7 @@ rec {
     buildPhase = ''
       eval "$preBuild"
 
-      # Hacky: RPM looks for <basename>.spec inside the tarball, so
-      # strip off the hash.
-      srcName="$(stripHash "$src")"
+      srcName="$(rpmspec --srpm -q --qf '%{source}' *.spec)"
       cp "$src" "$srcName" # `ln' doesn't work always work: RPM requires that the file is owned by root
 
       export HOME=/tmp/home
diff --git a/nixpkgs/pkgs/build-support/vm/test.nix b/nixpkgs/pkgs/build-support/vm/test.nix
index 1a29554ee80c..ae6a10dea3b9 100644
--- a/nixpkgs/pkgs/build-support/vm/test.nix
+++ b/nixpkgs/pkgs/build-support/vm/test.nix
@@ -9,29 +9,32 @@ with vmTools;
 
   buildHelloInVM = runInLinuxVM hello;
 
-  buildPanInVM = runInLinuxVM pan;
+  buildPcmanrmInVM = runInLinuxVM (pcmanfm.overrideAttrs (old: {
+    # goes out-of-memory with many cores
+    enableParallelBuilding = false;
+  }));
 
-
-  testRPMImage = makeImageTestScript diskImages.fedora16x86_64;
+  testRPMImage = makeImageTestScript diskImages.fedora27x86_64;
 
 
   buildPatchelfRPM = buildRPM {
     name = "patchelf-rpm";
     src = patchelf.src;
-    diskImage = diskImages.fedora16x86_64;
+    diskImage = diskImages.fedora27x86_64;
+    diskImageFormat = "qcow2";
   };
 
 
-  testUbuntuImage = makeImageTestScript diskImages.ubuntu810i386;
+  testUbuntuImage = makeImageTestScript diskImages.ubuntu1804i386;
 
 
   buildInDebian = runInLinuxImage (stdenv.mkDerivation {
     name = "deb-compile";
     src = patchelf.src;
-    diskImage = diskImages.ubuntu1204i386;
+    diskImage = diskImages.ubuntu1804i386;
+    diskImageFormat = "qcow2";
     memSize = 512;
-    prePhases = [ sysInfoPhase ];
-    sysInfoPhase = ''
+    postHook = ''
       dpkg-query --list
     '';
   });
diff --git a/nixpkgs/pkgs/build-support/wrapper-common/utils.bash b/nixpkgs/pkgs/build-support/wrapper-common/utils.bash
index cb3552ebc54b..0afccadf3384 100644
--- a/nixpkgs/pkgs/build-support/wrapper-common/utils.bash
+++ b/nixpkgs/pkgs/build-support/wrapper-common/utils.bash
@@ -21,13 +21,13 @@ mangleVarListGeneric() {
     local -a role_suffixes=("$@")
 
     local outputVar="${var}_@suffixSalt@"
-    declare -gx ${outputVar}+=''
+    declare -gx "$outputVar"+=''
     # For each role we serve, we accumulate the input parameters into our own
     # cc-wrapper-derivation-specific environment variables.
     for suffix in "${role_suffixes[@]}"; do
         local inputVar="${var}${suffix}"
         if [ -v "$inputVar" ]; then
-            export ${outputVar}+="${!outputVar:+$sep}${!inputVar}"
+            export "${outputVar}+=${!outputVar:+$sep}${!inputVar}"
         fi
     done
 }
@@ -42,7 +42,7 @@ mangleVarBool() {
     local -a role_suffixes=("$@")
 
     local outputVar="${var}_@suffixSalt@"
-    declare -gxi ${outputVar}+=0
+    declare -gxi "${outputVar}+=0"
     for suffix in "${role_suffixes[@]}"; do
         local inputVar="${var}${suffix}"
         if [ -v "$inputVar" ]; then
@@ -131,7 +131,7 @@ expandResponseParams() {
 }
 
 checkLinkType() {
-    local arg mode
+    local arg
     type="dynamic"
     for arg in "$@"; do
         if [[ "$arg" = -static ]]; then
@@ -146,7 +146,7 @@ checkLinkType() {
 # When building static-pie executables we cannot have rpath
 # set. At least glibc requires rpath to be empty
 filterRpathFlags() {
-    local linkType=$1 ret="" i
+    local linkType=$1 ret i
     shift
 
     if [[ "$linkType" == "static-pie" ]]; then
@@ -156,11 +156,11 @@ filterRpathFlags() {
                 # also skip its argument
                 shift
             else
-                ret+="$i "
+                ret+=("$i")
             fi
         done
     else
-        ret=$@
+        ret=("$@")
     fi
-    echo $ret
+    echo "${ret[@]}"
 }
diff --git a/nixpkgs/pkgs/build-support/writers/aliases.nix b/nixpkgs/pkgs/build-support/writers/aliases.nix
new file mode 100644
index 000000000000..fb108a6fd857
--- /dev/null
+++ b/nixpkgs/pkgs/build-support/writers/aliases.nix
@@ -0,0 +1,35 @@
+lib: prev:
+
+let
+  # Removing recurseForDerivation prevents derivations of aliased attribute
+  # set to appear while listing all the packages available.
+  removeRecurseForDerivations = alias: with lib;
+    if alias.recurseForDerivations or false then
+      removeAttrs alias ["recurseForDerivations"]
+    else alias;
+
+  # Disabling distribution prevents top-level aliases for non-recursed package
+  # sets from building on Hydra.
+  removeDistribute = alias: with lib;
+    if isDerivation alias then
+      dontDistribute alias
+    else alias;
+
+  # Make sure that we are not shadowing something from
+  # writers.
+  checkInPkgs = n: alias: if builtins.hasAttr n prev
+                          then throw "Alias ${n} is still in writers"
+                          else alias;
+
+  mapAliases = aliases:
+    lib.mapAttrs (n: alias: removeDistribute
+                             (removeRecurseForDerivations
+                              (checkInPkgs n alias)))
+                     aliases;
+
+in
+mapAliases ({
+  /* Cleanup before 22.05, Added 2021-12-11 */
+  writePython2 = "Python 2 is EOL and the use of writers.writePython2 is deprecated.";
+  writePython2Bin = "Python 2 is EOL and the use of writers.writePython2Bin is deprecated.";
+})
diff --git a/nixpkgs/pkgs/build-support/writers/default.nix b/nixpkgs/pkgs/build-support/writers/default.nix
index 111ec68a6021..30301e3b2e54 100644
--- a/nixpkgs/pkgs/build-support/writers/default.nix
+++ b/nixpkgs/pkgs/build-support/writers/default.nix
@@ -1,7 +1,9 @@
-{ pkgs, lib, gawk, gnused, gixy }:
+{ pkgs, config, buildPackages, lib, stdenv, libiconv, gawk, gnused, gixy }:
 
-with lib;
-rec {
+let
+  aliases = if (config.allowAliases or true) then (import ./aliases.nix lib) else prev: {};
+
+  writers = with lib; rec {
   # Base implementation for non-compiled executables.
   # Takes an interpreter, for example `${pkgs.bash}/bin/bash`
   #
@@ -77,7 +79,11 @@ rec {
     }) ''
       ${compileScript}
       ${lib.optionalString strip
-         "${pkgs.binutils-unwrapped}/bin/strip --strip-unneeded $out"}
+          "${lib.getBin buildPackages.bintools-unwrapped}/bin/${buildPackages.bintools-unwrapped.targetPrefix}strip -S $out"}
+      # Sometimes binaries produced for darwin (e. g. by GHC) won't be valid
+      # mach-o executables from the get-go, but need to be corrected somehow
+      # which is done by fixupPhase.
+      ${lib.optionalString pkgs.stdenvNoCC.hostPlatform.isDarwin "fixupPhase"}
       ${optionalString (types.path.check nameOrPath) ''
         mv $out tmp
         mkdir -p $out/$(dirname "${nameOrPath}")
@@ -146,10 +152,13 @@ rec {
       rustcArgs ? [],
       strip ? true
   }:
+  let
+    darwinArgs = lib.optionals stdenv.isDarwin [ "-L${lib.getLib libiconv}/lib" ];
+  in
     makeBinWriter {
       compileScript = ''
         cp "$contentPath" tmp.rs
-        PATH=${makeBinPath [pkgs.gcc]} ${lib.getBin rustc}/bin/rustc ${lib.escapeShellArgs rustcArgs} -o "$out" tmp.rs
+        PATH=${makeBinPath [pkgs.gcc]} ${lib.getBin rustc}/bin/rustc ${lib.escapeShellArgs rustcArgs} ${lib.escapeShellArgs darwinArgs} -o "$out" tmp.rs
       '';
       inherit strip;
     } name;
@@ -233,16 +242,16 @@ rec {
       then "${python}/bin/python"
       else "${python.withPackages (ps: libraries)}/bin/python"
     ;
-    check = writeDash "python2check.sh" ''
+    check = optionalString python.isPy3k (writeDash "pythoncheck.sh" ''
       exec ${pythonPackages.flake8}/bin/flake8 --show-source ${ignoreAttribute} "$1"
-    '';
+    '');
   } name;
 
-  # writePython2 takes a name an attributeset with libraries and some python2 sourcecode and
+  # writePyPy2 takes a name an attributeset with libraries and some pypy2 sourcecode and
   # returns an executable
   #
   # Example:
-  # writePython2 "test_python2" { libraries = [ pkgs.python2Packages.enum ]; } ''
+  # writePyPy2 "test_pypy2" { libraries = [ pkgs.pypy2Packages.enum ]; } ''
   #   from enum import Enum
   #
   #   class Test(Enum):
@@ -250,11 +259,11 @@ rec {
   #
   #   print Test.a
   # ''
-  writePython2 = makePythonWriter pkgs.python2 pkgs.python2Packages;
+  writePyPy2 = makePythonWriter pkgs.pypy2 pkgs.pypy2Packages;
 
-  # writePython2Bin takes the same arguments as writePython2 but outputs a directory (like writeScriptBin)
-  writePython2Bin = name:
-    writePython2 "/bin/${name}";
+  # writePyPy2Bin takes the same arguments as writePyPy2 but outputs a directory (like writeScriptBin)
+  writePyPy2Bin = name:
+    writePyPy2 "/bin/${name}";
 
   # writePython3 takes a name an attributeset with libraries and some python3 sourcecode and
   # returns an executable
@@ -273,4 +282,25 @@ rec {
   # writePython3Bin takes the same arguments as writePython3 but outputs a directory (like writeScriptBin)
   writePython3Bin = name:
     writePython3 "/bin/${name}";
-}
+
+  # writePyPy3 takes a name an attributeset with libraries and some pypy3 sourcecode and
+  # returns an executable
+  #
+  # Example:
+  # writePyPy3 "test_pypy3" { libraries = [ pkgs.pypy3Packages.pyyaml ]; } ''
+  #   import yaml
+  #
+  #   y = yaml.load("""
+  #     - test: success
+  #   """)
+  #   print(y[0]['test'])
+  # ''
+  writePyPy3 = makePythonWriter pkgs.pypy3 pkgs.pypy3Packages;
+
+  # writePyPy3Bin takes the same arguments as writePyPy3 but outputs a directory (like writeScriptBin)
+  writePyPy3Bin = name:
+    writePyPy3 "/bin/${name}";
+
+};
+in
+writers // (aliases writers)
diff --git a/nixpkgs/pkgs/build-support/writers/test.nix b/nixpkgs/pkgs/build-support/writers/test.nix
index 69bc7dd2c61a..decd7e42d5cc 100644
--- a/nixpkgs/pkgs/build-support/writers/test.nix
+++ b/nixpkgs/pkgs/build-support/writers/test.nix
@@ -3,8 +3,9 @@
 , lib
 , nodePackages
 , perlPackages
-, python2Packages
+, pypy2Packages
 , python3Packages
+, pypy3Packages
 , runCommand
 , writers
 , writeText
@@ -54,7 +55,7 @@ let
       print "success\n" if true;
     '';
 
-    python2 = writePython2Bin "test-writers-python2-bin" { libraries = [ python2Packages.enum ]; } ''
+    pypy2 = writePyPy2Bin "test-writers-pypy2-bin" { libraries = [ pypy2Packages.enum ]; } ''
       from enum import Enum
 
 
@@ -73,6 +74,15 @@ let
       """)
       print(y[0]['test'])
     '';
+
+    pypy3 = writePyPy3Bin "test-writers-pypy3-bin" { libraries = [ pypy3Packages.pyyaml ]; } ''
+      import yaml
+
+      y = yaml.load("""
+        - test: success
+      """)
+      print(y[0]['test'])
+    '';
   };
 
   simple = {
@@ -111,7 +121,7 @@ let
       print "success\n" if true;
     '';
 
-    python2 = writePython2 "test-writers-python2" { libraries = [ python2Packages.enum ]; } ''
+    pypy2 = writePyPy2 "test-writers-pypy2" { libraries = [ pypy2Packages.enum ]; } ''
       from enum import Enum
 
 
@@ -131,13 +141,26 @@ let
       print(y[0]['test'])
     '';
 
-    python2NoLibs = writePython2 "test-writers-python2-no-libs" {} ''
+    pypy3 = writePyPy3 "test-writers-pypy3" { libraries = [ pypy3Packages.pyyaml ]; } ''
+      import yaml
+
+      y = yaml.load("""
+        - test: success
+      """)
+      print(y[0]['test'])
+    '';
+
+    pypy2NoLibs = writePyPy2 "test-writers-pypy2-no-libs" {} ''
       print("success")
     '';
 
     python3NoLibs = writePython3 "test-writers-python3-no-libs" {} ''
       print("success")
     '';
+
+    pypy3NoLibs = writePyPy3 "test-writers-pypy3-no-libs" {} ''
+      print("success")
+    '';
   };