about summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/build-support')
-rw-r--r--pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix2
-rw-r--r--pkgs/build-support/build-graalvm-native-image/default.nix2
-rw-r--r--pkgs/build-support/docker/default.nix18
-rw-r--r--pkgs/build-support/docker/examples.nix2
-rw-r--r--pkgs/build-support/emacs/wrapper.nix18
-rw-r--r--pkgs/build-support/emacs/wrapper.sh2
-rw-r--r--pkgs/build-support/fetchgit/default.nix3
-rw-r--r--pkgs/build-support/fetchurl/default.nix2
-rw-r--r--pkgs/build-support/fetchurl/mirrors.nix1
-rw-r--r--pkgs/build-support/kernel/make-initrd-ng.nix16
-rw-r--r--pkgs/build-support/kernel/make-initrd.nix4
-rw-r--r--pkgs/build-support/kernel/make-initrd.sh2
-rw-r--r--pkgs/build-support/make-darwin-bundle/default.nix8
-rw-r--r--pkgs/build-support/make-desktopitem/default.nix11
-rw-r--r--pkgs/build-support/ocaml/dune.nix4
-rw-r--r--pkgs/build-support/ocaml/oasis.nix2
-rw-r--r--pkgs/build-support/rust/build-rust-crate/default.nix9
-rw-r--r--pkgs/build-support/setup-hooks/auto-patchelf.py40
-rw-r--r--pkgs/build-support/setup-hooks/auto-patchelf.sh10
-rw-r--r--pkgs/build-support/setup-hooks/copy-desktop-items.sh9
-rw-r--r--pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh32
-rw-r--r--pkgs/build-support/setup-hooks/make-wrapper.sh5
-rw-r--r--pkgs/build-support/setup-hooks/postgresql-test-hook/default.nix9
-rw-r--r--pkgs/build-support/setup-hooks/postgresql-test-hook/postgresql-test-hook.sh79
-rw-r--r--pkgs/build-support/setup-hooks/postgresql-test-hook/test.nix27
-rw-r--r--pkgs/build-support/setup-hooks/wrap-gapps-hook/wrap-gapps-hook.sh4
-rw-r--r--pkgs/build-support/testers/default.nix18
-rw-r--r--pkgs/build-support/testers/test-equal-derivation.nix (renamed from pkgs/build-support/test-equal-derivation.nix)19
-rw-r--r--pkgs/build-support/trivial-builders.nix48
-rw-r--r--pkgs/build-support/trivial-builders/test/write-text-file.nix34
30 files changed, 319 insertions, 121 deletions
diff --git a/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix b/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
index a36008d752bd9..945b9287ed00a 100644
--- a/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
+++ b/pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
@@ -178,7 +178,7 @@ let
         chmod -R 755 share
         cp -rLTf ${staticUsrProfileTarget}/share share
       else
-        cp -rLf ${staticUsrProfileTarget}/share share
+        cp -rsHf ${staticUsrProfileTarget}/share share
       fi
     fi
     for i in bin sbin include; do
diff --git a/pkgs/build-support/build-graalvm-native-image/default.nix b/pkgs/build-support/build-graalvm-native-image/default.nix
index d34f562bc5372..760896706ac28 100644
--- a/pkgs/build-support/build-graalvm-native-image/default.nix
+++ b/pkgs/build-support/build-graalvm-native-image/default.nix
@@ -55,5 +55,7 @@ stdenv.mkDerivation (args // {
     platforms = graalvmDrv.meta.platforms;
     # default to executable name
     mainProgram = executable;
+    # need to have native-image-installable-svm available
+    broken = !(builtins.elem "native-image-installable-svm" graalvmDrv.products);
   } // meta;
 })
diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix
index 96ea363c811e0..5a4e30ede8a3e 100644
--- a/pkgs/build-support/docker/default.nix
+++ b/pkgs/build-support/docker/default.nix
@@ -16,8 +16,8 @@
 , makeWrapper
 , moreutils
 , nix
+, nixosTests
 , pigz
-, pkgs
 , rsync
 , runCommand
 , runtimeShell
@@ -26,6 +26,7 @@
 , storeDir ? builtins.storeDir
 , substituteAll
 , symlinkJoin
+, tarsum
 , util-linux
 , vmTools
 , writeReferencesToFile
@@ -81,6 +82,15 @@ rec {
     inherit buildImage buildLayeredImage fakeNss pullImage shadowSetup buildImageWithNixDb;
   };
 
+  tests = {
+    inherit (nixosTests)
+      docker-tools
+      docker-tools-overlay
+      # requires remote builder
+      # docker-tools-cross
+      ;
+  };
+
   pullImage =
     let
       fixName = name: builtins.replaceStrings [ "/" ":" ] [ "-" "-" ] name;
