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/agda/default.nix13
-rwxr-xr-xpkgs/build-support/appimage/appimage-exec.sh108
-rw-r--r--pkgs/build-support/appimage/default.nix57
-rw-r--r--pkgs/build-support/bintools-wrapper/add-flags.sh26
-rw-r--r--pkgs/build-support/bintools-wrapper/add-hardening.sh2
-rw-r--r--pkgs/build-support/bintools-wrapper/default.nix13
-rw-r--r--pkgs/build-support/bintools-wrapper/ld-wrapper.sh20
-rw-r--r--pkgs/build-support/bintools-wrapper/setup-hook.sh11
-rw-r--r--pkgs/build-support/build-fhs-userenv/env.nix2
-rw-r--r--pkgs/build-support/cc-wrapper/add-flags.sh32
-rw-r--r--pkgs/build-support/cc-wrapper/add-hardening.sh2
-rw-r--r--pkgs/build-support/cc-wrapper/cc-wrapper.sh24
-rw-r--r--pkgs/build-support/cc-wrapper/default.nix8
-rw-r--r--pkgs/build-support/cc-wrapper/gnat-wrapper.sh10
-rw-r--r--pkgs/build-support/cc-wrapper/setup-hook.sh26
-rw-r--r--pkgs/build-support/dotnetbuildhelpers/default.nix2
-rw-r--r--pkgs/build-support/emacs/wrapper.nix2
-rw-r--r--pkgs/build-support/fetchmavenartifact/default.nix2
-rw-r--r--pkgs/build-support/fetchurl/mirrors.nix1
-rw-r--r--pkgs/build-support/pkg-config-wrapper/add-flags.sh12
-rw-r--r--pkgs/build-support/pkg-config-wrapper/default.nix126
-rw-r--r--pkgs/build-support/pkg-config-wrapper/pkg-config-wrapper.sh21
-rw-r--r--pkgs/build-support/pkg-config-wrapper/setup-hook.sh29
-rw-r--r--pkgs/build-support/rust/build-rust-crate/build-crate.nix4
-rw-r--r--pkgs/build-support/rust/build-rust-crate/configure-crate.nix22
-rw-r--r--pkgs/build-support/rust/build-rust-crate/default.nix17
-rw-r--r--pkgs/build-support/rust/build-rust-crate/test/default.nix26
-rw-r--r--pkgs/build-support/rust/default.nix54
-rw-r--r--pkgs/build-support/setup-hooks/role.bash14
-rw-r--r--pkgs/build-support/setup-hooks/validate-pkg-config.sh19
-rw-r--r--pkgs/build-support/vm/default.nix2
-rw-r--r--pkgs/build-support/vm/windows/controller/default.nix2
-rw-r--r--pkgs/build-support/wrapper-common/utils.bash32
33 files changed, 519 insertions, 222 deletions
diff --git a/pkgs/build-support/agda/default.nix b/pkgs/build-support/agda/default.nix
index 205aff555730..3c973e8cc0ac 100644
--- a/pkgs/build-support/agda/default.nix
+++ b/pkgs/build-support/agda/default.nix
@@ -30,6 +30,16 @@ let
 
   withPackages = arg: if builtins.isAttrs arg then withPackages' arg else withPackages' { pkgs = arg; };
 
+  extensions = [
+    "agda"
+    "agda-lib"
+    "agdai"
+    "lagda"
+    "lagda.md"
+    "lagda.org"
+    "lagda.rst"
+    "lagda.tex"
+  ];
 
   defaults =
     { pname
@@ -39,6 +49,7 @@ let
     , libraryFile ? "${libraryName}.agda-lib"
     , buildPhase ? null
     , installPhase ? null
+    , extraExtensions ? []
     , ...
     }: let
       agdaWithArgs = withPackages (builtins.filter (p: p ? isAgdaDerivation) buildInputs);
@@ -59,7 +70,7 @@ let
         installPhase = if installPhase != null then installPhase else ''
           runHook preInstall
           mkdir -p $out
-          find \( -name '*.agda' -or -name '*.agdai' -or -name '*.agda-lib' \) -exec cp -p --parents -t "$out" {} +
+          find \( ${concatMapStringsSep " -or " (p: "-name '*.${p}'") (extensions ++ extraExtensions)} \) -exec cp -p --parents -t "$out" {} +
           runHook postInstall
         '';
       };
diff --git a/pkgs/build-support/appimage/appimage-exec.sh b/pkgs/build-support/appimage/appimage-exec.sh
index 15eafc58a1ee..82ebdd0bbe4a 100755
--- a/pkgs/build-support/appimage/appimage-exec.sh
+++ b/pkgs/build-support/appimage/appimage-exec.sh
@@ -6,58 +6,55 @@ fi
 PATH="@path@:$PATH"
 apprun_opt=true
 
-#DEBUG=0
-
 # src : AppImage
 # dest : let's unpack() create the directory
 unpack() {
-  local src=$1
-  local out=$2
-  local appimageSignature=""
-  local appimageType=0
+  local src="$1"
+  local out="$2"
 
   # https://github.com/AppImage/libappimage/blob/ca8d4b53bed5cbc0f3d0398e30806e0d3adeaaab/src/libappimage/utils/MagicBytesChecker.cpp#L45-L63
-  eval "$(r2 -nn -Nqc "p8j 3 @ 8" "$src"|
-    jq -r '{appimageSignature: (.[:-1]|implode), appimageType: .[-1]}|
-      @sh "appimageSignature=\(.appimageSignature) appimageType=\(.appimageType)"')"
+  local appimageSignature=$(readelf -h "$src" | awk 'NR==2{print $10$11;}')
+  local appimageType=$(readelf -h "$src" | awk 'NR==2{print $12;}')
 
   # check AppImage signature
-  if [[ "$appimageSignature" != "AI" ]]; then
-    echo "Not an appimage."
+  if [ "$appimageSignature" != "4149" ]; then
+    echo "Not an AppImage file"
     exit
   fi
 
   case "$appimageType" in
-    1 ) echo "Uncompress $(basename "$src") of type $appimageType."
-        mkdir "$out"
-        pv "$src" | bsdtar -x -C "$out" -f -
-        ;;
-    2)
-        # This method avoid issues with non executable appimages,
-        # non-native packer, packer patching and squashfs-root destination prefix.
-
-        # multiarch offset one-liner using same method as AppImage
-        # see https://gist.github.com/probonopd/a490ba3401b5ef7b881d5e603fa20c93
-        offset=$(r2 -nn -Nqc "pfj.elf_header @ 0" "$src"|\
-          jq 'map({(.name): .value}) | add | .shoff + (.shnum * .shentsize)')
-
-        echo "Uncompress $(basename "$src") of type $appimageType @ offset $offset."
-        unsquashfs -q -d "$out" -o "$offset" "$src"
-        chmod go-w "$out"
-        ;;
-
-    # 3) get ready, https://github.com/TheAssassin/type3-runtime
-    *)  echo Unsupported AppImage Type: "$appimageType"
-        exit
-        ;;
+    "01")
+      echo "Uncompress $(basename "$src") of type $appimageType"
+      mkdir "$out"
+      pv "$src" | bsdtar -x -C "$out" -f -
+      ;;
+
+    "02")
+      # This method avoid issues with non executable appimages,
+      # non-native packer, packer patching and squashfs-root destination prefix.
+
+      # multiarch offset one-liner using same method as AppImage
+      # see https://gist.github.com/probonopd/a490ba3401b5ef7b881d5e603fa20c93
+      offset=$(readelf -h "$src" | awk 'NR==13{e_shoff=$5} NR==18{e_shentsize=$5} NR==19{e_shnum=$5} END{print e_shoff+e_shentsize*e_shnum}')
+      echo "Uncompress $(basename "$src") of type $appimageType @ offset $offset"
+      unsquashfs -q -d "$out" -o "$offset" "$src"
+      chmod go-w "$out"
+      ;;
+
+    # "03")
+    #   get ready, https://github.com/TheAssassin/type3-runtime
+
+    *)
+      echo Unsupported AppImage Type: "$appimageType"
+      exit
+      ;;
   esac
   echo "$(basename "$src") is now installed in $out"
 }
 
 apprun() {
 
-  eval "$(rahash2 "$APPIMAGE" -j | jq -r '.[] | @sh "SHA256=\(.hash)"')"
-  echo sha256 = \""$SHA256"\"\;
+  SHA256=$(sha256sum "$APPIMAGE" | awk '{print $1}')
   export APPDIR="${XDG_CACHE_HOME:-$HOME/.cache}/appimage-run/$SHA256"
 
   #compatibility
@@ -102,27 +99,26 @@ EOF
 }
 
 while getopts "x:w:dh" option; do
-    case "${option}" in
-        d)  set -x
-            ;;
-        x)  # eXtract
-            unpack_opt=true
-            APPDIR=${OPTARG}
-            ;;
-        w)  # WrapAppImage
-            export APPDIR=${OPTARG}
-            wrap_opt=true
-            ;;
-        h)  usage
-            ;;
-        *)
-            usage
-            ;;
-    esac
+  case "${option}" in
+    d)  set -x
+        ;;
+    x)  # eXtract
+        unpack_opt=true
+        APPDIR=${OPTARG}
+        ;;
+    w)  # WrapAppImage
+        export APPDIR=${OPTARG}
+        wrap_opt=true
+        ;;
+    h)  usage
+        ;;
+    *)  usage
+        ;;
+  esac
 done
-shift $((OPTIND-1))
+shift "$((OPTIND-1))"
 
-if [[ $wrap_opt = true ]] && [[ -d "$APPDIR" ]]; then
+if [ -n "$wrap_opt" ] && [ -d "$APPDIR" ]; then
   wrap "$@"
   exit
 else
@@ -130,12 +126,12 @@ else
   shift
 fi
 
-if [[ $unpack_opt = true ]] && [[ -f "$APPIMAGE" ]]; then
+if [ -n "$unpack_opt" ] && [ -f "$APPIMAGE" ]; then
   unpack "$APPIMAGE" "$APPDIR"
   exit
 fi
 
-if [[ $apprun_opt = true ]] && [[ -f "$APPIMAGE" ]]; then
+if [ -n "$apprun_opt" ] && [ -f "$APPIMAGE" ]; then
   apprun
   wrap "$@"
   exit
diff --git a/pkgs/build-support/appimage/default.nix b/pkgs/build-support/appimage/default.nix
index 993032c5601f..58c5988ea4f9 100644
--- a/pkgs/build-support/appimage/default.nix
+++ b/pkgs/build-support/appimage/default.nix
@@ -1,40 +1,57 @@
-{ stdenv, buildFHSUserEnv, writeScript, pkgs
-, bash, radare2, jq, squashfsTools, ripgrep
-, coreutils, libarchive, file, runtimeShell, pv
-, lib, runCommand }:
+{ stdenv
+, bash
+, binutils-unwrapped
+, coreutils
+, gawk
+, libarchive
+, pv
+, squashfsTools
+, buildFHSUserEnv
+, pkgs
+}:
 
 rec {
   appimage-exec = pkgs.substituteAll {
     src = ./appimage-exec.sh;
     isExecutable = true;
     dir = "bin";
-    path = with pkgs; lib.makeBinPath [ pv ripgrep file radare2 libarchive jq squashfsTools coreutils bash ];
+    path = with pkgs; stdenv.lib.makeBinPath [
+      bash
+      binutils-unwrapped
+      coreutils
+      gawk
+      libarchive
+      pv
+      squashfsTools
+    ];
   };
 
-  extract = { name, src }: runCommand "${name}-extracted" {
-    buildInputs = [ appimage-exec ];
-  } ''
-    appimage-exec.sh -x $out ${src}
-  '';
+  extract = { name, src }: pkgs.runCommand "${name}-extracted" {
+      buildInputs = [ appimage-exec ];
+    } ''
+      appimage-exec.sh -x $out ${src}
+    '';
 
   # for compatibility, deprecated
   extractType1 = extract;
   extractType2 = extract;
   wrapType1 = wrapType2;
 
-  wrapAppImage = args@{ name, src, extraPkgs, ... }: buildFHSUserEnv (defaultFhsEnvArgs // {
-    inherit name;
+  wrapAppImage = args@{ name, src, extraPkgs, ... }: buildFHSUserEnv
+    (defaultFhsEnvArgs // {
+      inherit name;
 
-    targetPkgs = pkgs: [ appimage-exec ]
-      ++ defaultFhsEnvArgs.targetPkgs pkgs ++ extraPkgs pkgs;
+      targetPkgs = pkgs: [ appimage-exec ]
+        ++ defaultFhsEnvArgs.targetPkgs pkgs ++ extraPkgs pkgs;
 
-    runScript = "appimage-exec.sh -w ${src}";
-  } // (removeAttrs args (builtins.attrNames (builtins.functionArgs wrapAppImage))));
+      runScript = "appimage-exec.sh -w ${src}";
+    } // (removeAttrs args (builtins.attrNames (builtins.functionArgs wrapAppImage))));
 
-  wrapType2 = args@{ name, src, extraPkgs ? pkgs: [], ... }: wrapAppImage (args // {
-    inherit name extraPkgs;
-    src = extract { inherit name src; };
-  });
+  wrapType2 = args@{ name, src, extraPkgs ? pkgs: [ ], ... }: wrapAppImage
+    (args // {
+      inherit name extraPkgs;
+      src = extract { inherit name src; };
+    });
 
   defaultFhsEnvArgs = {
     name = "appimage-env";
diff --git a/pkgs/build-support/bintools-wrapper/add-flags.sh b/pkgs/build-support/bintools-wrapper/add-flags.sh
index e5c0556556c7..e99beb381586 100644
--- a/pkgs/build-support/bintools-wrapper/add-flags.sh
+++ b/pkgs/build-support/bintools-wrapper/add-flags.sh
@@ -1,32 +1,32 @@
 # See cc-wrapper for comments.
 var_templates_list=(
-    NIX+IGNORE_LD_THROUGH_GCC
-    NIX+LDFLAGS
-    NIX+LDFLAGS_BEFORE
-    NIX+LDFLAGS_AFTER
-    NIX+LDFLAGS_HARDEN
-    NIX+HARDENING_ENABLE
+    NIX_IGNORE_LD_THROUGH_GCC
+    NIX_LDFLAGS
+    NIX_LDFLAGS_BEFORE
+    NIX_LDFLAGS_AFTER
+    NIX_LDFLAGS_HARDEN
+    NIX_HARDENING_ENABLE
 )
 var_templates_bool=(
-    NIX+SET_BUILD_ID
-    NIX+DONT_SET_RPATH
+    NIX_SET_BUILD_ID
+    NIX_DONT_SET_RPATH
 )
 
 accumulateRoles
 
 for var in "${var_templates_list[@]}"; do
-    mangleVarList "$var" ${role_infixes[@]+"${role_infixes[@]}"}
+    mangleVarList "$var" ${role_suffixes[@]+"${role_suffixes[@]}"}
 done
 for var in "${var_templates_bool[@]}"; do
-    mangleVarBool "$var" ${role_infixes[@]+"${role_infixes[@]}"}
+    mangleVarBool "$var" ${role_suffixes[@]+"${role_suffixes[@]}"}
 done
 
 if [ -e @out@/nix-support/libc-ldflags ]; then
-    NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/libc-ldflags)"
+    NIX_LDFLAGS_@suffixSalt@+=" $(< @out@/nix-support/libc-ldflags)"
 fi
 
 if [ -e @out@/nix-support/libc-ldflags-before ]; then
-    NIX_@infixSalt@_LDFLAGS_BEFORE="$(< @out@/nix-support/libc-ldflags-before) $NIX_@infixSalt@_LDFLAGS_BEFORE"
+    NIX_LDFLAGS_BEFORE_@suffixSalt@="$(< @out@/nix-support/libc-ldflags-before) $NIX_LDFLAGS_BEFORE_@suffixSalt@"
 fi
 
-export NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET=1
+export NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@=1
diff --git a/pkgs/build-support/bintools-wrapper/add-hardening.sh b/pkgs/build-support/bintools-wrapper/add-hardening.sh
index b7180870860a..5e49b7bd9053 100644
--- a/pkgs/build-support/bintools-wrapper/add-hardening.sh
+++ b/pkgs/build-support/bintools-wrapper/add-hardening.sh
@@ -5,7 +5,7 @@ declare -A hardeningEnableMap=()
 # Intentionally word-split in case 'NIX_HARDENING_ENABLE' is defined in Nix. The
 # array expansion also prevents undefined variables from causing trouble with
 # `set -u`.
-for flag in ${NIX_@infixSalt@_HARDENING_ENABLE-}; do
+for flag in ${NIX_HARDENING_ENABLE_@suffixSalt@-}; do
   hardeningEnableMap["$flag"]=1
 done
 
diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix
index 5cc99c6412a7..9e31ca6a8a21 100644
--- a/pkgs/build-support/bintools-wrapper/default.nix
+++ b/pkgs/build-support/bintools-wrapper/default.nix
@@ -45,7 +45,7 @@ let
   coreutils_bin = if nativeTools then "" else getBin coreutils;
 
   # See description in cc-wrapper.
-  infixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
+  suffixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
 
   # The dynamic linker has different names on different platforms. This is a
   # shell glob that ought to match it.