@@ -113,7 +123,7 @@ rec {
         outputHashAlgo = "sha256";
         outputHash = sha256;
 
-        nativeBuildInputs = lib.singleton skopeo;
+        nativeBuildInputs = [ skopeo ];
         SSL_CERT_FILE = "${cacert.out}/etc/ssl/certs/ca-bundle.crt";
 
         sourceURL = "docker://${imageName}@${imageDigest}";
@@ -132,7 +142,7 @@ rec {
 
   # We need to sum layer.tar, not a directory, hence tarsum instead of nix-hash.
   # And we cannot untar it, because then we cannot preserve permissions etc.
-  tarsum = pkgs.tarsum;
+  inherit tarsum; # pkgs.dockerTools.tarsum
 
   # buildEnv creates symlinks to dirs, which is hard to edit inside the overlay VM
   mergeDrvs =
@@ -754,7 +764,7 @@ rec {
   # "#!/usr/bin/env executable" shebang.
   usrBinEnv = runCommand "usr-bin-env" { } ''
     mkdir -p $out/usr/bin
-    ln -s ${pkgs.coreutils}/bin/env $out/usr/bin
+    ln -s ${coreutils}/bin/env $out/usr/bin
   '';
 
   # This provides /bin/sh, pointing to bashInteractive.
diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix
index 941ee048666d0..169edb171db41 100644
--- a/pkgs/build-support/docker/examples.nix
+++ b/pkgs/build-support/docker/examples.nix
@@ -486,7 +486,7 @@ rec {
   cross = let
     # Cross compile for x86_64 if on aarch64
     crossPkgs =
-      if pkgs.system == "aarch64-linux" then pkgsCross.gnu64
+      if pkgs.stdenv.hostPlatform.system == "aarch64-linux" then pkgsCross.gnu64
       else pkgsCross.aarch64-multiplatform;
   in crossPkgs.dockerTools.buildImage {
     name = "hello-cross";
diff --git a/pkgs/build-support/emacs/wrapper.nix b/pkgs/build-support/emacs/wrapper.nix
index 2aa61d6d2f62f..d61f6967c4b81 100644
--- a/pkgs/build-support/emacs/wrapper.nix
+++ b/pkgs/build-support/emacs/wrapper.nix
@@ -135,10 +135,16 @@ runCommand
           ''}
         }
 
+        siteAutoloads="$out/share/emacs/site-lisp/nix-generated-autoload.el"
+        touch $siteAutoloads
+
         # Iterate over the array of inputs (avoiding nix's own interpolation)
         for pkg in "''${requires[@]}"; do
           linkEmacsPackage $pkg
+          find $pkg -name "*-autoloads.el" \
+              -exec echo \(load \"{}\" \'noerror \'nomessage\) \; >> $siteAutoloads
         done
+        echo "(provide 'nix-generated-autoload)" >> $siteAutoloads
 
         siteStart="$out/share/emacs/site-lisp/site-start.el"
         siteStartByteCompiled="$siteStart"c
@@ -174,12 +180,12 @@ runCommand
           > "$subdirs"
 
         # Byte-compiling improves start-up time only slightly, but costs nothing.
-        $emacs/bin/emacs --batch -f batch-byte-compile "$siteStart" "$subdirs"
+        $emacs/bin/emacs --batch -f batch-byte-compile "$siteStart" "$subdirs" "$siteAutoloads"
 
         ${optionalString nativeComp ''
           $emacs/bin/emacs --batch \
             --eval "(add-to-list 'native-comp-eln-load-path \"$out/share/emacs/native-lisp/\")" \
-            -f batch-native-compile "$siteStart" "$subdirs"
+            -f batch-native-compile "$siteStart" "$subdirs" "$siteAutoloads"
         ''}
       '';
 
@@ -191,12 +197,18 @@ runCommand
     # Wrap emacs and friends so they find our site-start.el before the original.
     for prog in $emacs/bin/*; do # */
       local progname=$(basename "$prog")
+      local autoloadExpression=""
       rm -f "$out/bin/$progname"
+      if [[ $progname == emacs ]]; then
+        # progs other than "emacs" do not understand the `-l` switches
+        autoloadExpression="-l cl-loaddefs -l nix-generated-autoload"
+      fi
 
       substitute ${./wrapper.sh} $out/bin/$progname \
         --subst-var-by bash ${emacs.stdenv.shell} \
         --subst-var-by wrapperSiteLisp "$deps/share/emacs/site-lisp" \
         --subst-var-by wrapperSiteLispNative "$deps/share/emacs/native-lisp:" \
+        --subst-var autoloadExpression \
         --subst-var prog
       chmod +x $out/bin/$progname
     done
@@ -215,6 +227,8 @@ runCommand
       substitute ${./wrapper.sh} $out/Applications/Emacs.app/Contents/MacOS/Emacs \
         --subst-var-by bash ${emacs.stdenv.shell} \
         --subst-var-by wrapperSiteLisp "$deps/share/emacs/site-lisp" \
+        --subst-var-by wrapperSiteLispNative "$deps/share/emacs/native-lisp:" \
+        --subst-var-by autoloadExpression "-l cl-loaddefs -l nix-generated-autoload" \
         --subst-var-by prog "$emacs/Applications/Emacs.app/Contents/MacOS/Emacs"
       chmod +x $out/Applications/Emacs.app/Contents/MacOS/Emacs
     fi
diff --git a/pkgs/build-support/emacs/wrapper.sh b/pkgs/build-support/emacs/wrapper.sh
index e8eecb8c86966..16da2a9f64954 100644
--- a/pkgs/build-support/emacs/wrapper.sh
+++ b/pkgs/build-support/emacs/wrapper.sh
@@ -44,4 +44,4 @@ export emacsWithPackages_siteLisp=@wrapperSiteLisp@
 export EMACSNATIVELOADPATH="${newNativeLoadPath[*]}"
 export emacsWithPackages_siteLispNative=@wrapperSiteLispNative@
 
-exec @prog@ "$@"
+exec @prog@ @autoloadExpression@ "$@"
diff --git a/pkgs/build-support/fetchgit/default.nix b/pkgs/build-support/fetchgit/default.nix
index 1b59668ce4bc7..b0cc42f071450 100644
--- a/pkgs/build-support/fetchgit/default.nix
+++ b/pkgs/build-support/fetchgit/default.nix
@@ -27,6 +27,7 @@ in
 , # Impure env vars (https://nixos.org/nix/manual/#sec-advanced-attributes)
   # needed for netrcPhase
   netrcImpureEnvVars ? []
+, meta ? {}
 }:
 
 /* NOTE:
@@ -90,5 +91,5 @@ stdenvNoCC.mkDerivation {
     "GIT_PROXY_COMMAND" "NIX_GIT_SSL_CAINFO" "SOCKS_SERVER"
   ];
 
-  inherit preferLocalBuild;
+  inherit preferLocalBuild meta;
 }
diff --git a/pkgs/build-support/fetchurl/default.nix b/pkgs/build-support/fetchurl/default.nix
index dcab471fc8396..32cc416cc891a 100644
--- a/pkgs/build-support/fetchurl/default.nix
+++ b/pkgs/build-support/fetchurl/default.nix
@@ -160,5 +160,5 @@ stdenvNoCC.mkDerivation {
   '';
 
   inherit meta;
-  inherit passthru;
+  passthru = { inherit url; } // passthru;
 }
diff --git a/pkgs/build-support/fetchurl/mirrors.nix b/pkgs/build-support/fetchurl/mirrors.nix
index 954c88d1bafa2..2c6ba2b02448d 100644
--- a/pkgs/build-support/fetchurl/mirrors.nix
+++ b/pkgs/build-support/fetchurl/mirrors.nix
@@ -18,6 +18,7 @@
 
   # Apache
   apache = [
+    "https://dlcdn.apache.org/"
     "https://www-eu.apache.org/dist/"
     "https://ftp.wayne.edu/apache/"
     "https://www.apache.org/dist/"
diff --git a/pkgs/build-support/kernel/make-initrd-ng.nix b/pkgs/build-support/kernel/make-initrd-ng.nix
index 9fd202c44847a..1890bbcd173a3 100644
--- a/pkgs/build-support/kernel/make-initrd-ng.nix
+++ b/pkgs/build-support/kernel/make-initrd-ng.nix
@@ -66,14 +66,28 @@ in
     compressorArgs = _compressorArgsReal;
   };
 
+  inherit extension makeUInitrd uInitrdArch prepend;
+  ${if makeUInitrd then "uInitrdCompression" else null} = uInitrdCompression;
+
   passAsFile = ["contents"];
   contents = lib.concatMapStringsSep "\n" ({ object, symlink, ... }: "${object}\n${if symlink == null then "" else symlink}") contents + "\n";
 
-  nativeBuildInputs = [makeInitrdNGTool patchelf glibc cpio];
+  nativeBuildInputs = [makeInitrdNGTool patchelf glibc cpio] ++ lib.optional makeUInitrd ubootTools;
 } ''
   mkdir ./root
   make-initrd-ng "$contentsPath" ./root
   mkdir "$out"
   (cd root && find * .[^.*] -exec touch -h -d '@1' '{}' +)
+  for PREP in $prepend; do
+    cat $PREP >> $out/initrd
+  done
   (cd root && find * .[^.*] -print0 | sort -z | cpio -o -H newc -R +0:+0 --reproducible --null | eval -- $compress >> "$out/initrd")
+
+  if [ -n "$makeUInitrd" ]; then
+      mkimage -A "$uInitrdArch" -O linux -T ramdisk -C "$uInitrdCompression" -d "$out/initrd" $out/initrd.img
+      # Compatibility symlink
+      ln -sf "initrd.img" "$out/initrd"
+  else
+      ln -s "initrd" "$out/initrd$extension"
+  fi
 ''
diff --git a/pkgs/build-support/kernel/make-initrd.nix b/pkgs/build-support/kernel/make-initrd.nix
index 23ce992f0d557..9c27a142f4b65 100644
--- a/pkgs/build-support/kernel/make-initrd.nix
+++ b/pkgs/build-support/kernel/make-initrd.nix
@@ -18,7 +18,7 @@ let
   # compression type and filename extension.
   compressorName = fullCommand: builtins.elemAt (builtins.match "([^ ]*/)?([^ ]+).*" fullCommand) 1;
 in
-{ stdenvNoCC, perl, cpio, ubootTools, lib, pkgsBuildHost
+{ stdenvNoCC, perl, libarchive, ubootTools, lib, pkgsBuildHost
 # Name of the derivation (not of the resulting file!)
 , name ? "initrd"
 
@@ -82,7 +82,7 @@ in stdenvNoCC.mkDerivation rec {
 
   builder = ./make-initrd.sh;
 
-  nativeBuildInputs = [ perl cpio ]
+  nativeBuildInputs = [ perl libarchive ]
     ++ lib.optional makeUInitrd ubootTools;
 
   compress = "${_compressorExecutable} ${lib.escapeShellArgs _compressorArgsReal}";
diff --git a/pkgs/build-support/kernel/make-initrd.sh b/pkgs/build-support/kernel/make-initrd.sh
index 0a87d643546a5..8f64114d54c3f 100644
--- a/pkgs/build-support/kernel/make-initrd.sh
+++ b/pkgs/build-support/kernel/make-initrd.sh
@@ -40,7 +40,7 @@ for PREP in $prepend; do
   cat $PREP >> $out/initrd
 done
 (cd root && find * .[^.*] -exec touch -h -d '@1' '{}' +)
-(cd root && find * .[^.*] -print0 | sort -z | cpio -o -H newc -R +0:+0 --reproducible --null | eval -- $compress >> "$out/initrd")
+(cd root && find * .[^.*] -print0 | sort -z | bsdtar --uid 0 --gid 0 -cnf - -T - | bsdtar --null -cf - --format=newc @- | eval -- $compress >> "$out/initrd")
 
 if [ -n "$makeUInitrd" ]; then
     mkimage -A "$uInitrdArch" -O linux -T ramdisk -C "$uInitrdCompression" -d "$out/initrd" $out/initrd.img
diff --git a/pkgs/build-support/make-darwin-bundle/default.nix b/pkgs/build-support/make-darwin-bundle/default.nix
index b8f58882fff32..52dd54b0b2c4d 100644
--- a/pkgs/build-support/make-darwin-bundle/default.nix
+++ b/pkgs/build-support/make-darwin-bundle/default.nix
@@ -12,14 +12,14 @@
 
 writeShellScript "make-darwin-bundle-${name}" (''
   function makeDarwinBundlePhase() {
-    mkdir -p "$out/Applications/${name}.app/Contents/MacOS"
-    mkdir -p "$out/Applications/${name}.app/Contents/Resources"
+    mkdir -p "''${!outputBin}/Applications/${name}.app/Contents/MacOS"
+    mkdir -p "''${!outputBin}/Applications/${name}.app/Contents/Resources"
 
     if [ -n "${icon}" ]; then
-      ln -s "${icon}" "$out/Applications/${name}.app/Contents/Resources"
+      ln -s "${icon}" "''${!outputBin}/Applications/${name}.app/Contents/Resources"
     fi
 
-    ${writeDarwinBundle}/bin/write-darwin-bundle "$out" "${name}" "${exec}"
+    ${writeDarwinBundle}/bin/write-darwin-bundle "''${!outputBin}" "${name}" "${exec}"
   }
 
   preDistPhases+=" makeDarwinBundlePhase"
diff --git a/pkgs/build-support/make-desktopitem/default.nix b/pkgs/build-support/make-desktopitem/default.nix
index d831fe24d33b2..e09fd0e20f226 100644
--- a/pkgs/build-support/make-desktopitem/default.nix
+++ b/pkgs/build-support/make-desktopitem/default.nix
@@ -34,11 +34,6 @@
 , extraConfig ? {} # Additional values to be added literally to the final item, e.g. vendor extensions
 }:
 let
-  # FIXME: workaround until https://github.com/NixOS/nixpkgs/pull/162246 lands
-  cleanName = if lib.hasInfix " " name
-                then throw "makeDesktopItem: name must not contain spaces!"
-                else name;
-
   # There are multiple places in the FDO spec that make "boolean" values actually tristate,
   # e.g. StartupNotify, where "unset" is literally defined as "do something reasonable".
   # So, handle null values separately.
@@ -116,8 +111,8 @@ let
   content = [ mainSectionRendered ] ++ actionsRendered;
 in
 writeTextFile {
-  name = "${cleanName}.desktop";
-  destination = "/share/applications/${cleanName}.desktop";
+  name = "${name}.desktop";
+  destination = "/share/applications/${name}.desktop";
   text = builtins.concatStringsSep "\n" content;
-  checkPhase = "${buildPackages.desktop-file-utils}/bin/desktop-file-validate $target";
+  checkPhase = ''${buildPackages.desktop-file-utils}/bin/desktop-file-validate "$target"'';
 }
diff --git a/pkgs/build-support/ocaml/dune.nix b/pkgs/build-support/ocaml/dune.nix
index f82bac7d199db..2ded76d3cd4ac 100644
--- a/pkgs/build-support/ocaml/dune.nix
+++ b/pkgs/build-support/ocaml/dune.nix
@@ -7,8 +7,8 @@ let Dune =
   { "1" = dune_1; "2" = dune_2; "3" = dune_3; }."${dune-version}"
 ; in
 
-if (args ? minimumOCamlVersion && ! lib.versionAtLeast ocaml.version args.minimumOCamlVersion) ||
-   (args ? minimalOCamlVersion && ! lib.versionAtLeast ocaml.version args.minimalOCamlVersion)
+if (args ? minimumOCamlVersion && lib.versionOlder ocaml.version args.minimumOCamlVersion) ||
+   (args ? minimalOCamlVersion && lib.versionOlder ocaml.version args.minimalOCamlVersion)
 then throw "${pname}-${version} is not available for OCaml ${ocaml.version}"
 else
 
diff --git a/pkgs/build-support/ocaml/oasis.nix b/pkgs/build-support/ocaml/oasis.nix
index 8f81344daf093..91daad59050d4 100644
--- a/pkgs/build-support/ocaml/oasis.nix
+++ b/pkgs/build-support/ocaml/oasis.nix
@@ -8,7 +8,7 @@
 }@args:
 
 if args ? minimumOCamlVersion &&
-   ! lib.versionAtLeast ocaml.version args.minimumOCamlVersion
+   lib.versionOlder ocaml.version args.minimumOCamlVersion
 then throw "${pname}-${version} is not available for OCaml ${ocaml.version}"
 else
 
diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix
index afb938e511828..20b93b1921f84 100644
--- a/pkgs/build-support/rust/build-rust-crate/default.nix
+++ b/pkgs/build-support/rust/build-rust-crate/default.nix
@@ -277,9 +277,14 @@ crate_: lib.makeOverridable
 
       # Create a list of features that are enabled by the crate itself and
       # through the features argument of buildRustCrate. Exclude features
-      # with a forward slash, since they are passed through to dependencies.
+      # with a forward slash, since they are passed through to dependencies,
+      # and dep: features, since they're internal-only and do nothing except
+      # enable optional dependencies.
       crateFeatures = lib.optionals (crate ? features)
-        (builtins.filter (f: !lib.hasInfix "/" f) (crate.features ++ features));
+        (builtins.filter
+          (f: !(lib.hasInfix "/" f || lib.hasPrefix "dep:" f))
+          (crate.features ++ features)
+        );
 
       libName = if crate ? libName then crate.libName else crate.crateName;
       libPath = if crate ? libPath then crate.libPath else "";
diff --git a/pkgs/build-support/setup-hooks/auto-patchelf.py b/pkgs/build-support/setup-hooks/auto-patchelf.py
index 26fd623e3da08..861d772698d04 100644
--- a/pkgs/build-support/setup-hooks/auto-patchelf.py
+++ b/pkgs/build-support/setup-hooks/auto-patchelf.py
@@ -1,23 +1,21 @@
 #!/usr/bin/env python3
 
-from collections import defaultdict
-from contextlib import contextmanager
-from dataclasses import dataclass
-from elftools.common.exceptions import ELFError # type: ignore
-from elftools.elf.dynamic import DynamicSection # type: ignore
-from elftools.elf.elffile import ELFFile # type: ignore
-from elftools.elf.enums import ENUM_E_TYPE, ENUM_EI_OSABI # type: ignore
-from itertools import chain
-from pathlib import Path, PurePath
-
-from typing import Tuple, Optional, Iterator, List, DefaultDict, Set
-
 import argparse
 import os
 import pprint
 import subprocess
 import sys
+from collections import defaultdict
+from contextlib import contextmanager
+from dataclasses import dataclass
+from itertools import chain
+from pathlib import Path, PurePath
+from typing import DefaultDict, Iterator, List, Optional, Set, Tuple
 
+from elftools.common.exceptions import ELFError  # type: ignore
+from elftools.elf.dynamic import DynamicSection  # type: ignore
+from elftools.elf.elffile import ELFFile  # type: ignore
+from elftools.elf.enums import ENUM_E_TYPE, ENUM_EI_OSABI  # type: ignore
 
 
 @contextmanager
@@ -246,7 +244,7 @@ def auto_patchelf(
         lib_dirs: List[Path],
         runtime_deps: List[Path],
         recursive: bool =True,
-        ignore_missing: bool =False) -> None:
+        ignore_missing: List[str] = []) -> None:
 
     if not paths_to_patch:
         sys.exit("No paths to patch, stopping.")
@@ -264,12 +262,19 @@ def auto_patchelf(
     missing = [dep for dep in dependencies if not dep.found]
 
     # Print a summary of the missing dependencies at the end
+    print(f"auto-patchelf: {len(missing)} dependencies could not be satisfied")
+    failure = False
     for dep in missing:
-        print(f"auto-patchelf could not satisfy dependency {dep.name} wanted by {dep.file}")
+        if dep.name.name in ignore_missing or "*" in ignore_missing:
+            print(f"warn: auto-patchelf ignoring missing {dep.name} wanted by {dep.file}")
+        else:
+            print(f"error: auto-patchelf could not satisfy dependency {dep.name} wanted by {dep.file}")
+            failure = True
 
-    if missing and not ignore_missing:
+    if failure:
         sys.exit('auto-patchelf failed to find all the required dependencies.\n'
-                 'Add the missing dependencies to --libs or use --ignore-missing.')
+                 'Add the missing dependencies to --libs or use '
+                 '`--ignore-missing="foo.so.1 bar.so etc.so"`.')
 
 
 def main() -> None:
@@ -280,7 +285,8 @@ def main() -> None:
                     'libraries in the provided paths.')
     parser.add_argument(
         "--ignore-missing",
-        action="store_true",
+        nargs="*",
+        type=str,
         help="Do not fail when some dependencies are not found.")
     parser.add_argument(
         "--no-recurse",
diff --git a/pkgs/build-support/setup-hooks/auto-patchelf.sh b/pkgs/build-support/setup-hooks/auto-patchelf.sh
index 9822674196ae0..b56f9ce2dbf4c 100644
--- a/pkgs/build-support/setup-hooks/auto-patchelf.sh
+++ b/pkgs/build-support/setup-hooks/auto-patchelf.sh
@@ -53,10 +53,18 @@ autoPatchelf() {
         esac
     done
 
+    local ignoreMissingDepsArray=($autoPatchelfIgnoreMissingDeps)
+    if [ "$autoPatchelfIgnoreMissingDeps" == "1" ]; then
+        echo "autoPatchelf: WARNING: setting 'autoPatchelfIgnoreMissingDeps" \
+             "= true;' is deprecated and will be removed in a future release." \
+             "Use 'autoPatchelfIgnoreMissingDeps = [ \"*\" ];' instead." >&2
+        ignoreMissingDepsArray=( "*" )
+    fi
+
     local runtimeDependenciesArray=($runtimeDependencies)
     @pythonInterpreter@ @autoPatchelfScript@                            \
         ${norecurse:+--no-recurse}                                      \
-        ${autoPatchelfIgnoreMissingDeps:+--ignore-missing}              \
+        --ignore-missing "${ignoreMissingDepsArray[@]}"                 \
         --paths "$@"                                                    \
         --libs "${autoPatchelfLibs[@]}"                                 \
                "${extraAutoPatchelfLibs[@]}"                            \
diff --git a/pkgs/build-support/setup-hooks/copy-desktop-items.sh b/pkgs/build-support/setup-hooks/copy-desktop-items.sh
index b5c5ed81eb970..313ebc9803445 100644
--- a/pkgs/build-support/setup-hooks/copy-desktop-items.sh
+++ b/pkgs/build-support/setup-hooks/copy-desktop-items.sh
@@ -28,14 +28,15 @@ copyDesktopItems() {
         return
     fi
 
+    applications="${!outputBin}/share/applications"
     for desktopItem in $desktopItems; do
         if [[ -f "$desktopItem" ]]; then
-            echo "Copying '$desktopItem' into '$out/share/applications'"
-            install -D -m 444 -t "$out"/share/applications "$desktopItem"
+            echo "Copying '$desktopItem' into '${applications}'"
+            install -D -m 444 -t "${applications}" "$desktopItem"
         else
             for f in "$desktopItem"/share/applications/*.desktop; do
-                echo "Copying '$f' into '$out/share/applications'"
-                install -D -m 444 -t "$out"/share/applications "$f"
+                echo "Copying '$f' into '${applications}'"
+                install -D -m 444 -t "${applications}" "$f"
             done
         fi
     done
diff --git a/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh b/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh
index d54af90b68888..74c8f6d0b3334 100644
--- a/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh
+++ b/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh
@@ -163,7 +163,7 @@ convertIconTheme() {
     }
 
     iconsdir=$(getIcons "$sharePath" "apps/${iconName}" "$theme")
-    if [[ -n "$(ls -1 "$iconsdir/"*)" ]]; then
+    if [[ -n "$(ls -A1 "$iconsdir")" ]]; then
         icnsutil compose --toc "$out/${iconName}.icns" "$iconsdir/"*
     else
         echo "Warning: no icons were found. Creating an empty icon for ${iconName}.icns."
@@ -171,21 +171,41 @@ convertIconTheme() {
     fi
 }
 
+processExecFieldCodes() {
+  local -r file=$1
+  local -r execRaw=$(getDesktopParam "${file}" "Exec")
+  local -r execNoK="${execRaw/\%k/${file}}"
+  local -r execNoKC="${execNoK/\%c/$(getDesktopParam "${file}" "Name")}"
+  local -r icon=$(getDesktopParam "${file}" "Icon")
+  local -r execNoKCI="${execNoKC/\%i/${icon:+--icon }${icon}}"
+  local -r execNoKCIfu="${execNoKCI/\%[fu]/\$1}"
+  local -r exec="${execNoKCIfu/\%[FU]/\$@}"
+  if [[ "$exec" != "$execRaw" ]]; then
+    echo 1>&2 "desktopToDarwinBundle: Application bundles do not understand desktop entry field codes. Changed '$execRaw' to '$exec'."
+  fi
+  echo "$exec"
+}
+
 # For a given .desktop file, generate a darwin '.app' bundle for it.
 convertDesktopFile() {
     local -r file=$1
     local -r sharePath=$(dirname "$(dirname "$file")")
     local -r name=$(getDesktopParam "${file}" "^Name")
-    local -r exec=$(getDesktopParam "${file}" "Exec")
+    local -r macOSExec=$(getDesktopParam "${file}" "X-macOS-Exec")
+    if [[ "$macOSExec" ]]; then
+      local -r exec="$macOSExec"
+    else
+      local -r exec=$(processExecFieldCodes "${file}")
+    fi
     local -r iconName=$(getDesktopParam "${file}" "^Icon")
     local -r squircle=$(getDesktopParam "${file}" "X-macOS-SquircleIcon")
 
-    mkdir -p "$out/Applications/${name}.app/Contents/MacOS"
-    mkdir -p "$out/Applications/${name}.app/Contents/Resources"
+    mkdir -p "${!outputBin}/Applications/${name}.app/Contents/MacOS"
+    mkdir -p "${!outputBin}/Applications/${name}.app/Contents/Resources"
 
-    convertIconTheme "$out/Applications/${name}.app/Contents/Resources" "$sharePath" "$iconName"
+    convertIconTheme "${!outputBin}/Applications/${name}.app/Contents/Resources" "$sharePath" "$iconName"
 
-    write-darwin-bundle "$out" "$name" "$exec" "$iconName" "$squircle"
+    write-darwin-bundle "${!outputBin}" "$name" "$exec" "$iconName" "$squircle"
 }
 
 convertDesktopFiles() {
diff --git a/pkgs/build-support/setup-hooks/make-wrapper.sh b/pkgs/build-support/setup-hooks/make-wrapper.sh
index fa60658328941..7d598956168c9 100644
--- a/pkgs/build-support/setup-hooks/make-wrapper.sh
+++ b/pkgs/build-support/setup-hooks/make-wrapper.sh
@@ -18,6 +18,7 @@ assertExecutable() {
 # --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")
 # --run         COMMAND : run command before the executable
 # --add-flags   FLAGS   : add FLAGS to invocation of executable
 
@@ -126,6 +127,10 @@ makeWrapper() {
             varName="${params[$((n + 1))]}"
             n=$((n + 1))
             echo "unset $varName" >> "$wrapper"
+        elif [[ "$p" == "--chdir" ]]; then
+            dir="${params[$((n + 1))]}"
+            n=$((n + 1))
+            echo "cd ${dir@Q}" >> "$wrapper"
         elif [[ "$p" == "--run" ]]; then
             command="${params[$((n + 1))]}"
             n=$((n + 1))
diff --git a/pkgs/build-support/setup-hooks/postgresql-test-hook/default.nix b/pkgs/build-support/setup-hooks/postgresql-test-hook/default.nix
new file mode 100644
index 0000000000000..d0031c93c10cb
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/postgresql-test-hook/default.nix
@@ -0,0 +1,9 @@
+{ callPackage, makeSetupHook }:
+
+(makeSetupHook {
+  name = "postgresql-test-hook";
+} ./postgresql-test-hook.sh).overrideAttrs (o: {
+  passthru.tests = {
+    simple = callPackage ./test.nix { };
+  };
+})
diff --git a/pkgs/build-support/setup-hooks/postgresql-test-hook/postgresql-test-hook.sh b/pkgs/build-support/setup-hooks/postgresql-test-hook/postgresql-test-hook.sh
new file mode 100644
index 0000000000000..041a3f5653325
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/postgresql-test-hook/postgresql-test-hook.sh
@@ -0,0 +1,79 @@
+preCheckHooks+=('postgresqlStart')
+postCheckHooks+=('postgresqlStop')
+
+
+postgresqlStart() {
+
+  # Add default environment variable values
+  #
+  # Client variables:
+  #  - https://www.postgresql.org/docs/current/libpq-envars.html
+  #
+  # Server variables:
+  #  - only PGDATA: https://www.postgresql.org/docs/current/creating-cluster.html
+
+  if [[ "${PGDATA:-}" == "" ]]; then
+    PGDATA="$NIX_BUILD_TOP/postgresql"
+  fi
+  export PGDATA
+
+  if [[ "${PGHOST:-}" == "" ]]; then
+    mkdir -p "$NIX_BUILD_TOP/run/postgresql"
+    PGHOST="$NIX_BUILD_TOP/run/postgresql"
+  fi
+  export PGHOST
+
+  if [[ "${PGUSER:-}" == "" ]]; then
+    PGUSER="test_user"
+  fi
+  export PGUSER
+
+  if [[ "${PGDATABASE:-}" == "" ]]; then
+    PGDATABASE="test_db"
+  fi
+  export PGDATABASE
+
+  if [[ "${postgresqlTestUserOptions:-}" == "" ]]; then
+    postgresqlTestUserOptions="LOGIN"
+  fi
+
+  if [[ "${postgresqlTestSetupSQL:-}" == "" ]]; then
+    postgresqlTestSetupSQL="$(cat <<EOF
+      CREATE ROLE "$PGUSER" $postgresqlTestUserOptions;
+      CREATE DATABASE "$PGDATABASE" OWNER '$PGUSER';
+EOF
+    )"
+  fi
+
+  if [[ "${postgresqlTestSetupCommands:-}" == "" ]]; then
+    postgresqlTestSetupCommands='echo "$postgresqlTestSetupSQL" | PGUSER=postgres psql postgres'
+  fi
+
+  if ! type initdb >/dev/null; then
+    echo >&2 'initdb not found. Did you add postgresql to the checkInputs?'
+    false
+  fi
+  header 'initializing postgresql'
+  initdb -U postgres
+
+  # Move the socket
+  echo "unix_socket_directories = '$NIX_BUILD_TOP/run/postgresql'" >>"$PGDATA/postgresql.conf"
+
+  # TCP ports can be a problem in some sandboxes,
+  # so we disable tcp listening by default
+  if ! [[ "${postgresqlEnableTCP:-}" = 1 ]]; then
+    echo "listen_addresses = ''" >>"$PGDATA/postgresql.conf"
+  fi
+
+  header 'starting postgresql'
+  eval "${postgresqlStartCommands:-pg_ctl start}"
+
+  header 'setting up postgresql'
+  eval "$postgresqlTestSetupCommands"
+
+}
+
+postgresqlStop() {
+  header 'stopping postgresql'
+  pg_ctl stop
+}
diff --git a/pkgs/build-support/setup-hooks/postgresql-test-hook/test.nix b/pkgs/build-support/setup-hooks/postgresql-test-hook/test.nix
new file mode 100644
index 0000000000000..6d8ad6c8c7e33
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/postgresql-test-hook/test.nix
@@ -0,0 +1,27 @@
+{ postgresql, postgresqlTestHook, stdenv }:
+
+stdenv.mkDerivation {
+  name = "postgresql-test-hook-test";
+  buildInputs = [ postgresqlTestHook ];
+  checkInputs = [ postgresql ];
+  dontUnpack = true;
+  doCheck = true;
+  passAsFile = ["sql"];
+  sql = ''
+    CREATE TABLE hello (
+      message text
+    );
+    INSERT INTO hello VALUES ('it '||'worked');
+    SELECT * FROM hello;
+  '';
+  checkPhase = ''
+    runHook preCheck
+    psql <$sqlPath | grep 'it worked'
+    TEST_RAN=1
+    runHook postCheck
+  '';
+  installPhase = ''
+    [[ $TEST_RAN == 1 ]]
+    touch $out
+  '';
+}
diff --git a/pkgs/build-support/setup-hooks/wrap-gapps-hook/wrap-gapps-hook.sh b/pkgs/build-support/setup-hooks/wrap-gapps-hook/wrap-gapps-hook.sh
index 1a46e075dbe76..0acf4a8e6f8d4 100644
--- a/pkgs/build-support/setup-hooks/wrap-gapps-hook/wrap-gapps-hook.sh
+++ b/pkgs/build-support/setup-hooks/wrap-gapps-hook/wrap-gapps-hook.sh
@@ -14,10 +14,6 @@ gappsWrapperArgsHook() {
         gappsWrapperArgs+=(--set GDK_PIXBUF_MODULE_FILE "$GDK_PIXBUF_MODULE_FILE")
     fi
 
-    if [ -n "$XDG_ICON_DIRS" ]; then
-        gappsWrapperArgs+=(--prefix XDG_DATA_DIRS : "$XDG_ICON_DIRS")
-    fi
-
     if [ -n "$GSETTINGS_SCHEMAS_PATH" ]; then
         gappsWrapperArgs+=(--prefix XDG_DATA_DIRS : "$GSETTINGS_SCHEMAS_PATH")
     fi
diff --git a/pkgs/build-support/testers/default.nix b/pkgs/build-support/testers/default.nix
new file mode 100644
index 0000000000000..8b79843b8332f
--- /dev/null
+++ b/pkgs/build-support/testers/default.nix
@@ -0,0 +1,18 @@
+{ pkgs, lib, callPackage, runCommand }:
+# Documentation is in doc/builders/testers.chapter.md
+{
+  testEqualDerivation = callPackage ./test-equal-derivation.nix { };
+
+  testVersion =
+    { package,
+      command ? "${package.meta.mainProgram or package.pname or package.name} --version",
+      version ? package.version,
+    }: runCommand "${package.name}-test-version" { nativeBuildInputs = [ package ]; meta.timeout = 60; } ''
+      if output=$(${command} 2>&1); then
+        grep -Fw "${version}" - <<< "$output"
+        touch $out
+      else
+        echo "$output" >&2 && exit 1
+      fi
+    '';
+}
diff --git a/pkgs/build-support/test-equal-derivation.nix b/pkgs/build-support/testers/test-equal-derivation.nix
index 5d2185ce16525..610d5f5855760 100644
--- a/pkgs/build-support/test-equal-derivation.nix
+++ b/pkgs/build-support/testers/test-equal-derivation.nix
@@ -1,29 +1,12 @@
 { lib, runCommand, emptyFile, nix-diff }:
 
-/*
-  Checks that two packages produce the exact same build instructions.
-
-  This can be used to make sure that a certain difference of configuration,
-  such as the presence of an overlay does not cause a cache miss.
-
-  When the derivations are equal, the return value is an empty file.
-  Otherwise, the build log explains the difference via `nix-diff`.
-
-  Example:
-
-      testEqualDerivation
-        "The hello package must stay the same when enabling checks."
-        hello
-        (hello.overrideAttrs(o: { doCheck = true; }))
-
-*/
 assertion: a: b:
 let
   drvA = builtins.unsafeDiscardOutputDependency a.drvPath or (throw "testEqualDerivation second argument must be a package");
   drvB = builtins.unsafeDiscardOutputDependency b.drvPath or (throw "testEqualDerivation third argument must be a package");
   name =
     if a?name
-    then lib.strings.sanitizeDerivationName "testEqualDerivation-${a.name}"
+    then "testEqualDerivation-${a.name}"
     else "testEqualDerivation";
 in
 if drvA == drvB then
diff --git a/pkgs/build-support/trivial-builders.nix b/pkgs/build-support/trivial-builders.nix
index 68f0f1bc4ddcb..bd14971fe78b4 100644
--- a/pkgs/build-support/trivial-builders.nix
+++ b/pkgs/build-support/trivial-builders.nix
@@ -70,8 +70,7 @@ rec {
     # name of the resulting derivation
     }: buildCommand:
     stdenv.mkDerivation ({
-      name = lib.strings.sanitizeDerivationName name;
-      inherit buildCommand;
+      inherit buildCommand name;
       passAsFile = [ "buildCommand" ]
         ++ (derivationArgs.passAsFile or []);
     }
@@ -121,7 +120,7 @@ rec {
         allowSubstitutes = false;
       }
       ''
-        target=$out${destination}
+        target=$out${lib.escapeShellArg destination}
         mkdir -p "$(dirname "$target")"
 
         if [ -e "$textPath" ]; then
@@ -516,15 +515,19 @@ rec {
    * # setup hook that depends on the hello package and runs ./myscript.sh
    * myhellohook = makeSetupHook { deps = [ hello ]; } ./myscript.sh;
    *
-   * # wrotes a setup hook where @bash@ myscript.sh is substituted for the
+   * # writes a Linux-exclusive setup hook where @bash@ myscript.sh is substituted for the
    * # bash interpreter.
    * myhellohookSub = makeSetupHook {
    *                 deps = [ hello ];
    *                 substitutions = { bash = "${pkgs.bash}/bin/bash"; };
+   *                 meta.platforms = lib.platforms.linux;
    *               } ./myscript.sh;
    */
-  makeSetupHook = { name ? "hook", deps ? [], substitutions ? {} }: script:
-    runCommand name substitutions
+  makeSetupHook = { name ? "hook", deps ? [], substitutions ? {}, meta ? {} }: script:
+    runCommand name
+      (substitutions // {
+        inherit meta;
+      })
       (''
         mkdir -p $out/nix-support
         cp ${script} $out/nix-support/setup-hook
@@ -781,37 +784,4 @@ rec {
     outputHash = "0sjjj9z1dhilhpc8pq4154czrb79z9cm044jvn75kxcjv6v5l2m5";
     preferLocalBuild = true;
   } "mkdir $out";
-
-  /* Checks the command output contains the specified version
-   *
-   * Although simplistic, this test assures that the main program
-   * can run. While there's no substitute for a real test case,
-   * it does catch dynamic linking errors and such. It also provides
-   * some protection against accidentally building the wrong version,
-   * for example when using an 'old' hash in a fixed-output derivation.
-   *
-   * Examples:
-   *
-   * passthru.tests.version = testVersion { package = hello; };
-   *
-   * passthru.tests.version = testVersion {
-   *   package = seaweedfs;
-   *   command = "weed version";
-   * };
-   *
-   * passthru.tests.version = testVersion {
-   *   package = key;
-   *   command = "KeY --help";
-   *   # Wrong '2.5' version in the code. Drop on next version.
-   *   version = "2.5";
-   * };
-   */
-  testVersion =
-    { package,
-      command ? "${package.meta.mainProgram or package.pname or package.name} --version",
-      version ? package.version,
-    }: runCommand "${package.name}-test-version" { nativeBuildInputs = [ package ]; meta.timeout = 60; } ''
-      ${command} |& grep -Fw ${version}
-      touch $out
-    '';
 }
diff --git a/pkgs/build-support/trivial-builders/test/write-text-file.nix b/pkgs/build-support/trivial-builders/test/write-text-file.nix
new file mode 100644
index 0000000000000..ac83a75fca4ab
--- /dev/null
+++ b/pkgs/build-support/trivial-builders/test/write-text-file.nix
@@ -0,0 +1,34 @@
+{ writeTextFile }:
+let
+  veryWeirdName = ''here's a name with some "bad" characters, like spaces and quotes'';
+in writeTextFile {
+  name = "weird-names";
+  destination = "/etc/${veryWeirdName}";
+  text = ''passed!'';
+  checkPhase = ''
+    # intentionally hardcode everything here, to make sure
+    # Nix does not mess with file paths
+
+    name="here's a name with some \"bad\" characters, like spaces and quotes"
+    fullPath="$out/etc/$name"
+
+    if [ -f "$fullPath" ]; then
+      echo "[PASS] File exists!"
+    else
+      echo "[FAIL] File was not created at expected path!"
+      exit 1
+    fi
+
+    content=$(<"$fullPath")
+    expected="passed!"
+
+    if [ "$content" = "$expected" ]; then
+      echo "[PASS] Contents match!"
+    else
+      echo "[FAIL] File contents don't match!"
+      echo "       Expected: $expected"
+      echo "       Got:      $content"
+      exit 2
+    fi
+  '';
+}