@@ -83,7 +83,7 @@ stdenv.mkDerivation {
   shell = getBin shell + shell.shellPath or "";
   gnugrep_bin = if nativeTools then "" else gnugrep;
 
-  inherit targetPrefix infixSalt;
+  inherit targetPrefix suffixSalt;
 
   outputs = [ "out" ] ++ optionals propagateDoc ([ "man" ] ++ optional (bintools ? info) "info");
 
@@ -95,9 +95,9 @@ stdenv.mkDerivation {
       (mapc
         (lambda (arg)
           (when (file-directory-p (concat arg "/lib"))
-            (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib")))
+            (setenv "NIX_LDFLAGS_${suffixSalt}" (concat (getenv "NIX_LDFLAGS_${suffixSalt}") " -L" arg "/lib")))
           (when (file-directory-p (concat arg "/lib64"))
-            (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib64"))))
+            (setenv "NIX_LDFLAGS_${suffixSalt}" (concat (getenv "NIX_LDFLAGS_${suffixSalt}") " -L" arg "/lib64"))))
         '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)}))
     '';
   };
@@ -248,6 +248,11 @@ stdenv.mkDerivation {
       printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before
     '')
 
+    + optionalString stdenv.targetPlatform.isMacOS ''
+      # Ensure consistent LC_VERSION_MIN_MACOSX and remove LC_UUID.
+      echo "-macosx_version_min 10.12 -sdk_version 10.12 -no_uuid" >> $out/nix-support/libc-ldflags-before
+    ''
+
     + optionalString (!nativeTools) ''
       ##
       ## User env support
diff --git a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh
index ed2f00a8974e..81b5a90edd5c 100644
--- a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh
+++ b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh
@@ -16,7 +16,7 @@ fi
 
 source @out@/nix-support/utils.bash
 
-if [ -z "${NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then
+if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
     source @out@/nix-support/add-flags.sh
 fi
 
@@ -24,7 +24,7 @@ fi
 # Optionally filter out paths not refering to the store.
 expandResponseParams "$@"
 if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}"
-        && ( -z "$NIX_@infixSalt@_IGNORE_LD_THROUGH_GCC" || -z "${NIX_@infixSalt@_LDFLAGS_SET:-}" ) ]]; then
+        && ( -z "$NIX_IGNORE_LD_THROUGH_GCC_@suffixSalt@" || -z "${NIX_LDFLAGS_SET_@suffixSalt@:-}" ) ]]; then
     rest=()
     nParams=${#params[@]}
     declare -i n=0
@@ -60,12 +60,12 @@ source @out@/nix-support/add-hardening.sh
 extraAfter=()
 extraBefore=(${hardeningLDFlags[@]+"${hardeningLDFlags[@]}"})
 
-if [ -z "${NIX_@infixSalt@_LDFLAGS_SET:-}" ]; then
-    extraAfter+=($NIX_@infixSalt@_LDFLAGS)
-    extraBefore+=($NIX_@infixSalt@_LDFLAGS_BEFORE)
+if [ -z "${NIX_LDFLAGS_SET_@suffixSalt@:-}" ]; then
+    extraAfter+=($NIX_LDFLAGS_@suffixSalt@)
+    extraBefore+=($NIX_LDFLAGS_BEFORE_@suffixSalt@)
 fi
 
-extraAfter+=($NIX_@infixSalt@_LDFLAGS_AFTER)
+extraAfter+=($NIX_LDFLAGS_AFTER_@suffixSalt@)
 
 # Specify the target emulation if nothing is passed in ("-m" overrides this
 # environment variable). Ensures we never blindly fallback on targeting the host
@@ -84,8 +84,8 @@ declare -A libs
 declare -i relocatable=0 link32=0
 
 if
-    [ "$NIX_@infixSalt@_DONT_SET_RPATH" != 1 ] \
-        || [ "$NIX_@infixSalt@_SET_BUILD_ID" = 1 ] \
+    [ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 ] \
+        || [ "$NIX_SET_BUILD_ID_@suffixSalt@" = 1 ] \
         || [ -e @out@/nix-support/dynamic-linker-m32 ]
 then
     prev=
@@ -144,7 +144,7 @@ if [ -e "@out@/nix-support/dynamic-linker-m32" ] && (( "$link32" )); then
 fi
 
 # Add all used dynamic libraries to the rpath.
-if [ "$NIX_@infixSalt@_DONT_SET_RPATH" != 1 ]; then
+if [ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 ]; then
     # For each directory in the library search path (-L...),
     # see if it contains a dynamic library used by a -l... flag.  If
     # so, add the directory to the rpath.
@@ -186,7 +186,7 @@ fi
 
 # Only add --build-id if this is a final link. FIXME: should build gcc
 # with --enable-linker-build-id instead?
-if [ "$NIX_@infixSalt@_SET_BUILD_ID" = 1 ] && ! (( "$relocatable" )); then
+if [ "$NIX_SET_BUILD_ID_@suffixSalt@" = 1 ] && ! (( "$relocatable" )); then
     extraAfter+=(--build-id)
 fi
 
diff --git a/pkgs/build-support/bintools-wrapper/setup-hook.sh b/pkgs/build-support/bintools-wrapper/setup-hook.sh
index a714bd151c90..7e9547b96c25 100644
--- a/pkgs/build-support/bintools-wrapper/setup-hook.sh
+++ b/pkgs/build-support/bintools-wrapper/setup-hook.sh
@@ -10,11 +10,11 @@
 
 bintoolsWrapper_addLDVars () {
     # See ../setup-hooks/role.bash
-    local role_post role_pre
+    local role_post
     getHostRoleEnvHook
 
     if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then
-        export NIX_${role_pre}LDFLAGS+=" -L$1/lib64"
+        export NIX_LDFLAGS${role_post}+=" -L$1/lib64"
     fi
 
     if [[ -d "$1/lib" ]]; then
@@ -24,7 +24,7 @@ bintoolsWrapper_addLDVars () {
         # directories and bloats the size of the environment variable space.
         local -a glob=( $1/lib/lib* )
         if [ "${#glob[*]}" -gt 0 ]; then
-            export NIX_${role_pre}LDFLAGS+=" -L$1/lib"
+            export NIX_LDFLAGS${role_post}+=" -L$1/lib"
         fi
     fi
 }
@@ -52,7 +52,7 @@ fi
 
 # Export tool environment variables so various build systems use the right ones.
 
-export NIX_${role_pre}BINTOOLS=@out@
+export NIX_BINTOOLS${role_post}=@out@
 
 for cmd in \
     ar as ld nm objcopy objdump readelf ranlib strip strings size windres
@@ -60,7 +60,6 @@ do
     if
         PATH=$_PATH type -p "@targetPrefix@${cmd}" > /dev/null
     then
-        export "${role_pre}${cmd^^}=@targetPrefix@${cmd}";
         export "${cmd^^}${role_post}=@targetPrefix@${cmd}";
     fi
 done
@@ -70,4 +69,4 @@ done
 export NIX_HARDENING_ENABLE
 
 # No local scope in sourced file
-unset -v role_pre role_post cmd upper_case
+unset -v role_post cmd upper_case
diff --git a/pkgs/build-support/build-fhs-userenv/env.nix b/pkgs/build-support/build-fhs-userenv/env.nix
index 8de43d5a9195..083e7617b502 100644
--- a/pkgs/build-support/build-fhs-userenv/env.nix
+++ b/pkgs/build-support/build-fhs-userenv/env.nix
@@ -58,7 +58,7 @@ let
 
     # Force compilers and other tools to look in default search paths
     unset NIX_ENFORCE_PURITY
-    export NIX_CC_WRAPPER_${stdenv.cc.infixSalt}_TARGET_HOST=1
+    export NIX_CC_WRAPPER_TARGET_HOST_${stdenv.cc.suffixSalt}=1
     export NIX_CFLAGS_COMPILE='-idirafter /usr/include'
     export NIX_CFLAGS_LINK='-L/usr/lib -L/usr/lib32'
     export NIX_LDFLAGS='-L/usr/lib -L/usr/lib32'
diff --git a/pkgs/build-support/cc-wrapper/add-flags.sh b/pkgs/build-support/cc-wrapper/add-flags.sh
index 323ea5bfd772..3398f11e8c21 100644
--- a/pkgs/build-support/cc-wrapper/add-flags.sh
+++ b/pkgs/build-support/cc-wrapper/add-flags.sh
@@ -5,15 +5,15 @@
 # wrapped binary just inherit the work of the forker's wrapper script.
 
 var_templates_list=(
-    NIX+CFLAGS_COMPILE
-    NIX+CFLAGS_COMPILE_BEFORE
-    NIX+CFLAGS_LINK
-    NIX+CXXSTDLIB_COMPILE
-    NIX+CXXSTDLIB_LINK
-    NIX+GNATFLAGS_COMPILE
+    NIX_CFLAGS_COMPILE
+    NIX_CFLAGS_COMPILE_BEFORE
+    NIX_CFLAGS_LINK
+    NIX_CXXSTDLIB_COMPILE
+    NIX_CXXSTDLIB_LINK
+    NIX_GNATFLAGS_COMPILE
 )
 var_templates_bool=(
-    NIX+ENFORCE_NO_NATIVE
+    NIX_ENFORCE_NO_NATIVE
 )
 
 accumulateRoles
@@ -21,37 +21,37 @@ accumulateRoles
 # We need to mangle names for hygiene, but also take parameters/overrides
 # from the environment.
 for var in "${var_templates_list[@]}"; do
-    mangleVarList "$var" ${role_infixes[@]+"${role_infixes[@]}"}
+    mangleVarList "$var" ${role_suffixes[@]+"${role_suffixes[@]}"}
 done
 for var in "${var_templates_bool[@]}"; do
-    mangleVarBool "$var" ${role_infixes[@]+"${role_infixes[@]}"}
+    mangleVarBool "$var" ${role_suffixes[@]+"${role_suffixes[@]}"}
 done
 
 # `-B@out@/bin' forces cc to use ld-wrapper.sh when calling ld.
-NIX_@infixSalt@_CFLAGS_COMPILE="-B@out@/bin/ $NIX_@infixSalt@_CFLAGS_COMPILE"
+NIX_CFLAGS_COMPILE_@suffixSalt@="-B@out@/bin/ $NIX_CFLAGS_COMPILE_@suffixSalt@"
 
 # Export and assign separately in order that a failing $(..) will fail
 # the script.
 
 if [ -e @out@/nix-support/libc-cflags ]; then
-    NIX_@infixSalt@_CFLAGS_COMPILE="$(< @out@/nix-support/libc-cflags) $NIX_@infixSalt@_CFLAGS_COMPILE"
+    NIX_CFLAGS_COMPILE_@suffixSalt@="$(< @out@/nix-support/libc-cflags) $NIX_CFLAGS_COMPILE_@suffixSalt@"
 fi
 
 if [ -e @out@/nix-support/cc-cflags ]; then
-    NIX_@infixSalt@_CFLAGS_COMPILE="$(< @out@/nix-support/cc-cflags) $NIX_@infixSalt@_CFLAGS_COMPILE"
+    NIX_CFLAGS_COMPILE_@suffixSalt@="$(< @out@/nix-support/cc-cflags) $NIX_CFLAGS_COMPILE_@suffixSalt@"
 fi
 
 if [ -e @out@/nix-support/gnat-cflags ]; then
-    NIX_@infixSalt@_GNATFLAGS_COMPILE="$(< @out@/nix-support/gnat-cflags) $NIX_@infixSalt@_GNATFLAGS_COMPILE"
+    NIX_GNATFLAGS_COMPILE_@suffixSalt@="$(< @out@/nix-support/gnat-cflags) $NIX_GNATFLAGS_COMPILE_@suffixSalt@"
 fi
 
 if [ -e @out@/nix-support/cc-ldflags ]; then
-    NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/cc-ldflags)"
+    NIX_LDFLAGS_@suffixSalt@+=" $(< @out@/nix-support/cc-ldflags)"
 fi
 
 if [ -e @out@/nix-support/cc-cflags-before ]; then
-    NIX_@infixSalt@_CFLAGS_COMPILE_BEFORE="$(< @out@/nix-support/cc-cflags-before) $NIX_@infixSalt@_CFLAGS_COMPILE_BEFORE"
+    NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@="$(< @out@/nix-support/cc-cflags-before) $NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@"
 fi
 
 # That way forked processes will not extend these environment variables again.
-export NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET=1
+export NIX_CC_WRAPPER_FLAGS_SET_@suffixSalt@=1
diff --git a/pkgs/build-support/cc-wrapper/add-hardening.sh b/pkgs/build-support/cc-wrapper/add-hardening.sh
index fc40fe7408b6..8e2fe6c407ea 100644
--- a/pkgs/build-support/cc-wrapper/add-hardening.sh
+++ b/pkgs/build-support/cc-wrapper/add-hardening.sh
@@ -5,7 +5,7 @@ declare -A hardeningEnableMap=()
 # Intentionally word-split in case 'NIX_HARDENING_ENABLE' is defined in Nix. The
 # array expansion also prevents undefined variables from causing trouble with
 # `set -u`.
-for flag in ${NIX_@infixSalt@_HARDENING_ENABLE-}; do
+for flag in ${NIX_HARDENING_ENABLE_@suffixSalt@-}; do
   hardeningEnableMap["$flag"]=1
 done
 
diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh
index ba3dfc96f5c4..cf00202221e6 100644
--- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh
+++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh
@@ -18,12 +18,12 @@ fi
 source @out@/nix-support/utils.bash
 
 # Flirting with a layer violation here.
-if [ -z "${NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then
+if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
     source @bintools@/nix-support/add-flags.sh
 fi
 
 # Put this one second so libc ldflags take priority.
-if [ -z "${NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then
+if [ -z "${NIX_CC_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
     source @out@/nix-support/add-flags.sh
 fi
 
@@ -113,7 +113,7 @@ fi
 
 
 # Clear march/mtune=native -- they bring impurity.
-if [ "$NIX_@infixSalt@_ENFORCE_NO_NATIVE" = 1 ]; then
+if [ "$NIX_ENFORCE_NO_NATIVE_@suffixSalt@" = 1 ]; then
     rest=()
     # Old bash empty array hack
     for p in ${params+"${params[@]}"}; do
@@ -129,36 +129,36 @@ fi
 
 if [[ "$isCpp" = 1 ]]; then
     if [[ "$cppInclude" = 1 ]]; then
-        NIX_@infixSalt@_CFLAGS_COMPILE+=" ${NIX_@infixSalt@_CXXSTDLIB_COMPILE:-@default_cxx_stdlib_compile@}"
+        NIX_CFLAGS_COMPILE_@suffixSalt@+=" ${NIX_CXXSTDLIB_COMPILE_@suffixSalt@:-@default_cxx_stdlib_compile@}"
     fi
-    NIX_@infixSalt@_CFLAGS_LINK+=" $NIX_@infixSalt@_CXXSTDLIB_LINK"
+    NIX_CFLAGS_LINK_@suffixSalt@+=" $NIX_CXXSTDLIB_LINK_@suffixSalt@"
 fi
 
 source @out@/nix-support/add-hardening.sh
 
 # Add the flags for the C compiler proper.
-extraAfter=($NIX_@infixSalt@_CFLAGS_COMPILE)
-extraBefore=(${hardeningCFlags[@]+"${hardeningCFlags[@]}"} $NIX_@infixSalt@_CFLAGS_COMPILE_BEFORE)
+extraAfter=($NIX_CFLAGS_COMPILE_@suffixSalt@)
+extraBefore=(${hardeningCFlags[@]+"${hardeningCFlags[@]}"} $NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@)
 
 if [ "$dontLink" != 1 ]; then
 
     # Add the flags that should only be passed to the compiler when
     # linking.
-    extraAfter+=($NIX_@infixSalt@_CFLAGS_LINK)
+    extraAfter+=($NIX_CFLAGS_LINK_@suffixSalt@)
 
     # Add the flags that should be passed to the linker (and prevent
-    # `ld-wrapper' from adding NIX_@infixSalt@_LDFLAGS again).
-    for i in $NIX_@infixSalt@_LDFLAGS_BEFORE; do
+    # `ld-wrapper' from adding NIX_LDFLAGS_@suffixSalt@ again).
+    for i in $NIX_LDFLAGS_BEFORE_@suffixSalt@; do
         extraBefore+=("-Wl,$i")
     done
-    for i in $NIX_@infixSalt@_LDFLAGS; do
+    for i in $NIX_LDFLAGS_@suffixSalt@; do
         if [ "${i:0:3}" = -L/ ]; then
             extraAfter+=("$i")
         else
             extraAfter+=("-Wl,$i")
         fi
     done
-    export NIX_@infixSalt@_LDFLAGS_SET=1
+    export NIX_LDFLAGS_SET_@suffixSalt@=1
 fi
 
 # As a very special hack, if the arguments are just `-v', then don't
diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix
index 36177ec2e358..da16a23f9dff 100644
--- a/pkgs/build-support/cc-wrapper/default.nix
+++ b/pkgs/build-support/cc-wrapper/default.nix
@@ -54,12 +54,12 @@ let
     "-isystem ${libcxx}/include/c++/v1"
   else "";
 
-  # The "infix salt" is a arbitrary string added in the middle of env vars
+  # The "suffix salt" is a arbitrary string added in the end of env vars
   # defined by cc-wrapper's hooks so that multiple cc-wrappers can be used
   # without interfering. For the moment, it is defined as the target triple,
   # adjusted to be a valid bash identifier. This should be considered an
   # unstable implementation detail, however.
-  infixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
+  suffixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
 
   expand-response-params =
     if buildPackages.stdenv.hasCC && buildPackages.stdenv.cc != "/dev/null"
@@ -106,7 +106,7 @@ stdenv.mkDerivation {
   shell = getBin shell + shell.shellPath or "";
   gnugrep_bin = if nativeTools then "" else gnugrep;
 
-  inherit targetPrefix infixSalt;
+  inherit targetPrefix suffixSalt;
 
   outputs = [ "out" ] ++ optionals propagateDoc [ "man" "info" ];
 
@@ -123,7 +123,7 @@ stdenv.mkDerivation {
       (mapc
         (lambda (arg)
           (when (file-directory-p (concat arg "/include"))
-            (setenv "NIX_${infixSalt}_CFLAGS_COMPILE" (concat (getenv "NIX_${infixSalt}_CFLAGS_COMPILE") " -isystem " arg "/include"))))
+            (setenv "NIX_CFLAGS_COMPILE_${suffixSalt}" (concat (getenv "NIX_CFLAGS_COMPILE_${suffixSalt}") " -isystem " arg "/include"))))
         '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)}))
     '';
   };
diff --git a/pkgs/build-support/cc-wrapper/gnat-wrapper.sh b/pkgs/build-support/cc-wrapper/gnat-wrapper.sh
index 15b53d76c630..d3f7d382c19a 100644
--- a/pkgs/build-support/cc-wrapper/gnat-wrapper.sh
+++ b/pkgs/build-support/cc-wrapper/gnat-wrapper.sh
@@ -18,12 +18,12 @@ fi
 source @out@/nix-support/utils.bash
 
 # Flirting with a layer violation here.
-if [ -z "${NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then
+if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
     source @bintools@/nix-support/add-flags.sh
 fi
 
 # Put this one second so libc ldflags take priority.
-if [ -z "${NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then
+if [ -z "${NIX_CC_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
     source @out@/nix-support/add-flags.sh
 fi
 
@@ -108,7 +108,7 @@ fi
 
 
 # Clear march/mtune=native -- they bring impurity.
-if [ "$NIX_@infixSalt@_ENFORCE_NO_NATIVE" = 1 ]; then
+if [ "$NIX_ENFORCE_NO_NATIVE_@suffixSalt@" = 1 ]; then
     rest=()
     # Old bash empty array hack
     for p in ${params+"${params[@]}"}; do
@@ -124,12 +124,12 @@ fi
 
 if [ "$(basename $0)x" = "gnatmakex" ]; then
     extraBefore=("--GNATBIND=@out@/bin/gnatbind" "--GNATLINK=@out@/bin/gnatlink")
-    extraAfter=($NIX_@infixSalt@_GNATFLAGS_COMPILE)
+    extraAfter=($NIX_GNATFLAGS_COMPILE_@suffixSalt@)
 fi
 
 if [ "$(basename $0)x" = "gnatbindx" ]; then
     extraBefore=()
-    extraAfter=($NIX_@infixSalt@_GNATFLAGS_COMPILE)
+    extraAfter=($NIX_GNATFLAGS_COMPILE_@suffixSalt@)
 fi
 
 if [ "$(basename $0)x" = "gnatlinkx" ]; then
diff --git a/pkgs/build-support/cc-wrapper/setup-hook.sh b/pkgs/build-support/cc-wrapper/setup-hook.sh
index 5b13f2683097..6a913cc4eac7 100644
--- a/pkgs/build-support/cc-wrapper/setup-hook.sh
+++ b/pkgs/build-support/cc-wrapper/setup-hook.sh
@@ -6,9 +6,9 @@
 # tools. For example:
 #
 #   # Flags for compiling (whether or not linking) C code for the...
-#   NIX_BUILD_CFLAGS_COMPILE  # ...build platform
-#   NIX_CFLAGS_COMPILE        # ...host platform
-#   NIX_TARGET_CFLAGS_COMPILE # ...target platform
+#   NIX_CFLAGS_COMPILE_FOR_BUILD  # ...build platform
+#   NIX_CFLAGS_COMPILE            # ...host platform
+#   NIX_CFLAGS_COMPILE_FOR_TARGET # ...target platform
 #
 # Notice that these platforms are the 3 *relative* to the package using
 # cc-wrapper, not absolute like `x86_64-pc-linux-gnu`.
@@ -33,12 +33,12 @@
 # The basic strategy is:
 #
 #  - Everyone exclusively *adds information* to relative-platform-specific
-#    environment variables, like `NIX_TARGET_CFLAGS_COMPILE`, to communicate
+#    environment variables, like `NIX_CFLAGS_COMPILE_FOR_TARGET`, to communicate
 #    with the wrapped binaries.
 #
 #  - The wrapped binaries will exclusively *read* cc-wrapper-derivation-specific
-#    environment variables distinguished with with `infixSalt`, like
-#    `NIX_@infixSalt@_CFLAGS_COMPILE`.
+#    environment variables distinguished with with `suffixSalt`, like
+#    `NIX_CFLAGS_COMPILE_@suffixSalt@`.
 #
 #  - `add-flags`, beyond its old task of reading extra flags stuck inside the
 #    cc-wrapper derivation, will convert the relative-platform-specific
@@ -65,15 +65,15 @@
 # function is guaranteed to be exactly the same.
 ccWrapper_addCVars () {
     # See ../setup-hooks/role.bash
-    local role_post role_pre
+    local role_post
     getHostRoleEnvHook
 
     if [ -d "$1/include" ]; then
-        export NIX_${role_pre}CFLAGS_COMPILE+=" -isystem $1/include"
+        export NIX_CFLAGS_COMPILE${role_post}+=" -isystem $1/include"
     fi
 
     if [ -d "$1/Library/Frameworks" ]; then
-        export NIX_${role_pre}CFLAGS_COMPILE+=" -iframework $1/Library/Frameworks"
+        export NIX_CFLAGS_COMPILE${role_post}+=" -iframework $1/Library/Frameworks"
     fi
 }
 
@@ -105,10 +105,10 @@ fi
 
 # Export tool environment variables so various build systems use the right ones.
 
-export NIX_${role_pre}CC=@out@
+export NIX_CC${role_post}=@out@
 
-export ${role_pre}CC=@named_cc@
-export ${role_pre}CXX=@named_cxx@
+export CC${role_post}=@named_cc@
+export CXX${role_post}=@named_cxx@
 export CC${role_post}=@named_cc@
 export CXX${role_post}=@named_cxx@
 
@@ -117,4 +117,4 @@ export CXX${role_post}=@named_cxx@
 export NIX_HARDENING_ENABLE
 
 # No local scope in sourced file
-unset -v role_pre role_post
+unset -v role_post
diff --git a/pkgs/build-support/dotnetbuildhelpers/default.nix b/pkgs/build-support/dotnetbuildhelpers/default.nix
index 0edfd0b467ab..809619ed55d9 100644
--- a/pkgs/build-support/dotnetbuildhelpers/default.nix
+++ b/pkgs/build-support/dotnetbuildhelpers/default.nix
@@ -12,7 +12,7 @@
         cp -v "$script" "$target"/"$scriptName"
         chmod 755 "$target"/"$scriptName"
         patchShebangs "$target"/"$scriptName"
-        substituteInPlace "$target"/"$scriptName" --replace pkg-config ${pkgconfig}/bin/pkg-config
+        substituteInPlace "$target"/"$scriptName" --replace pkg-config ${pkgconfig}/bin/${pkgconfig.targetPrefix}pkg-config
         substituteInPlace "$target"/"$scriptName" --replace monodis ${mono}/bin/monodis
       done
     ''
diff --git a/pkgs/build-support/emacs/wrapper.nix b/pkgs/build-support/emacs/wrapper.nix
index 25f068cd3fa0..1f2fbd8068e7 100644
--- a/pkgs/build-support/emacs/wrapper.nix
+++ b/pkgs/build-support/emacs/wrapper.nix
@@ -174,7 +174,7 @@ runCommand
 
     mkdir -p $out/share
     # Link icons and desktop files into place
-    for dir in applications icons info man; do
+    for dir in applications icons info man emacs; do
       ln -s $emacs/share/$dir $out/share/$dir
     done
   ''
diff --git a/pkgs/build-support/fetchmavenartifact/default.nix b/pkgs/build-support/fetchmavenartifact/default.nix
index d7ad406943be..583a9ea396cf 100644
--- a/pkgs/build-support/fetchmavenartifact/default.nix
+++ b/pkgs/build-support/fetchmavenartifact/default.nix
@@ -3,7 +3,7 @@
 { fetchurl, stdenv }:
 let
   defaultRepos = [
-    "http://central.maven.org/maven2"
+    "http://repo1.maven.org/maven2"
     "http://oss.sonatype.org/content/repositories/releases"
     "http://oss.sonatype.org/content/repositories/public"
     "http://repo.typesafe.com/typesafe/releases"
diff --git a/pkgs/build-support/fetchurl/mirrors.nix b/pkgs/build-support/fetchurl/mirrors.nix
index 4e8b0aa99a8f..0eba8816b638 100644
--- a/pkgs/build-support/fetchurl/mirrors.nix
+++ b/pkgs/build-support/fetchurl/mirrors.nix
@@ -426,7 +426,6 @@
   # Maven Central
   maven = [
     "https://repo1.maven.org/maven2/"
-    "https://central.maven.org/maven2/"
   ];
 
   # Alsa Project
diff --git a/pkgs/build-support/pkg-config-wrapper/add-flags.sh b/pkgs/build-support/pkg-config-wrapper/add-flags.sh
new file mode 100644
index 000000000000..35ecf62ca230
--- /dev/null
+++ b/pkgs/build-support/pkg-config-wrapper/add-flags.sh
@@ -0,0 +1,12 @@
+# See cc-wrapper for comments.
+var_templates_list=(
+    PKG_CONFIG_PATH
+)
+
+accumulateRoles
+
+for var in "${var_templates_list[@]}"; do
+    mangleVarList "$var" ${role_suffixes[@]+"${role_suffixes[@]}"}
+done
+
+export NIX_PKG_CONFIG_WRAPPER_FLAGS_SET_@suffixSalt@=1
diff --git a/pkgs/build-support/pkg-config-wrapper/default.nix b/pkgs/build-support/pkg-config-wrapper/default.nix
new file mode 100644
index 000000000000..e01df107dd17
--- /dev/null
+++ b/pkgs/build-support/pkg-config-wrapper/default.nix
@@ -0,0 +1,126 @@
+# The wrapper script ensures variables like PKG_CONFIG_PATH and
+# PKG_CONFIG_PATH_FOR_BUILD work properly.
+
+{ stdenvNoCC
+, buildPackages
+, pkg-config
+, baseBinName ? "pkg-config"
+, propagateDoc ? pkg-config != null && pkg-config ? man
+, extraPackages ? [], extraBuildCommands ? ""
+}:
+
+with stdenvNoCC.lib;
+
+let
+  stdenv = stdenvNoCC;
+  inherit (stdenv) hostPlatform targetPlatform;
+
+  # Prefix for binaries. Customarily ends with a dash separator.
+  #
+  # TODO(@Ericson2314) Make unconditional, or optional but always true by
+  # default.
+  targetPrefix = stdenv.lib.optionalString (targetPlatform != hostPlatform)
+                                        (targetPlatform.config + "-");
+
+  # See description in cc-wrapper.
+  suffixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
+
+in
+
+stdenv.mkDerivation {
+  pname = targetPrefix + pkg-config.pname + "-wrapper";
+  inherit (pkg-config) version;
+
+  preferLocalBuild = true;
+
+  shell = getBin stdenvNoCC.shell + stdenvNoCC.shell.shellPath or "";
+
+  inherit targetPrefix suffixSalt baseBinName;
+
+  outputs = [ "out" ] ++ optionals propagateDoc ([ "man" ] ++ optional (pkg-config ? doc) "doc");
+
+  passthru = {
+    inherit pkg-config;
+  };
+
+  dontBuild = true;
+  dontConfigure = true;
+
+  unpackPhase = ''
+    src=$PWD
+  '';
+
+  installPhase =
+    ''
+      mkdir -p $out/bin $out/nix-support
+
+      wrap() {
+        local dst="$1"
+        local wrapper="$2"
+        export prog="$3"
+        substituteAll "$wrapper" "$out/bin/$dst"
+        chmod +x "$out/bin/$dst"
+      }
+
+      echo $pkg-config > $out/nix-support/orig-pkg-config
+
+      wrap ${targetPrefix}${baseBinName} ${./pkg-config-wrapper.sh} "${getBin pkg-config}/bin/${baseBinName}"
+    ''
+    # symlink in share for autoconf to find macros
+
+    # TODO(@Ericson2314): in the future just make the unwrapped pkg-config a
+    # propagated dep once we can rely on downstream deps comming first in
+    # search paths. (https://github.com/NixOS/nixpkgs/pull/31414 took a crack
+    # at this.)
+    + ''
+      ln -s ${pkg-config}/share $out/share
+    '';
+
+  strictDeps = true;
+
+  wrapperName = "PKG_CONFIG_WRAPPER";
+
+  setupHooks = [
+    ../setup-hooks/role.bash
+    ./setup-hook.sh
+  ];
+
+  postFixup =
+    ##
+    ## User env support
+    ##
+
+    # Propagate the underling unwrapped pkg-config so that if you
+    # install the wrapper, you get anything else it might provide.
+    ''
+      printWords ${pkg-config} > $out/nix-support/propagated-user-env-packages
+    ''
+
+    ##
+    ## Man page and doc support
+    ##
+    + optionalString propagateDoc (''
+      ln -s ${pkg-config.man} $man
+    '' + optionalString (pkg-config ? doc) ''
+      ln -s ${pkg-config.doc} $doc
+    '')
+
+    + ''
+      substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
+      substituteAll ${../wrapper-common/utils.bash} $out/nix-support/utils.bash
+    ''
+
+    ##
+    ## Extra custom steps
+    ##
+    + extraBuildCommands;
+
+  meta =
+    let pkg-config_ = if pkg-config != null then pkg-config else {}; in
+    (if pkg-config_ ? meta then removeAttrs pkg-config.meta ["priority"] else {}) //
+    { description =
+        stdenv.lib.attrByPath ["meta" "description"] "pkg-config" pkg-config_
+        + " (wrapper script)";
+      priority = 10;
+  };
+}
diff --git a/pkgs/build-support/pkg-config-wrapper/pkg-config-wrapper.sh b/pkgs/build-support/pkg-config-wrapper/pkg-config-wrapper.sh
new file mode 100644
index 000000000000..f7c7429eb0b3
--- /dev/null
+++ b/pkgs/build-support/pkg-config-wrapper/pkg-config-wrapper.sh
@@ -0,0 +1,21 @@
+#! @shell@
+set -eu -o pipefail +o posix
+shopt -s nullglob
+
+if (( "${NIX_DEBUG:-0}" >= 7 )); then
+    set -x
+fi
+
+source @out@/nix-support/utils.bash
+
+if [ -z "${NIX_PKG_CONFIG_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
+    source @out@/nix-support/add-flags.sh
+fi
+
+if (( ${#role_suffixes[@]} > 0 )); then
+	# 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@ "$@"
+fi
diff --git a/pkgs/build-support/pkg-config-wrapper/setup-hook.sh b/pkgs/build-support/pkg-config-wrapper/setup-hook.sh
new file mode 100644
index 000000000000..34f1a999a82e
--- /dev/null
+++ b/pkgs/build-support/pkg-config-wrapper/setup-hook.sh
@@ -0,0 +1,29 @@
+# pkg-config Wrapper hygiene
+#
+# See comments in cc-wrapper's setup hook. This works exactly the same way.
+
+# Skip setup hook if we're neither a build-time dep, nor, temporarily, doing a
+# native compile.
+#
+# TODO(@Ericson2314): No native exception
+[[ -z ${strictDeps-} ]] || (( "$hostOffset" < 0 )) || return 0
+
+pkgConfigWrapper_addPkgConfigPath () {
+    # See ../setup-hooks/role.bash
+    local role_post
+    getHostRoleEnvHook
+
+    addToSearchPath "PKG_CONFIG_PATH${role_post}" "$1/lib/pkgconfig"
+    addToSearchPath "PKG_CONFIG_PATH${role_post}" "$1/share/pkgconfig"
+}
+
+# See ../setup-hooks/role.bash
+getTargetRole
+getTargetRoleWrapper
+
+addEnvHooks "$targetOffset" pkgConfigWrapper_addPkgConfigPath
+
+export PKG_CONFIG${role_post}=@targetPrefix@@baseBinName@
+
+# No local scope in sourced file
+unset -v role_post
diff --git a/pkgs/build-support/rust/build-rust-crate/build-crate.nix b/pkgs/build-support/rust/build-rust-crate/build-crate.nix
index d6d1cebb2e91..f82effdbca7c 100644
--- a/pkgs/build-support/rust/build-rust-crate/build-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate/build-crate.nix
@@ -1,4 +1,4 @@
-{ lib, stdenv, mkRustcDepArgs, rust }:
+{ lib, stdenv, mkRustcDepArgs, mkRustcFeatureArgs, rust }:
 { crateName,
   dependencies,
   crateFeatures, crateRenames, libName, release, libPath,
@@ -13,7 +13,7 @@
       ++ ["-C codegen-units=$NIX_BUILD_CORES"]
       ++ ["--remap-path-prefix=$NIX_BUILD_TOP=/" ]
       ++ [(mkRustcDepArgs dependencies crateRenames)]
-      ++ [crateFeatures]
+      ++ [(mkRustcFeatureArgs crateFeatures)]
       ++ extraRustcOpts
       ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) "--target ${rust.toRustTarget stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc"
       # since rustc 1.42 the "proc_macro" crate is part of the default crate prelude
diff --git a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
index c47bc00938c1..8e2f5f7f35e0 100644
--- a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
@@ -1,5 +1,6 @@
-{ lib, stdenv, echo_colored, noisily, mkRustcDepArgs }:
-{ build
+{ lib, stdenv, echo_colored, noisily, mkRustcDepArgs, mkRustcFeatureArgs }:
+{
+  build
 , buildDependencies
 , colors
 , completeBuildDeps
@@ -30,6 +31,9 @@ let version_ = lib.splitString "-" crateVersion;
     optLevel = if release then 3 else 0;
     completeDepsDir = lib.concatStringsSep " " completeDeps;
     completeBuildDepsDir = lib.concatStringsSep " " completeBuildDeps;
+    envFeatures = lib.concatStringsSep " " (
+      map (f: lib.replaceChars ["-"] ["_"] (lib.toUpper f)) crateFeatures
+    );
 in ''
   ${echo_colored colors}
   ${noisily colors verbose}
@@ -161,14 +165,24 @@ in ''
        EXTRA_BUILD_FLAGS="$EXTRA_BUILD_FLAGS $(tr '\n' ' ' < target/link.build)"
      fi
      noisily rustc --crate-name build_script_build $BUILD --crate-type bin ${rustcOpts} \
-       ${crateFeatures} --out-dir target/build/${crateName} --emit=dep-info,link \
+       ${mkRustcFeatureArgs crateFeatures} --out-dir target/build/${crateName} --emit=dep-info,link \
        -L dependency=target/buildDeps ${buildDeps} --cap-lints allow $EXTRA_BUILD_FLAGS --color ${colors}
 
      mkdir -p target/build/${crateName}.out
      export RUST_BACKTRACE=1
      BUILD_OUT_DIR="-L $OUT_DIR"
      mkdir -p $OUT_DIR
-     target/build/${crateName}/build_script_build > target/build/${crateName}.opt
+
+     (
+       # Features should be set as environment variable for build scripts:
+       # https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
+       for feature in ${envFeatures}; do
+         export CARGO_FEATURE_$feature=1
+       done
+
+       target/build/${crateName}/build_script_build > target/build/${crateName}.opt
+     )
+
      set +e
      EXTRA_BUILD=$(sed -n "s/^cargo:rustc-flags=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u)
      EXTRA_FEATURES=$(sed -n "s/^cargo:rustc-cfg=\(.*\)/--cfg \1/p" target/build/${crateName}.opt | tr '\n' ' ')
diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix
index d9ed26f1d94a..d559aba16165 100644
--- a/pkgs/build-support/rust/build-rust-crate/default.nix
+++ b/pkgs/build-support/rust/build-rust-crate/default.nix
@@ -45,14 +45,17 @@ let
            " --extern ${name}=${dep.lib}/lib/lib${extern}-${dep.metadata}${stdenv.hostPlatform.extensions.sharedLibrary}")
       ) dependencies;
 
+   # Create feature arguments for rustc.
+   mkRustcFeatureArgs = lib.concatMapStringsSep " " (f: ''--cfg feature=\"${f}\"'');
+
    inherit (import ./log.nix { inherit lib; }) noisily echo_colored;
 
    configureCrate = import ./configure-crate.nix {
-     inherit lib stdenv echo_colored noisily mkRustcDepArgs;
+     inherit lib stdenv echo_colored noisily mkRustcDepArgs mkRustcFeatureArgs;
    };
 
    buildCrate = import ./build-crate.nix {
-     inherit lib stdenv mkRustcDepArgs rust;
+     inherit lib stdenv mkRustcDepArgs mkRustcFeatureArgs rust;
    };
 
    installCrate = import ./install-crate.nix { inherit stdenv; };
@@ -233,8 +236,11 @@ stdenv.mkDerivation (rec {
       ++ lib.concatMap (dep: dep.completeBuildDeps ++ dep.completeDeps) buildDependencies
     );
 
-    crateFeatures = lib.optionalString (crate ? features)
-      (lib.concatMapStringsSep " " (f: ''--cfg feature=\"${f}\"'') (crate.features ++ features));
+    # 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.
+    crateFeatures = lib.optionals (crate ? features)
+      (builtins.filter (f: !lib.hasInfix "/" f) (crate.features ++ features));
 
     libName = if crate ? libName then crate.libName else crate.crateName;
     libPath = if crate ? libPath then crate.libPath else "";
@@ -244,7 +250,8 @@ stdenv.mkDerivation (rec {
     metadata = let
       depsMetadata = lib.foldl' (str: dep: str + dep.metadata) "" (dependencies ++ buildDependencies);
       hashedMetadata = builtins.hashString "sha256"
-        (crateName + "-" + crateVersion + "___" + toString crateFeatures + "___" + depsMetadata);
+        (crateName + "-" + crateVersion + "___" + toString (mkRustcFeatureArgs crateFeatures) +
+          "___" + depsMetadata);
       in lib.substring 0 10 hashedMetadata;
 
     build = crate.build or "";
diff --git a/pkgs/build-support/rust/build-rust-crate/test/default.nix b/pkgs/build-support/rust/build-rust-crate/test/default.nix
index bdd6c86d5f07..24ddc11459ec 100644
--- a/pkgs/build-support/rust/build-rust-crate/test/default.nix
+++ b/pkgs/build-support/rust/build-rust-crate/test/default.nix
@@ -344,6 +344,32 @@ let
         buildTests = true;
         expectedTestOutputs = [ "test baz_false ... ok" ];
       };
+      buildScriptFeatureEnv = {
+        crateName = "build-script-feature-env";
+        features = [ "some-feature" "crate/another_feature" ];
+        src = symlinkJoin {
+          name = "build-script-feature-env";
+          paths = [
+            (mkFile  "src/main.rs" ''
+              #[cfg(test)]
+              #[test]
+              fn feature_not_visible() {
+                assert!(std::env::var("CARGO_FEATURE_SOME_FEATURE").is_err());
+                assert!(option_env!("CARGO_FEATURE_SOME_FEATURE").is_none());
+              }
+              fn main() {}
+            '')
+            (mkFile  "build.rs" ''
+              fn main() {
+                assert!(std::env::var("CARGO_FEATURE_SOME_FEATURE").is_ok());
+                assert!(option_env!("CARGO_FEATURE_SOME_FEATURE").is_none());
+              }
+            '')
+          ];
+        };
+        buildTests = true;
+        expectedTestOutputs = [ "test feature_not_visible ... ok" ];
+      };
       # Regression test for https://github.com/NixOS/nixpkgs/pull/88054
       # Build script output should be rewritten as valid env vars.
       buildScriptIncludeDirDeps = let
diff --git a/pkgs/build-support/rust/default.nix b/pkgs/build-support/rust/default.nix
index a6b47930c274..8d3a7ba6929c 100644
--- a/pkgs/build-support/rust/default.nix
+++ b/pkgs/build-support/rust/default.nix
@@ -28,6 +28,13 @@
 , meta ? {}
 , target ? null
 , cargoVendorDir ? null
+, checkType ? buildType
+
+# Needed to `pushd`/`popd` into a subdir of a tarball if this subdir
+# contains a Cargo.toml, but isn't part of a workspace (which is e.g. the
+# case for `rustfmt`/etc from the `rust-sources).
+# Otherwise, everything from the tarball would've been built/tested.
+, buildAndTestSubdir ? null
 , ... } @ args:
 
 assert cargoVendorDir == null -> cargoSha256 != "unset";
@@ -70,7 +77,8 @@ let
 
   # Specify the stdenv's `diff` by abspath to ensure that the user's build
   # inputs do not cause us to find the wrong `diff`.
-  diff = "${diffutils}/bin/diff";
+  # The `.nativeDrv` stanza works like nativeBuildInputs and ensures cross-compiling has the right version available.
+  diff = "${diffutils.nativeDrv or diffutils}/bin/diff";
 
 in
 
@@ -130,6 +138,7 @@ stdenv.mkDerivation (args // {
       # give a friendlier error msg.
       if ! [ -e $srcLockfile ]; then
         echo "ERROR: Missing Cargo.lock from src. Expected to find it at: $srcLockfile"
+        echo "Hint: You can use the cargoPatches attribute to add a Cargo.lock manually to the build."
         exit 1
       fi
 
@@ -161,6 +170,7 @@ stdenv.mkDerivation (args // {
   '';
 
   buildPhase = with builtins; args.buildPhase or ''
+    ${stdenv.lib.optionalString (buildAndTestSubdir != null) "pushd ${buildAndTestSubdir}"}
     runHook preBuild
 
     (
@@ -176,22 +186,29 @@ stdenv.mkDerivation (args // {
         --frozen ${concatStringsSep " " cargoBuildFlags}
     )
 
-    # rename the output dir to a architecture independent one
-    mapfile -t targets < <(find "$NIX_BUILD_TOP" -type d | grep '${releaseDir}$')
-    for target in "''${targets[@]}"; do
-      rm -rf "$target/../../${buildType}"
-      ln -srf "$target" "$target/../../"
-    done
-
     runHook postBuild
+
+    ${stdenv.lib.optionalString (buildAndTestSubdir != null) "popd"}
+
+    # This needs to be done after postBuild: packages like `cargo` do a pushd/popd in
+    # the pre/postBuild-hooks that need to be taken into account before gathering
+    # all binaries to install.
+    bins=$(find $releaseDir \
+      -maxdepth 1 \
+      -type f \
+      -executable ! \( -regex ".*\.\(so.[0-9.]+\|so\|a\|dylib\)" \))
   '';
 
-  checkPhase = args.checkPhase or ''
+  checkPhase = args.checkPhase or (let
+    argstr = "${stdenv.lib.optionalString (checkType == "release") "--release"} --target ${rustTarget} --frozen";
+  in ''
+    ${stdenv.lib.optionalString (buildAndTestSubdir != null) "pushd ${buildAndTestSubdir}"}
     runHook preCheck
-    echo "Running cargo cargo test -- ''${checkFlags} ''${checkFlagsArray+''${checkFlagsArray[@]}}"
-    cargo test -- ''${checkFlags} ''${checkFlagsArray+"''${checkFlagsArray[@]}"}
+    echo "Running cargo test ${argstr} -- ''${checkFlags} ''${checkFlagsArray+''${checkFlagsArray[@]}}"
+    cargo test ${argstr} -- ''${checkFlags} ''${checkFlagsArray+"''${checkFlagsArray[@]}"}
     runHook postCheck
-  '';
+    ${stdenv.lib.optionalString (buildAndTestSubdir != null) "popd"}
+  '');
 
   doCheck = args.doCheck or true;
 
@@ -201,13 +218,16 @@ stdenv.mkDerivation (args // {
 
   installPhase = args.installPhase or ''
     runHook preInstall
+
+    # rename the output dir to a architecture independent one
+    mapfile -t targets < <(find "$NIX_BUILD_TOP" -type d | grep '${releaseDir}$')
+    for target in "''${targets[@]}"; do
+      rm -rf "$target/../../${buildType}"
+      ln -srf "$target" "$target/../../"
+    done
     mkdir -p $out/bin $out/lib
 
-    find $releaseDir \
-      -maxdepth 1 \
-      -type f \
-      -executable ! \( -regex ".*\.\(so.[0-9.]+\|so\|a\|dylib\)" \) \
-      -print0 | xargs -r -0 cp -t $out/bin
+    xargs -r cp -t $out/bin <<< $bins
     find $releaseDir \
       -maxdepth 1 \
       -regex ".*\.\(so.[0-9.]+\|so\|a\|dylib\)" \
diff --git a/pkgs/build-support/setup-hooks/role.bash b/pkgs/build-support/setup-hooks/role.bash
index 6f1c36f5c050..cf69e732e7c3 100644
--- a/pkgs/build-support/setup-hooks/role.bash
+++ b/pkgs/build-support/setup-hooks/role.bash
@@ -3,21 +3,17 @@
 # derivation) in which the derivation is used.
 #
 # The role is intened to be use as part of other variables names like
-#  - $NIX_${role_pre}_SOMETHING
-#  - $NIX_SOMETHING_${role_post}
+#  - $NIX_SOMETHING${role_post}
 
 function getRole() {
     case $1 in
         -1)
-            role_pre='BUILD_'
             role_post='_FOR_BUILD'
             ;;
         0)
-            role_pre=''
             role_post=''
             ;;
         1)
-            role_pre='TARGET_'
             role_post='_FOR_TARGET'
             ;;
         *)
@@ -54,18 +50,18 @@ function getTargetRoleEnvHook() {
 }
 
 # This variant is inteneded specifically for code-prodocing tool wrapper scripts
-# `NIX_@wrapperName@_@infixSalt@_TARGET_*` tracks this (needs to be an exported
+# `NIX_@wrapperName@_TARGET_*_@suffixSalt@` tracks this (needs to be an exported
 # env var so can't use fancier data structures).
 function getTargetRoleWrapper() {
     case $targetOffset in
         -1)
-            export NIX_@wrapperName@_@infixSalt@_TARGET_BUILD=1
+            export NIX_@wrapperName@_TARGET_BUILD_@suffixSalt@=1
             ;;
         0)
-            export NIX_@wrapperName@_@infixSalt@_TARGET_HOST=1
+            export NIX_@wrapperName@_TARGET_HOST_@suffixSalt@=1
             ;;
         1)
-            export NIX_@wrapperName@_@infixSalt@_TARGET_TARGET=1
+            export NIX_@wrapperName@_TARGET_TARGET_@suffixSalt@=1
             ;;
         *)
             echo "@name@: used as improper sort of dependency" >2
diff --git a/pkgs/build-support/setup-hooks/validate-pkg-config.sh b/pkgs/build-support/setup-hooks/validate-pkg-config.sh
new file mode 100644
index 000000000000..54fc9cc122ca
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/validate-pkg-config.sh
@@ -0,0 +1,19 @@
+# This setup hook validates each pkgconfig file in each output.
+
+fixupOutputHooks+=(_validatePkgConfig)
+
+_validatePkgConfig() {
+    for pc in $(find "$prefix" -name '*.pc'); do
+        local bail=0
+
+        # Do not fail immediately. It's nice to see all errors when
+        # there are multiple pkgconfig files.
+        if ! pkg-config --validate "$pc"; then
+            bail=1
+        fi
+    done
+
+    if [ $bail -eq 1 ]; then
+        exit 1
+    fi
+}
diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix
index f86e33713840..909cdc6da044 100644
--- a/pkgs/build-support/vm/default.nix
+++ b/pkgs/build-support/vm/default.nix
@@ -115,7 +115,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,cache=loose
+    mount -t 9p xchg /fs/tmp/xchg -o trans=virtio,version=9p2000.L
 
     mkdir -p /fs/proc
     mount -t proc none /fs/proc
diff --git a/pkgs/build-support/vm/windows/controller/default.nix b/pkgs/build-support/vm/windows/controller/default.nix
index 08b93aaf1174..9d13983a2833 100644
--- a/pkgs/build-support/vm/windows/controller/default.nix
+++ b/pkgs/build-support/vm/windows/controller/default.nix
@@ -53,7 +53,7 @@ let
       store /fs/nix/store
 
     mount -t 9p \
-      -o trans=virtio,version=9p2000.L,cache=loose \
+      -o trans=virtio,version=9p2000.L \
       xchg /fs/xchg
 
     echo root:x:0:0::/root:/bin/false > /fs/etc/passwd
diff --git a/pkgs/build-support/wrapper-common/utils.bash b/pkgs/build-support/wrapper-common/utils.bash
index 4fd57162072e..8c4680a8e446 100644
--- a/pkgs/build-support/wrapper-common/utils.bash
+++ b/pkgs/build-support/wrapper-common/utils.bash
@@ -1,29 +1,29 @@
-# Accumulate infixes for taking in the right input parameters with the `mangle*`
+# Accumulate suffixes for taking in the right input parameters with the `mangle*`
 # functions below. See setup-hook for details.
 accumulateRoles() {
-    declare -ga role_infixes=()
-    if [ "${NIX_@wrapperName@_@infixSalt@_TARGET_BUILD:-}" ]; then
-        role_infixes+=(_BUILD_)
+    declare -ga role_suffixes=()
+    if [ "${NIX_@wrapperName@_TARGET_BUILD_@suffixSalt@:-}" ]; then
+        role_suffixes+=('_FOR_BUILD')
     fi
-    if [ "${NIX_@wrapperName@_@infixSalt@_TARGET_HOST:-}" ]; then
-        role_infixes+=(_)
+    if [ "${NIX_@wrapperName@_TARGET_HOST_@suffixSalt@:-}" ]; then
+        role_suffixes+=('')
     fi
-    if [ "${NIX_@wrapperName@_@infixSalt@_TARGET_TARGET:-}" ]; then
-        role_infixes+=(_TARGET_)
+    if [ "${NIX_@wrapperName@_TARGET_TARGET_@suffixSalt@:-}" ]; then
+        role_suffixes+=('_FOR_TARGET')
     fi
 }
 
 mangleVarList() {
     local var="$1"
     shift
-    local -a role_infixes=("$@")
+    local -a role_suffixes=("$@")
 
-    local outputVar="${var/+/_@infixSalt@_}"
+    local outputVar="${var}_@suffixSalt@"
     declare -gx ${outputVar}+=''
     # For each role we serve, we accumulate the input parameters into our own
     # cc-wrapper-derivation-specific environment variables.
-    for infix in "${role_infixes[@]}"; do
-        local inputVar="${var/+/${infix}}"
+    for suffix in "${role_suffixes[@]}"; do
+        local inputVar="${var}${suffix}"
         if [ -v "$inputVar" ]; then
             export ${outputVar}+="${!outputVar:+ }${!inputVar}"
         fi
@@ -33,12 +33,12 @@ mangleVarList() {
 mangleVarBool() {
     local var="$1"
     shift
-    local -a role_infixes=("$@")
+    local -a role_suffixes=("$@")
 
-    local outputVar="${var/+/_@infixSalt@_}"
+    local outputVar="${var}_@suffixSalt@"
     declare -gxi ${outputVar}+=0
-    for infix in "${role_infixes[@]}"; do
-        local inputVar="${var/+/${infix}}"
+    for suffix in "${role_suffixes[@]}"; do
+        local inputVar="${var}${suffix}"
         if [ -v "$inputVar" ]; then
             # "1" in the end makes `let` return success error code when
             # expression itself evaluates to zero.