summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
authorParnell Springmeyer <parnell@digitalmentat.com>2018-01-10 10:13:49 -0800
committerParnell Springmeyer <parnell@digitalmentat.com>2018-01-10 10:13:49 -0800
commite4ec980e9ced7dbea0fb1310f831207bbc7175b0 (patch)
tree0c9ec3233fc73958db0637d409a44c527f0984eb /pkgs/build-support
parenta6cdf0aaa17530773f1de918c88a1f3245fd2612 (diff)
parent80cb0c39de929f7e8e65d587cb22af777db98bea (diff)
downloadnixpkgs-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar
nixpkgs-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.gz
nixpkgs-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.bz2
nixpkgs-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.lz
nixpkgs-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.xz
nixpkgs-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.zst
nixpkgs-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.zip
Merge remote-tracking branch 'upstream/master' into parnell/fetchdocker
Diffstat (limited to 'pkgs/build-support')
-rw-r--r--pkgs/build-support/bintools-wrapper/add-flags.sh40
-rw-r--r--pkgs/build-support/bintools-wrapper/add-hardening.sh53
-rw-r--r--pkgs/build-support/bintools-wrapper/default.nix306
-rw-r--r--[-rwxr-xr-x]pkgs/build-support/bintools-wrapper/ld-solaris-wrapper.sh (renamed from pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh)0
-rw-r--r--pkgs/build-support/bintools-wrapper/ld-wrapper.sh (renamed from pkgs/build-support/cc-wrapper/ld-wrapper.sh)11
-rw-r--r--pkgs/build-support/bintools-wrapper/macos-sierra-reexport-hack.bash (renamed from pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash)4
-rw-r--r--pkgs/build-support/bintools-wrapper/setup-hook.sh88
-rwxr-xr-xpkgs/build-support/build-fhs-userenv/chroot-user.rb169
-rw-r--r--pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c139
-rw-r--r--pkgs/build-support/build-fhs-userenv/chrootenv/default.nix19
-rw-r--r--pkgs/build-support/build-fhs-userenv/default.nix18
-rw-r--r--pkgs/build-support/build-pecl.nix2
-rw-r--r--pkgs/build-support/cc-wrapper/add-flags.sh35
-rw-r--r--pkgs/build-support/cc-wrapper/add-hardening.sh10
-rw-r--r--pkgs/build-support/cc-wrapper/cc-wrapper.sh13
-rw-r--r--pkgs/build-support/cc-wrapper/default.nix162
-rw-r--r--pkgs/build-support/cc-wrapper/gnat-wrapper.sh8
-rw-r--r--pkgs/build-support/cc-wrapper/setup-hook.sh88
-rw-r--r--pkgs/build-support/cc-wrapper/utils.sh32
-rw-r--r--pkgs/build-support/docker/examples.nix2
-rw-r--r--pkgs/build-support/emacs/setup-hook.sh6
-rw-r--r--pkgs/build-support/emacs/wrapper.nix36
-rw-r--r--pkgs/build-support/fetchsvn/builder.sh6
-rw-r--r--pkgs/build-support/gcc-wrapper-old/default.nix27
-rw-r--r--pkgs/build-support/gcc-wrapper-old/setup-hook.sh4
-rw-r--r--pkgs/build-support/libredirect/default.nix6
-rw-r--r--pkgs/build-support/mkshell/default.nix46
-rw-r--r--pkgs/build-support/release/source-tarball.nix2
-rw-r--r--pkgs/build-support/rust/build-rust-crate.nix382
-rw-r--r--pkgs/build-support/rust/cargo-vendor.nix6
-rw-r--r--pkgs/build-support/rust/carnix.nix875
-rw-r--r--pkgs/build-support/rust/default-crate-overrides.nix10
-rw-r--r--pkgs/build-support/rust/fetchcrate.nix35
-rw-r--r--pkgs/build-support/setup-hooks/find-xml-catalogs.sh2
-rw-r--r--pkgs/build-support/setup-hooks/ld-is-cc-hook.sh5
-rw-r--r--pkgs/build-support/setup-hooks/separate-debug-info.sh6
-rw-r--r--pkgs/build-support/setup-hooks/set-java-classpath.sh2
-rw-r--r--pkgs/build-support/setup-hooks/setup-debug-info-dirs.sh2
-rw-r--r--pkgs/build-support/setup-hooks/strip.sh37
-rw-r--r--pkgs/build-support/setup-hooks/win-dll-link.sh2
-rw-r--r--pkgs/build-support/setup-hooks/wrap-gapps-hook.sh2
-rw-r--r--pkgs/build-support/singularity-tools/default.nix7
-rw-r--r--pkgs/build-support/trivial-builders.nix4
-rw-r--r--pkgs/build-support/vm/default.nix53
44 files changed, 2278 insertions, 484 deletions
diff --git a/pkgs/build-support/bintools-wrapper/add-flags.sh b/pkgs/build-support/bintools-wrapper/add-flags.sh
new file mode 100644
index 00000000000..7d118d20fc6
--- /dev/null
+++ b/pkgs/build-support/bintools-wrapper/add-flags.sh
@@ -0,0 +1,40 @@
+# See cc-wrapper for comments.
+var_templates_list=(
+    NIX+IGNORE_LD_THROUGH_GCC
+    NIX+LDFLAGS
+    NIX+LDFLAGS_BEFORE
+    NIX+LDFLAGS_AFTER
+    NIX+LDFLAGS_HARDEN
+)
+var_templates_bool=(
+    NIX+SET_BUILD_ID
+    NIX+DONT_SET_RPATH
+)
+
+declare -a role_infixes=()
+if [ "${NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_BUILD:-}" ]; then
+    role_infixes+=(_BUILD_)
+fi
+if [ "${NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_HOST:-}" ]; then
+    role_infixes+=(_)
+fi
+if [ "${NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_TARGET:-}" ]; then
+    role_infixes+=(_TARGET_)
+fi
+
+for var in "${var_templates_list[@]}"; do
+    mangleVarList "$var" "${role_infixes[@]}"
+done
+for var in "${var_templates_bool[@]}"; do
+    mangleVarBool "$var" "${role_infixes[@]}"
+done
+
+if [ -e @out@/nix-support/libc-ldflags ]; then
+    NIX_@infixSalt@_LDFLAGS+=" $(< @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"
+fi
+
+export NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET=1
diff --git a/pkgs/build-support/bintools-wrapper/add-hardening.sh b/pkgs/build-support/bintools-wrapper/add-hardening.sh
new file mode 100644
index 00000000000..5282d17fce2
--- /dev/null
+++ b/pkgs/build-support/bintools-wrapper/add-hardening.sh
@@ -0,0 +1,53 @@
+hardeningFlags=(relro bindnow)
+# Intentionally word-split in case 'hardeningEnable' is defined in
+# Nix. Also, our bootstrap tools version of bash is old enough that
+# undefined arrays trip `set -u`.
+if [[ -v hardeningEnable[@] ]]; then
+  hardeningFlags+=(${hardeningEnable[@]})
+fi
+hardeningLDFlags=()
+
+declare -A hardeningDisableMap
+
+# Intentionally word-split in case 'hardeningDisable' is defined in Nix.
+for flag in ${hardeningDisable[@]:-IGNORED_KEY} @hardening_unsupported_flags@
+do
+  hardeningDisableMap[$flag]=1
+done
+
+if (( "${NIX_DEBUG:-0}" >= 1 )); then
+  printf 'HARDENING: disabled flags:' >&2
+  (( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2
+  echo >&2
+fi
+
+if [[ -z "${hardeningDisableMap[all]:-}" ]]; then
+  if (( "${NIX_DEBUG:-0}" >= 1 )); then
+    echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2;
+  fi
+  for flag in "${hardeningFlags[@]}"
+  do
+    if [[ -z "${hardeningDisableMap[$flag]:-}" ]]; then
+      case $flag in
+        pie)
+          if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then
+            if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling LDFlags -pie >&2; fi
+            hardeningLDFlags+=('-pie')
+          fi
+          ;;
+        relro)
+          if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling relro >&2; fi
+          hardeningLDFlags+=('-z' 'relro')
+          ;;
+        bindnow)
+          if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling bindnow >&2; fi
+          hardeningLDFlags+=('-z' 'now')
+          ;;
+        *)
+          # Ignore unsupported. Checked in Nix that at least *some*
+          # tool supports each flag.
+          ;;
+      esac
+    fi
+  done
+fi
diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix
new file mode 100644
index 00000000000..bb0e6b82aa5
--- /dev/null
+++ b/pkgs/build-support/bintools-wrapper/default.nix
@@ -0,0 +1,306 @@
+# The Nixpkgs CC is not directly usable, since it doesn't know where
+# the C library and standard header files are. Therefore the compiler
+# produced by that package cannot be installed directly in a user
+# environment and used from the command line. So we use a wrapper
+# script that sets up the right environment variables so that the
+# compiler and the linker just "work".
+
+{ name ? "", stdenvNoCC, nativeTools, noLibc ? false, nativeLibc, nativePrefix ? ""
+, bintools ? null, libc ? null
+, coreutils ? null, shell ? stdenvNoCC.shell, gnugrep ? null
+, extraPackages ? [], extraBuildCommands ? ""
+, buildPackages ? {}
+, useMacosReexportHack ? false
+}:
+
+with stdenvNoCC.lib;
+
+assert nativeTools -> nativePrefix != "";
+assert !nativeTools ->
+  bintools != null && coreutils != null && gnugrep != null;
+assert !(nativeLibc && noLibc);
+assert (noLibc || nativeLibc) == (libc == null);
+
+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 + "-");
+
+  bintoolsVersion = (builtins.parseDrvName bintools.name).version;
+  bintoolsName = (builtins.parseDrvName bintools.name).name;
+
+  libc_bin = if libc == null then null else getBin libc;
+  libc_dev = if libc == null then null else getDev libc;
+  libc_lib = if libc == null then null else getLib libc;
+  bintools_bin = if nativeTools then "" else getBin bintools;
+  # The wrapper scripts use 'cat' and 'grep', so we may need coreutils.
+  coreutils_bin = if nativeTools then "" else getBin coreutils;
+
+  dashlessTarget = stdenv.lib.replaceStrings ["-"] ["_"] targetPlatform.config;
+
+  # See description in cc-wrapper.
+  infixSalt = dashlessTarget;
+
+  # The dynamic linker has different names on different platforms. This is a
+  # shell glob that ought to match it.
+  dynamicLinker =
+    /**/ if libc == null then null
+    else if targetPlatform.system == "i686-linux"     then "${libc_lib}/lib/ld-linux.so.2"
+    else if targetPlatform.system == "x86_64-linux"   then "${libc_lib}/lib/ld-linux-x86-64.so.2"
+    # ARM with a wildcard, which can be "" or "-armhf".
+    else if (with targetPlatform; isArm && isLinux)   then "${libc_lib}/lib/ld-linux*.so.3"
+    else if targetPlatform.system == "aarch64-linux"  then "${libc_lib}/lib/ld-linux-aarch64.so.1"
+    else if targetPlatform.system == "powerpc-linux"  then "${libc_lib}/lib/ld.so.1"
+    else if targetPlatform.system == "mips64el-linux" then "${libc_lib}/lib/ld.so.1"
+    else if targetPlatform.isDarwin                   then "/usr/lib/dyld"
+    else if stdenv.lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1"
+    else null;
+
+  expand-response-params =
+    if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null"
+    then import ../expand-response-params { inherit (buildPackages) stdenv; }
+    else "";
+
+in
+
+stdenv.mkDerivation {
+  name = targetPrefix
+    + (if name != "" then name else "${bintoolsName}-wrapper")
+    + (stdenv.lib.optionalString (bintools != null && bintoolsVersion != "") "-${bintoolsVersion}");
+
+  preferLocalBuild = true;
+
+  inherit bintools_bin libc_bin libc_dev libc_lib coreutils_bin;
+  shell = getBin shell + shell.shellPath or "";
+  gnugrep_bin = if nativeTools then "" else gnugrep;
+
+  inherit targetPrefix infixSalt;
+
+  outputs = [ "out" "info" "man" ];
+
+  passthru = {
+    inherit bintools libc nativeTools nativeLibc nativePrefix;
+
+    emacsBufferSetup = pkgs: ''
+      ; We should handle propagation here too
+      (mapc
+        (lambda (arg)
+          (when (file-directory-p (concat arg "/lib"))
+            (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib")))
+          (when (file-directory-p (concat arg "/lib64"))
+            (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib64"))))
+        '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)}))
+    '';
+  };
+
+  dontBuild = true;
+  dontConfigure = true;
+
+  unpackPhase = ''
+    src=$PWD
+  '';
+
+  installPhase =
+    ''
+      set -u
+
+      mkdir -p $out/bin {$out,$info,$man}/nix-support
+
+      wrap() {
+        local dst="$1"
+        local wrapper="$2"
+        export prog="$3"
+        set +u
+        substituteAll "$wrapper" "$out/bin/$dst"
+        set -u
+        chmod +x "$out/bin/$dst"
+      }
+    ''
+
+    + (if nativeTools then ''
+      echo ${nativePrefix} > $out/nix-support/orig-bintools
+
+      ldPath="${nativePrefix}/bin"
+    '' else ''
+      echo $bintools_bin > $out/nix-support/orig-bintools
+
+      ldPath="${bintools_bin}/bin"
+    ''
+
+    + optionalString (targetPlatform.isSunOS && nativePrefix != "") ''
+      # Solaris needs an additional ld wrapper.
+      ldPath="${nativePrefix}/bin"
+      exec="$ldPath/${targetPrefix}ld"
+      wrap ld-solaris ${./ld-solaris-wrapper.sh}
+    '')
+
+    + ''
+      # Create a symlink to as (the assembler).
+      if [ -e $ldPath/${targetPrefix}as ]; then
+        ln -s $ldPath/${targetPrefix}as $out/bin/${targetPrefix}as
+      fi
+
+    '' + (if !useMacosReexportHack then ''
+      wrap ${targetPrefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${targetPrefix}ld}
+    '' else ''
+      ldInner="${targetPrefix}ld-reexport-delegate"
+      wrap "$ldInner" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${targetPrefix}ld}
+      wrap "${targetPrefix}ld" ${./ld-wrapper.sh} "$out/bin/$ldInner"
+      unset ldInner
+    '') + ''
+
+      for variant in ld.gold ld.bfd ld.lld; do
+        local underlying=$ldPath/${targetPrefix}$variant
+        [[ -e "$underlying" ]] || continue
+        wrap ${targetPrefix}$variant ${./ld-wrapper.sh} $underlying
+      done
+
+      set +u
+    '';
+
+  emulation = let
+    fmt =
+      /**/ if targetPlatform.isDarwin  then "mach-o"
+      else if targetPlatform.isWindows then "pe"
+      else "elf" + toString targetPlatform.parsed.cpu.bits;
+    endianPrefix = if targetPlatform.isBigEndian then "big" else "little";
+    arch =
+      /**/ if targetPlatform.isAarch64 then endianPrefix + "aarch64"
+      else if targetPlatform.isArm     then endianPrefix + "arm"
+      else if targetPlatform.isx86_64  then "x86-64"
+      else if targetPlatform.isi686    then "i386"
+      else throw "unknown emulation for platform: " + targetPlatform.config;
+    in targetPlatform.platform.bfdEmulation or (fmt + "-" + arch);
+
+  depsTargetTargetPropagated = extraPackages;
+
+  setupHook = ./setup-hook.sh;
+
+  postFixup =
+    ''
+      set -u
+    ''
+
+    + optionalString (libc != null) (''
+      ##
+      ## General libc support
+      ##
+
+      echo "-L${libc_lib}/lib" > $out/nix-support/libc-ldflags
+
+      echo "${libc_lib}" > $out/nix-support/orig-libc
+      echo "${libc_dev}" > $out/nix-support/orig-libc-dev
+
+      ##
+      ## Dynamic linker support
+      ##
+
+      if [[ -z ''${dynamicLinker+x} ]]; then
+        echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2
+        local dynamicLinker="${libc_lib}/lib/ld*.so.?"
+      fi
+
+      # Expand globs to fill array of options
+      dynamicLinker=($dynamicLinker)
+
+      case ''${#dynamicLinker[@]} in
+        0) echo "No dynamic linker found for platform '${targetPlatform.config}'." >&2;;
+        1) echo "Using dynamic linker: '$dynamicLinker'" >&2;;
+        *) echo "Multiple dynamic linkers found for platform '${targetPlatform.config}'." >&2;;
+      esac
+
+      if [ -n "''${dynamicLinker:-}" ]; then
+        echo $dynamicLinker > $out/nix-support/dynamic-linker
+
+    '' + (if targetPlatform.isDarwin then ''
+        printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook
+    '' else ''
+        if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then
+          echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32
+        fi
+
+        local ldflagsBefore=(-dynamic-linker "$dynamicLinker")
+    '') + ''
+      fi
+
+      # The dynamic linker is passed in `ldflagsBefore' to allow
+      # explicit overrides of the dynamic linker by callers to ld
+      # (the *last* value counts, so ours should come first).
+      printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before
+    '')
+
+    + optionalString (!nativeTools) ''
+
+      ##
+      ## User env support
+      ##
+
+      # Propagate the underling unwrapped bintools so that if you
+      # install the wrapper, you get tools like objdump, the manpages,
+      # etc. as well (same for any binaries of libc).
+      printWords ${bintools_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages
+
+      ##
+      ## Man page and info support
+      ##
+
+      printWords ${bintools.info or ""} \
+        >> $info/nix-support/propagated-build-inputs
+      printWords ${bintools.man or ""} \
+        >> $man/nix-support/propagated-build-inputs
+    ''
+
+    + ''
+
+      ##
+      ## Hardening support
+      ##
+
+      # some linkers on some platforms don't support specific -z flags
+      export hardening_unsupported_flags=""
+      if [[ "$($ldPath/${targetPrefix}ld -z now 2>&1 || true)" =~ un(recognized|known)\ option ]]; then
+        hardening_unsupported_flags+=" bindnow"
+      fi
+      if [[ "$($ldPath/${targetPrefix}ld -z relro 2>&1 || true)" =~ un(recognized|known)\ option ]]; then
+        hardening_unsupported_flags+=" relro"
+      fi
+    ''
+
+    + optionalString hostPlatform.isCygwin ''
+      hardening_unsupported_flags+=" pic"
+    ''
+
+    + ''
+      set +u
+      substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
+      substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh
+      substituteAll ${../cc-wrapper/utils.sh} $out/nix-support/utils.sh
+
+      ##
+      ## Extra custom steps
+      ##
+
+    ''
+    + extraBuildCommands;
+
+  inherit dynamicLinker expand-response-params;
+
+  # for substitution in utils.sh
+  expandResponseParams = "${expand-response-params}/bin/expand-response-params";
+
+  meta =
+    let bintools_ = if bintools != null then bintools else {}; in
+    (if bintools_ ? meta then removeAttrs bintools.meta ["priority"] else {}) //
+    { description =
+        stdenv.lib.attrByPath ["meta" "description"] "System binary utilities" bintools_
+        + " (wrapper script)";
+  } // optionalAttrs useMacosReexportHack {
+    platforms = stdenv.lib.platforms.darwin;
+  };
+}
diff --git a/pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh b/pkgs/build-support/bintools-wrapper/ld-solaris-wrapper.sh
index 5d81e34a047..5d81e34a047 100755..100644
--- a/pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh
+++ b/pkgs/build-support/bintools-wrapper/ld-solaris-wrapper.sh
diff --git a/pkgs/build-support/cc-wrapper/ld-wrapper.sh b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh
index ef618f9a86d..991ed0fe263 100644
--- a/pkgs/build-support/cc-wrapper/ld-wrapper.sh
+++ b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh
@@ -14,12 +14,12 @@ if [ -n "@coreutils_bin@" ]; then
     PATH="@coreutils_bin@/bin"
 fi
 
-if [ -z "${NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then
+source @out@/nix-support/utils.sh
+
+if [ -z "${NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then
     source @out@/nix-support/add-flags.sh
 fi
 
-source @out@/nix-support/utils.sh
-
 
 # Optionally filter out paths not refering to the store.
 expandResponseParams "$@"
@@ -67,6 +67,11 @@ fi
 
 extraAfter+=($NIX_@infixSalt@_LDFLAGS_AFTER)
 
+# Specify the target emulation if nothing is passed in ("-m" overrides this
+# environment variable). Ensures we never blindly fallback on targeting the host
+# platform.
+: ${LDEMULATION:=@emulation@}
+
 # Three tasks:
 #
 #   1. Find all -L... switches for rpath
diff --git a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash b/pkgs/build-support/bintools-wrapper/macos-sierra-reexport-hack.bash
index 20503545333..a0c4e9edfcd 100644
--- a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash
+++ b/pkgs/build-support/bintools-wrapper/macos-sierra-reexport-hack.bash
@@ -81,8 +81,10 @@ else
 
     symbolBloatObject=$outputNameLibless-symbol-hack.o
     if [[ ! -e $symbolBloatObject ]]; then
+        # `-Q` means use GNU Assembler rather than Clang, avoiding an awkward
+        # dependency cycle.
         printf '.private_extern _______child_hack_foo\nchild_hack_foo:\n' \
-            | @targetPrefix@as -- -o $symbolBloatObject
+            | @targetPrefix@as -Q -- -o $symbolBloatObject
     fi
 
     # first half of libs
diff --git a/pkgs/build-support/bintools-wrapper/setup-hook.sh b/pkgs/build-support/bintools-wrapper/setup-hook.sh
new file mode 100644
index 00000000000..48a00b0b9b0
--- /dev/null
+++ b/pkgs/build-support/bintools-wrapper/setup-hook.sh
@@ -0,0 +1,88 @@
+# Binutils Wrapper hygiene
+#
+# See comments in cc-wrapper's setup hook. This works exactly the same way.
+
+set -u
+
+# Skip setup hook if we're neither a build-time dep, nor, temporarily, doing a
+# native compile.
+#
+# TODO(@Ericson2314): No native exception
+[[ -z ${crossConfig-} ]] || (( "$hostOffset" < 0 )) || return 0
+
+bintoolsWrapper_addLDVars () {
+    case $depHostOffset in
+        -1) local role='BUILD_' ;;
+        0)  local role='' ;;
+        1)  local role='TARGET_' ;;
+        *)  echo "bintools-wrapper: Error: Cannot be used with $depHostOffset-offset deps" >2;
+            return 1 ;;
+    esac
+
+    if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then
+        export NIX_${role}LDFLAGS+=" -L$1/lib64"
+    fi
+
+    if [[ -d "$1/lib" ]]; then
+        export NIX_${role}LDFLAGS+=" -L$1/lib"
+    fi
+}
+
+case $targetOffset in
+    -1)
+        export NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_BUILD=1
+        role_pre='BUILD_'
+        role_post='_FOR_BUILD'
+        ;;
+    0)
+        export NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_HOST=1
+        role_pre=''
+        role_post=''
+        ;;
+    1)
+        export NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_TARGET=1
+        role_pre='TARGET_'
+        role_post='_FOR_TARGET'
+        ;;
+    *)
+        echo "cc-wrapper: used as improper sort of dependency" >2;
+        return 1
+        ;;
+esac
+
+addEnvHooks "$targetOffset" bintoolsWrapper_addLDVars
+
+# shellcheck disable=SC2157
+if [ -n "@bintools_bin@" ]; then
+    addToSearchPath _PATH @bintools_bin@/bin
+fi
+
+# shellcheck disable=SC2157
+if [ -n "@libc_bin@" ]; then
+    addToSearchPath _PATH @libc_bin@/bin
+fi
+
+# shellcheck disable=SC2157
+if [ -n "@coreutils_bin@" ]; then
+    addToSearchPath _PATH @coreutils_bin@/bin
+fi
+
+# Export tool environment variables so various build systems use the right ones.
+
+export NIX_${role_pre}BINTOOLS=@out@
+
+for cmd in \
+    ar as ld nm objcopy objdump readelf ranlib strip strings size windres
+do
+    if
+        PATH=$_PATH type -p "@targetPrefix@${cmd}" > /dev/null
+    then
+        upper_case="$(echo "$cmd" | tr "[:lower:]" "[:upper:]")"
+        export "${role_pre}${upper_case}=@targetPrefix@${cmd}";
+        export "${upper_case}${role_post}=@targetPrefix@${cmd}";
+    fi
+done
+
+# No local scope in sourced file
+unset -v role_pre role_post cmd upper_case
+set +u
diff --git a/pkgs/build-support/build-fhs-userenv/chroot-user.rb b/pkgs/build-support/build-fhs-userenv/chroot-user.rb
deleted file mode 100755
index 833aab16ceb..00000000000
--- a/pkgs/build-support/build-fhs-userenv/chroot-user.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/env ruby
-
-# Bind mounts hierarchy: from => to (relative)
-# If 'to' is nil, path will be the same
-mounts = { '/' => 'host',
-           '/proc' => nil,
-           '/sys' => nil,
-           '/nix' => nil,
-           '/tmp' => nil,
-           '/var' => nil,
-           '/run' => nil,
-           '/dev' => nil,
-           '/home' => nil,
-         }
-
-# Propagate environment variables
-envvars = [ 'TERM',
-            'DISPLAY',
-            'XAUTHORITY',
-            'HOME',
-            'XDG_RUNTIME_DIR',
-            'LANG',
-            'SSL_CERT_FILE',
-            'DBUS_SESSION_BUS_ADDRESS',
-          ]
-
-require 'tmpdir'
-require 'fileutils'
-require 'pathname'
-require 'set'
-require 'fiddle'
-
-def write_file(path, str)
-  File.open(path, 'w') { |file| file.write str }
-end
-
-# Import C standard library and several needed calls
-$libc = Fiddle.dlopen nil
-
-def make_fcall(name, args, output)
-  c = Fiddle::Function.new $libc[name], args, output
-  lambda do |*args|
-    ret = c.call *args
-    raise SystemCallError.new Fiddle.last_error if ret < 0
-    return ret
-  end
-end
-
-$fork = make_fcall 'fork', [], Fiddle::TYPE_INT
-
-CLONE_NEWNS   = 0x00020000
-CLONE_NEWUSER = 0x10000000
-$unshare = make_fcall 'unshare', [Fiddle::TYPE_INT], Fiddle::TYPE_INT
-
-MS_BIND = 0x1000
-MS_REC  = 0x4000
-MS_SLAVE  = 0x80000
-$mount = make_fcall 'mount', [Fiddle::TYPE_VOIDP,
-                              Fiddle::TYPE_VOIDP,
-                              Fiddle::TYPE_VOIDP,
-                              Fiddle::TYPE_LONG,
-                              Fiddle::TYPE_VOIDP],
-                    Fiddle::TYPE_INT
-
-# Read command line args
-abort "Usage: chrootenv program args..." unless ARGV.length >= 1
-execp = ARGV
-
-# Populate extra mounts
-if not ENV["CHROOTENV_EXTRA_BINDS"].nil?
-  $stderr.puts "CHROOTENV_EXTRA_BINDS is discussed for deprecation."
-  $stderr.puts "If you have a usecase, please drop a note in issue #16030."
-  $stderr.puts "Notice that we now bind-mount host FS to '/host' and symlink all directories from it to '/' by default."
-
-  for extra in ENV["CHROOTENV_EXTRA_BINDS"].split(':')
-    paths = extra.split('=')
-    if not paths.empty?
-      if paths.size <= 2
-        mounts[paths[0]] = paths[1]
-      else
-        $stderr.puts "Ignoring invalid entry in CHROOTENV_EXTRA_BINDS: #{extra}"
-      end
-    end
-  end
-end
-
-# Set destination paths for mounts
-mounts = mounts.map { |k, v| [k, v.nil? ? k.sub(/^\/*/, '') : v] }.to_h
-
-# Create temporary directory for root and chdir
-root = Dir.mktmpdir 'chrootenv'
-
-# Fork process; we need this to do a proper cleanup because
-# child process will chroot into temporary directory.
-# We use imported 'fork' instead of native to overcome
-# CRuby's meddling with threads; this should be safe because
-# we don't use threads at all.
-$cpid = $fork.call
-if $cpid == 0
-  # If we are root, no need to create new user namespace.
-  if Process.uid == 0
-    $unshare.call CLONE_NEWNS
-    # Mark all mounted filesystems as slave so changes
-    # don't propagate to the parent mount namespace.
-    $mount.call nil, '/', nil, MS_REC | MS_SLAVE, nil
-  else
-    # Save user UID and GID
-    uid = Process.uid
-    gid = Process.gid
-
-    # Create new mount and user namespaces
-    # CLONE_NEWUSER requires a program to be non-threaded, hence
-    # native fork above.
-    $unshare.call CLONE_NEWNS | CLONE_NEWUSER
-
-    # Map users and groups to the parent namespace
-    begin
-      # setgroups is only available since Linux 3.19
-      write_file '/proc/self/setgroups', 'deny'
-    rescue
-    end
-    write_file '/proc/self/uid_map', "#{uid} #{uid} 1"
-    write_file '/proc/self/gid_map', "#{gid} #{gid} 1"
-  end
-
-  # Do rbind mounts.
-  mounts.each do |from, rto|
-    to = "#{root}/#{rto}"
-    FileUtils.mkdir_p to
-    $mount.call from, to, nil, MS_BIND | MS_REC, nil
-  end
-
-  # Don't make root private so privilege drops inside chroot are possible
-  File.chmod(0755, root)
-  # Chroot!
-  Dir.chroot root
-  Dir.chdir '/'
-
-  # New environment
-  new_env = Hash[ envvars.map { |x| [x, ENV[x]] } ]
-
-  # Finally, exec!
-  exec(new_env, *execp, close_others: true, unsetenv_others: true)
-end
-
-# Wait for a child. If we catch a signal, resend it to child and continue
-# waiting.
-def wait_child
-  begin
-    Process.wait
-
-    # Return child's exit code
-    if $?.exited?
-      exit $?.exitstatus
-      else
-      exit 1
-    end
-  rescue SignalException => e
-    Process.kill e.signo, $cpid
-    wait_child
-  end
-end
-
-begin
-  wait_child
-ensure
-  # Cleanup
-  FileUtils.rm_rf root, secure: true
-end
diff --git a/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c b/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c
new file mode 100644
index 00000000000..c03a1710f45
--- /dev/null
+++ b/pkgs/build-support/build-fhs-userenv/chrootenv/chrootenv.c
@@ -0,0 +1,139 @@
+#define _GNU_SOURCE
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <errno.h>
+#include <sched.h>
+#include <unistd.h>
+
+#define fail(s, err) g_error("%s: %s: %s", __func__, s, g_strerror(err))
+#define fail_if(expr)                                                          \
+  if (expr)                                                                    \
+    fail(#expr, errno);
+
+#include <ftw.h>
+
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+const gchar *bind_blacklist[] = {"bin", "etc", "host", "usr", NULL};
+
+void bind_mount(const gchar *source, const gchar *target) {
+  fail_if(g_mkdir(target, 0755));
+  fail_if(mount(source, target, "bind", MS_BIND | MS_REC, NULL));
+}
+
+void bind_mount_host(const gchar *host, const gchar *guest) {
+  g_autofree gchar *point = g_build_filename(guest, "host", NULL);
+  bind_mount(host, point);
+}
+
+void bind_mount_item(const gchar *host, const gchar *guest, const gchar *name) {
+  g_autofree gchar *source = g_build_filename(host, name, NULL);
+  g_autofree gchar *target = g_build_filename(guest, name, NULL);
+
+  if (G_LIKELY(g_file_test(source, G_FILE_TEST_IS_DIR)))
+    bind_mount(source, target);
+}
+
+void bind(const gchar *host, const gchar *guest) {
+  g_autoptr(GError) err = NULL;
+  g_autoptr(GDir) dir = g_dir_open(host, 0, &err);
+
+  if (err != NULL)
+    fail("g_dir_open", errno);
+
+  const gchar *item;
+
+  while (item = g_dir_read_name(dir))
+    if (!g_strv_contains(bind_blacklist, item))
+      bind_mount_item(host, guest, item);
+
+  bind_mount_host(host, guest);
+}
+
+void spit(const char *path, char *fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+
+  FILE *f = g_fopen(path, "w");
+
+  if (f == NULL)
+    fail("g_fopen", errno);
+
+  g_vfprintf(f, fmt, args);
+  fclose(f);
+}
+
+int nftw_remove(const char *path, const struct stat *sb, int type,
+                struct FTW *ftw) {
+  return remove(path);
+}
+
+int main(gint argc, gchar **argv) {
+  const gchar *self = *argv++;
+
+  if (argc < 2) {
+    g_message("%s command [arguments...]", self);
+    return 1;
+  }
+
+  if (g_getenv("NIX_CHROOTENV"))
+    g_warning("chrootenv doesn't stack!");
+  else
+    g_setenv("NIX_CHROOTENV", "", TRUE);
+
+  g_autofree gchar *prefix =
+      g_build_filename(g_get_tmp_dir(), "chrootenvXXXXXX", NULL);
+
+  fail_if(!g_mkdtemp_full(prefix, 0755));
+
+  pid_t cpid = fork();
+
+  if (cpid < 0)
+    fail("fork", errno);
+
+  else if (cpid == 0) {
+    uid_t uid = getuid();
+    gid_t gid = getgid();
+
+    if (unshare(CLONE_NEWNS | CLONE_NEWUSER) < 0) {
+      int unshare_errno = errno;
+
+      g_message("Requires Linux version >= 3.19 built with CONFIG_USER_NS");
+      if (g_file_test("/proc/sys/kernel/unprivileged_userns_clone",
+                      G_FILE_TEST_EXISTS))
+        g_message("Run: sudo sysctl -w kernel.unprivileged_userns_clone=1");
+
+      fail("unshare", unshare_errno);
+    }
+
+    spit("/proc/self/setgroups", "deny");
+    spit("/proc/self/uid_map", "%d %d 1", uid, uid);
+    spit("/proc/self/gid_map", "%d %d 1", gid, gid);
+
+    bind("/", prefix);
+
+    fail_if(chroot(prefix));
+    fail_if(execvp(*argv, argv));
+  }
+
+  else {
+    int status;
+
+    fail_if(waitpid(cpid, &status, 0) != cpid);
+    fail_if(nftw(prefix, nftw_remove, getdtablesize(),
+                 FTW_DEPTH | FTW_MOUNT | FTW_PHYS));
+
+    if (WIFEXITED(status))
+      return WEXITSTATUS(status);
+
+    else if (WIFSIGNALED(status))
+      kill(getpid(), WTERMSIG(status));
+
+    return 1;
+  }
+}
diff --git a/pkgs/build-support/build-fhs-userenv/chrootenv/default.nix b/pkgs/build-support/build-fhs-userenv/chrootenv/default.nix
new file mode 100644
index 00000000000..375c30e1e46
--- /dev/null
+++ b/pkgs/build-support/build-fhs-userenv/chrootenv/default.nix
@@ -0,0 +1,19 @@
+{ stdenv, pkgconfig, glib }:
+
+stdenv.mkDerivation {
+  name = "chrootenv";
+
+  nativeBuildInputs = [ pkgconfig ];
+  buildInputs = [ glib ];
+
+  buildCommand = ''
+    cc ${./chrootenv.c} $(pkg-config --cflags --libs glib-2.0) -o $out
+  '';
+
+  meta = with stdenv.lib; {
+    description = "Setup mount/user namespace for FHS emulation";
+    license = licenses.free;
+    maintainers = with maintainers; [ yegortimoshenko ];
+    platforms = platforms.linux;
+  };
+}
diff --git a/pkgs/build-support/build-fhs-userenv/default.nix b/pkgs/build-support/build-fhs-userenv/default.nix
index d91cdffcf39..219530a67bd 100644
--- a/pkgs/build-support/build-fhs-userenv/default.nix
+++ b/pkgs/build-support/build-fhs-userenv/default.nix
@@ -1,17 +1,13 @@
-{ callPackage, runCommand, lib, writeScript, stdenv, coreutils, ruby }:
+{ callPackage, runCommand, lib, writeScript, stdenv, coreutils }:
 
 let buildFHSEnv = callPackage ./env.nix { }; in
 
-args@{ name, runScript ? "bash", extraBindMounts ? [], extraInstallCommands ? "", meta ? {}, passthru ? {}, ... }:
+args@{ name, runScript ? "bash", extraInstallCommands ? "", meta ? {}, passthru ? {}, ... }:
 
 let
-  env = buildFHSEnv (removeAttrs args [ "runScript" "extraBindMounts" "extraInstallCommands" "meta" "passthru" ]);
+  env = buildFHSEnv (removeAttrs args [ "runScript" "extraInstallCommands" "meta" "passthru" ]);
 
-  # Sandboxing script
-  chroot-user = writeScript "chroot-user" ''
-    #! ${ruby}/bin/ruby
-    ${builtins.readFile ./chroot-user.rb}
-  '';
+  chrootenv = callPackage ./chrootenv {};
 
   init = run: writeScript "${name}-init" ''
     #! ${stdenv.shell}
@@ -32,8 +28,7 @@ in runCommand name {
   passthru = passthru // {
     env = runCommand "${name}-shell-env" {
       shellHook = ''
-        ${lib.optionalString (extraBindMounts != []) ''export CHROOTENV_EXTRA_BINDS="${lib.concatStringsSep ":" extraBindMounts}:$CHROOTENV_EXTRA_BINDS"''}
-        exec ${chroot-user} ${init "bash"} "$(pwd)"
+        exec ${chrootenv} ${init "bash"} "$(pwd)"
       '';
     } ''
       echo >&2 ""
@@ -46,8 +41,7 @@ in runCommand name {
   mkdir -p $out/bin
   cat <<EOF >$out/bin/${name}
   #! ${stdenv.shell}
-  ${lib.optionalString (extraBindMounts != []) ''export CHROOTENV_EXTRA_BINDS="${lib.concatStringsSep ":" extraBindMounts}:$CHROOTENV_EXTRA_BINDS"''}
-  exec ${chroot-user} ${init runScript} "\$(pwd)" "\$@"
+  exec ${chrootenv} ${init runScript} "\$(pwd)" "\$@"
   EOF
   chmod +x $out/bin/${name}
   ${extraInstallCommands}
diff --git a/pkgs/build-support/build-pecl.nix b/pkgs/build-support/build-pecl.nix
index ce948739c32..738dbb56708 100644
--- a/pkgs/build-support/build-pecl.nix
+++ b/pkgs/build-support/build-pecl.nix
@@ -22,6 +22,4 @@ stdenv.mkDerivation (args // {
   makeFlags = [ "EXTENSION_DIR=$(out)/lib/php/extensions" ] ++ makeFlags;
 
   autoreconfPhase = "phpize";
-
-  preConfigure = "touch unix.h";
 })
diff --git a/pkgs/build-support/cc-wrapper/add-flags.sh b/pkgs/build-support/cc-wrapper/add-flags.sh
index 39633fce69a..d8b42244607 100644
--- a/pkgs/build-support/cc-wrapper/add-flags.sh
+++ b/pkgs/build-support/cc-wrapper/add-flags.sh
@@ -4,19 +4,14 @@
 # that case, it is cheaper/better to not repeat this step and let the forked
 # wrapped binary just inherit the work of the forker's wrapper script.
 
-var_templates=(
+var_templates_list=(
     NIX+CFLAGS_COMPILE
     NIX+CFLAGS_LINK
     NIX+CXXSTDLIB_COMPILE
     NIX+CXXSTDLIB_LINK
     NIX+GNATFLAGS_COMPILE
-    NIX+IGNORE_LD_THROUGH_GCC
-    NIX+LDFLAGS
-    NIX+LDFLAGS_BEFORE
-    NIX+LDFLAGS_AFTER
-
-    NIX+SET_BUILD_ID
-    NIX+DONT_SET_RPATH
+)
+var_templates_bool=(
     NIX+ENFORCE_NO_NATIVE
 )
 
@@ -35,17 +30,11 @@ fi
 
 # We need to mangle names for hygiene, but also take parameters/overrides
 # from the environment.
-for var in "${var_templates[@]}"; do
-    outputVar="${var/+/_@infixSalt@_}"
-    export ${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
-        inputVar="${var/+/${infix}}"
-        if [ -v "$inputVar" ]; then
-            export ${outputVar}+="${!outputVar:+ }${!inputVar}"
-        fi
-    done
+for var in "${var_templates_list[@]}"; do
+    mangleVarList "$var" "${role_infixes[@]}"
+done
+for var in "${var_templates_bool[@]}"; do
+    mangleVarBool "$var" "${role_infixes[@]}"
 done
 
 # `-B@out@/bin' forces cc to use ld-wrapper.sh when calling ld.
@@ -66,17 +55,9 @@ if [ -e @out@/nix-support/gnat-cflags ]; then
     NIX_@infixSalt@_GNATFLAGS_COMPILE="$(< @out@/nix-support/gnat-cflags) $NIX_@infixSalt@_GNATFLAGS_COMPILE"
 fi
 
-if [ -e @out@/nix-support/libc-ldflags ]; then
-    NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/libc-ldflags)"
-fi
-
 if [ -e @out@/nix-support/cc-ldflags ]; then
     NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/cc-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"
-fi
-
 # That way forked processes will not extend these environment variables again.
 export NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET=1
diff --git a/pkgs/build-support/cc-wrapper/add-hardening.sh b/pkgs/build-support/cc-wrapper/add-hardening.sh
index b0e39e455ff..a35ff3cb426 100644
--- a/pkgs/build-support/cc-wrapper/add-hardening.sh
+++ b/pkgs/build-support/cc-wrapper/add-hardening.sh
@@ -6,7 +6,6 @@ if [[ -v hardeningEnable[@] ]]; then
   hardeningFlags+=(${hardeningEnable[@]})
 fi
 hardeningCFlags=()
-hardeningLDFlags=()
 
 declare -A hardeningDisableMap
 
@@ -44,7 +43,6 @@ if [[ -z "${hardeningDisableMap[all]:-}" ]]; then
           if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then
             if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling LDFlags -pie >&2; fi
             hardeningCFlags+=('-pie')
-            hardeningLDFlags+=('-pie')
           fi
           ;;
         pic)
@@ -59,14 +57,6 @@ if [[ -z "${hardeningDisableMap[all]:-}" ]]; then
           if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling format >&2; fi
           hardeningCFlags+=('-Wformat' '-Wformat-security' '-Werror=format-security')
           ;;
-        relro)
-          if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling relro >&2; fi
-          hardeningLDFlags+=('-z' 'relro')
-          ;;
-        bindnow)
-          if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling bindnow >&2; fi
-          hardeningLDFlags+=('-z' 'now')
-          ;;
         *)
           # Ignore unsupported. Checked in Nix that at least *some*
           # tool supports each flag.
diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh
index d2cdbf6ce0c..c2e6c140635 100644
--- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh
+++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh
@@ -15,12 +15,18 @@ if [[ -n "@coreutils_bin@" && -n "@gnugrep_bin@" ]]; then
     PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin"
 fi
 
+source @out@/nix-support/utils.sh
+
+# Flirting with a layer violation here.
+if [ -z "${NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; 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
     source @out@/nix-support/add-flags.sh
 fi
 
-source @out@/nix-support/utils.sh
-
 
 # Parse command line options and set several variables.
 # For instance, figure out if linker flags should be passed.
@@ -59,7 +65,8 @@ while (( "$n" < "$nParams" )); do
         cppInclude=0
     elif [ "$p" = -nostdinc++ ]; then
         cppInclude=0
-    elif [ "${p:0:1}" != - ]; then
+    elif [[ "$p" != -?* ]]; then
+        # A dash alone signifies standard input; it is not a flag
         nonFlagArgs=1
     fi
     n+=1
diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix
index b79697b33f0..8de2366ff5f 100644
--- a/pkgs/build-support/cc-wrapper/default.nix
+++ b/pkgs/build-support/cc-wrapper/default.nix
@@ -6,18 +6,17 @@
 # compiler and the linker just "work".
 
 { name ? "", stdenvNoCC, nativeTools, noLibc ? false, nativeLibc, nativePrefix ? ""
-, cc ? null, libc ? null, binutils ? null, coreutils ? null, shell ? stdenvNoCC.shell
+, cc ? null, libc ? null, bintools, coreutils ? null, shell ? stdenvNoCC.shell
 , zlib ? null, extraPackages ? [], extraBuildCommands ? ""
 , isGNU ? false, isClang ? cc.isClang or false, gnugrep ? null
 , buildPackages ? {}
-, useMacosReexportHack ? false
 }:
 
 with stdenvNoCC.lib;
 
 assert nativeTools -> nativePrefix != "";
 assert !nativeTools ->
-  cc != null && binutils != null && coreutils != null && gnugrep != null;
+  cc != null && coreutils != null && gnugrep != null;
 assert !(nativeLibc && noLibc);
 assert (noLibc || nativeLibc) == (libc == null);
 
@@ -42,11 +41,10 @@ let
   libc_dev = if libc == null then null else getDev libc;
   libc_lib = if libc == null then null else getLib libc;
   cc_solib = getLib cc;
-  binutils_bin = if nativeTools then "" else getBin binutils;
   # The wrapper scripts use 'cat' and 'grep', so we may need coreutils.
   coreutils_bin = if nativeTools then "" else getBin coreutils;
 
-  default_cxx_stdlib_compile=optionalString (targetPlatform.isLinux && !(cc.isGNU or false))
+  default_cxx_stdlib_compile = optionalString (targetPlatform.isLinux && !(cc.isGNU or false) && !nativeTools)
     "-isystem $(echo -n ${cc.gcc}/include/c++/*) -isystem $(echo -n ${cc.gcc}/include/c++/*)/$(${cc.gcc}/bin/gcc -dumpmachine)";
 
   dashlessTarget = stdenv.lib.replaceStrings ["-"] ["_"] targetPlatform.config;
@@ -58,21 +56,6 @@ let
   # unstable implementation detail, however.
   infixSalt = dashlessTarget;
 
-  # The dynamic linker has different names on different platforms. This is a
-  # shell glob that ought to match it.
-  dynamicLinker =
-    /**/ if libc == null then null
-    else if targetPlatform.system == "i686-linux"     then "${libc_lib}/lib/ld-linux.so.2"
-    else if targetPlatform.system == "x86_64-linux"   then "${libc_lib}/lib/ld-linux-x86-64.so.2"
-    # ARM with a wildcard, which can be "" or "-armhf".
-    else if (with targetPlatform; isArm && isLinux)   then "${libc_lib}/lib/ld-linux*.so.3"
-    else if targetPlatform.system == "aarch64-linux"  then "${libc_lib}/lib/ld-linux-aarch64.so.1"
-    else if targetPlatform.system == "powerpc-linux"  then "${libc_lib}/lib/ld.so.1"
-    else if targetPlatform.system == "mips64el-linux" then "${libc_lib}/lib/ld.so.1"
-    else if targetPlatform.isDarwin                   then "/usr/lib/dyld"
-    else if stdenv.lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1"
-    else null;
-
   expand-response-params =
     if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null"
     then import ../expand-response-params { inherit (buildPackages) stdenv; }
@@ -80,6 +63,14 @@ let
 
 in
 
+# Ensure bintools matches
+assert libc_bin == bintools.libc_bin;
+assert libc_dev == bintools.libc_dev;
+assert libc_lib == bintools.libc_lib;
+assert nativeTools == bintools.nativeTools;
+assert nativeLibc == bintools.nativeLibc;
+assert nativePrefix == bintools.nativePrefix;
+
 stdenv.mkDerivation {
   name = targetPrefix
     + (if name != "" then name else "${ccName}-wrapper")
@@ -87,8 +78,8 @@ stdenv.mkDerivation {
 
   preferLocalBuild = true;
 
-  inherit cc libc_bin libc_dev libc_lib binutils_bin coreutils_bin;
-  shell = getBin shell + shell.shellPath or "";
+  inherit cc libc_bin libc_dev libc_lib bintools coreutils_bin;
+  shell = getBin shell + stdenv.lib.optionalString (stdenv ? shellPath) stdenv.shellPath;
   gnugrep_bin = if nativeTools then "" else gnugrep;
 
   inherit targetPrefix infixSalt;
@@ -98,20 +89,18 @@ stdenv.mkDerivation {
   passthru = {
     # "cc" is the generic name for a C compiler, but there is no one for package
     # providing the linker and related tools. The two we use now are GNU
-    # Binutils, and Apple's "cctools"; "binutils" as an attempt to find an
+    # Binutils, and Apple's "cctools"; "bintools" as an attempt to find an
     # unused middle-ground name that evokes both.
-    bintools = binutils_bin;
+    inherit bintools;
     inherit libc nativeTools nativeLibc nativePrefix isGNU isClang default_cxx_stdlib_compile;
 
     emacsBufferSetup = pkgs: ''
       ; We should handle propagation here too
-      (mapc (lambda (arg)
-        (when (file-directory-p (concat arg "/include"))
-          (setenv "NIX_${infixSalt}_CFLAGS_COMPILE" (concat (getenv "NIX_${infixSalt}_CFLAGS_COMPILE") " -isystem " arg "/include")))
-        (when (file-directory-p (concat arg "/lib"))
-          (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib")))
-        (when (file-directory-p (concat arg "/lib64"))
-          (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib64")))) '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)}))
+      (mapc
+        (lambda (arg)
+          (when (file-directory-p (concat arg "/include"))
+            (setenv "NIX_${infixSalt}_CFLAGS_COMPILE" (concat (getenv "NIX_${infixSalt}_CFLAGS_COMPILE") " -isystem " arg "/include"))))
+        '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)}))
     '';
   };
 
@@ -141,45 +130,18 @@ stdenv.mkDerivation {
       echo ${if targetPlatform.isDarwin then cc else nativePrefix} > $out/nix-support/orig-cc
 
       ccPath="${if targetPlatform.isDarwin then cc else nativePrefix}/bin"
-      ldPath="${nativePrefix}/bin"
     '' else ''
       echo $cc > $out/nix-support/orig-cc
 
       ccPath="${cc}/bin"
-      ldPath="${binutils_bin}/bin"
-    ''
-
-    + optionalString (targetPlatform.isSunOS && nativePrefix != "") ''
-      # Solaris needs an additional ld wrapper.
-      ldPath="${nativePrefix}/bin"
-      exec="$ldPath/${targetPrefix}ld"
-      wrap ld-solaris ${./ld-solaris-wrapper.sh}
     '')
 
     + ''
-      # Create a symlink to as (the assembler).  This is useful when a
-      # cc-wrapper is installed in a user environment, as it ensures that
-      # the right assembler is called.
-      if [ -e $ldPath/${targetPrefix}as ]; then
-        ln -s $ldPath/${targetPrefix}as $out/bin/${targetPrefix}as
-      fi
-
-    '' + (if !useMacosReexportHack then ''
-      wrap ${targetPrefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${targetPrefix}ld}
-    '' else ''
-      ldInner="${targetPrefix}ld-reexport-delegate"
-      wrap "$ldInner" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${targetPrefix}ld}
-      wrap "${targetPrefix}ld" ${./ld-wrapper.sh} "$out/bin/$ldInner"
-      unset ldInner
-    '') + ''
-
-      if [ -e ${binutils_bin}/bin/${targetPrefix}ld.gold ]; then
-        wrap ${targetPrefix}ld.gold ${./ld-wrapper.sh} ${binutils_bin}/bin/${targetPrefix}ld.gold
-      fi
-
-      if [ -e ${binutils_bin}/bin/ld.bfd ]; then
-        wrap ${targetPrefix}ld.bfd ${./ld-wrapper.sh} ${binutils_bin}/bin/${targetPrefix}ld.bfd
-      fi
+      # Create symlinks to everything in the bintools wrapper.
+      for bbin in $bintools/bin/*; do
+        mkdir -p "$out/bin"
+        ln -s "$bbin" "$out/bin/$(basename $bbin)"
+      done
 
       # We export environment variables pointing to the wrapped nonstandard
       # cmds, lest some lousy configure script use those to guess compiler
@@ -239,16 +201,29 @@ stdenv.mkDerivation {
       ln -s $ccPath/${targetPrefix}ghdl $out/bin/${targetPrefix}ghdl
     '';
 
-  propagatedBuildInputs = extraPackages;
+  propagatedBuildInputs = [ bintools ];
+  depsTargetTargetPropagated = extraPackages;
 
   setupHook = ./setup-hook.sh;
 
   postFixup =
     ''
       set -u
+
+      # Backwards compatability for packages expecting this file, e.g. with
+      # `$NIX_CC/nix-support/dynamic-linker`.
+      #
+      # TODO(@Ericson2314): Remove this after stable release and force
+      # everyone to refer to bintools-wrapper directly.
+      if [[ -f "$bintools/nix-support/dynamic-linker" ]]; then
+        ln -s "$bintools/nix-support/dynamic-linker" "$out/nix-support"
+      fi
+      if [[ -f "$bintools/nix-support/dynamic-linker-m32" ]]; then
+        ln -s "$bintools/nix-support/dynamic-linker-m32" "$out/nix-support"
+      fi
     ''
 
-    + optionalString (libc != null) (''
+    + optionalString (libc != null) ''
       ##
       ## General libc support
       ##
@@ -264,50 +239,11 @@ stdenv.mkDerivation {
       # compile, because it uses "#include_next <limits.h>" to find the
       # limits.h file in ../includes-fixed. To remedy the problem,
       # another -idirafter is necessary to add that directory again.
-      echo "-B${libc_lib}/lib/ -idirafter ${libc_dev}/include -idirafter ${cc}/lib/gcc/*/*/include-fixed" > $out/nix-support/libc-cflags
-
-      echo "-L${libc_lib}/lib" > $out/nix-support/libc-ldflags
+      echo "-B${libc_lib}/lib/ -idirafter ${libc_dev}/include ${optionalString isGNU "-idirafter ${cc}/lib/gcc/*/*/include-fixed"}" > $out/nix-support/libc-cflags
 
       echo "${libc_lib}" > $out/nix-support/orig-libc
       echo "${libc_dev}" > $out/nix-support/orig-libc-dev
-
-      ##
-      ## Dynamic linker support
-      ##
-
-      if [[ -z ''${dynamicLinker+x} ]]; then
-        echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2
-        local dynamicLinker="${libc_lib}/lib/ld*.so.?"
-      fi
-
-      # Expand globs to fill array of options
-      dynamicLinker=($dynamicLinker)
-
-      case ''${#dynamicLinker[@]} in
-        0) echo "No dynamic linker found for platform '${targetPlatform.config}'." >&2;;
-        1) echo "Using dynamic linker: '$dynamicLinker'" >&2;;
-        *) echo "Multiple dynamic linkers found for platform '${targetPlatform.config}'." >&2;;
-      esac
-
-      if [ -n "''${dynamicLinker:-}" ]; then
-        echo $dynamicLinker > $out/nix-support/dynamic-linker
-
-    '' + (if targetPlatform.isDarwin then ''
-        printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook
-    '' else ''
-        if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then
-          echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32
-        fi
-
-        local ldflagsBefore=(-dynamic-linker "$dynamicLinker")
-    '') + ''
-      fi
-
-      # The dynamic linker is passed in `ldflagsBefore' to allow
-      # explicit overrides of the dynamic linker by callers to gcc/ld
-      # (the *last* value counts, so ours should come first).
-      printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before
-    '')
+    ''
 
     + optionalString (!nativeTools) ''
 
@@ -348,7 +284,6 @@ stdenv.mkDerivation {
       # Propagate the wrapped cc so that if you install the wrapper,
       # you get tools like gcov, the manpages, etc. as well (including
       # for binutils and Glibc).
-      printWords ${cc} ${binutils_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages
       printWords ${cc.man or ""}  > $man/nix-support/propagated-user-env-packages
     ''
 
@@ -358,14 +293,7 @@ stdenv.mkDerivation {
       ## Hardening support
       ##
 
-      # some linkers on some platforms don't support specific -z flags
-      export hardening_unsupported_flags=""
-      if [[ "$($ldPath/${targetPrefix}ld -z now 2>&1 || true)" =~ un(recognized|known)\ option ]]; then
-        hardening_unsupported_flags+=" bindnow"
-      fi
-      if [[ "$($ldPath/${targetPrefix}ld -z relro 2>&1 || true)" =~ un(recognized|known)\ option ]]; then
-        hardening_unsupported_flags+=" relro"
-      fi
+      export hardening_unsupported_flags="${builtins.concatStringsSep " " (cc.hardeningUnsupportedFlags or [])}"
     ''
 
     + optionalString hostPlatform.isCygwin ''
@@ -384,7 +312,7 @@ stdenv.mkDerivation {
     ''
     + extraBuildCommands;
 
-  inherit dynamicLinker expand-response-params;
+  inherit expand-response-params;
 
   # for substitution in utils.sh
   expandResponseParams = "${expand-response-params}/bin/expand-response-params";
@@ -395,7 +323,5 @@ stdenv.mkDerivation {
     { description =
         stdenv.lib.attrByPath ["meta" "description"] "System C compiler" cc_
         + " (wrapper script)";
-  } // optionalAttrs useMacosReexportHack {
-    platforms = stdenv.lib.platforms.darwin;
   };
 }
diff --git a/pkgs/build-support/cc-wrapper/gnat-wrapper.sh b/pkgs/build-support/cc-wrapper/gnat-wrapper.sh
index 7a0eb28be63..a86c9fe4ada 100644
--- a/pkgs/build-support/cc-wrapper/gnat-wrapper.sh
+++ b/pkgs/build-support/cc-wrapper/gnat-wrapper.sh
@@ -17,12 +17,12 @@ if [ -n "@coreutils_bin@" ]; then
     PATH="@coreutils_bin@/bin"
 fi
 
+source @out@/nix-support/utils.sh
+
 if [ -z "${NIX_@infixSalt@_GNAT_WRAPPER_FLAGS_SET:-}" ]; then
     source @out@/nix-support/add-flags.sh
 fi
 
-source @out@/nix-support/utils.sh
-
 
 # Figure out if linker flags should be passed.  GCC prints annoying
 # warnings when they are not needed.
@@ -36,10 +36,6 @@ for i in "$@"; do
         dontLink=1
     elif [ "${i:0:1}" != - ]; then
         nonFlagArgs=1
-    elif [ "$i" = -m32 ]; then
-        if [ -e @out@/nix-support/dynamic-linker-m32 ]; then
-            NIX_@infixSalt@_LDFLAGS+=" -dynamic-linker $(< @out@/nix-support/dynamic-linker-m32)"
-        fi
     fi
 done
 
diff --git a/pkgs/build-support/cc-wrapper/setup-hook.sh b/pkgs/build-support/cc-wrapper/setup-hook.sh
index a8f29bd5877..29a7306b9b7 100644
--- a/pkgs/build-support/cc-wrapper/setup-hook.sh
+++ b/pkgs/build-support/cc-wrapper/setup-hook.sh
@@ -54,19 +54,26 @@
 # For more details, read the individual files where the mechanisms used to
 # accomplish this will be individually documented.
 
+set -u
+
+# Skip setup hook if we're neither a build-time dep, nor, temporarily, doing a
+# native compile.
+#
+# TODO(@Ericson2314): No native exception
+[[ -z ${crossConfig-} ]] || (( "$hostOffset" < 0 )) || return 0
 
 # It's fine that any other cc-wrapper will redefine this. Bash functions close
 # over no state, and there's no @-substitutions within, so any redefined
 # function is guaranteed to be exactly the same.
 ccWrapper_addCVars () {
-    # The `depOffset` describes how the platforms of the dependencies are slid
-    # relative to the depending package. It is brought into scope of the
-    # environment hook defined as the role of the dependency being applied.
-    case $depOffset in
+    # The `depHostOffset` describes how the host platform of the dependencies
+    # are slid relative to the depending package. It is brought into scope of
+    # the environment hook defined as the role of the dependency being applied.
+    case $depHostOffset in
         -1) local role='BUILD_' ;;
         0)  local role='' ;;
         1)  local role='TARGET_' ;;
-        *)  echo "cc-wrapper: Error: Cannot be used with $depOffset-offset deps, " >2;
+        *)  echo "cc-wrapper: Error: Cannot be used with $depHostOffset-offset deps" >2;
             return 1 ;;
     esac
 
@@ -74,14 +81,6 @@ ccWrapper_addCVars () {
         export NIX_${role}CFLAGS_COMPILE+=" ${ccIncludeFlag:--isystem} $1/include"
     fi
 
-    if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then
-        export NIX_${role}LDFLAGS+=" -L$1/lib64"
-    fi
-
-    if [[ -d "$1/lib" ]]; then
-        export NIX_${role}LDFLAGS+=" -L$1/lib"
-    fi
-
     if [[ -d "$1/Library/Frameworks" ]]; then
         export NIX_${role}CFLAGS_COMPILE+=" -F$1/Library/Frameworks"
     fi
@@ -95,18 +94,31 @@ ccWrapper_addCVars () {
 #
 # We also need to worry about what role is being added on *this* invocation of
 # setup-hook, which `role` tracks.
-if [ -n "${crossConfig:-}" ]; then
-    export NIX_CC_WRAPPER_@infixSalt@_TARGET_BUILD=1
-    role="BUILD_"
-else
-    export NIX_CC_WRAPPER_@infixSalt@_TARGET_HOST=1
-    role=""
-fi
-
-# Eventually the exact sort of env-hook we create will depend on the role. This
-# is because based on what relative platform we are targeting, we use different
-# dependencies.
-envHooks+=(ccWrapper_addCVars)
+case $targetOffset in
+    -1)
+        export NIX_CC_WRAPPER_@infixSalt@_TARGET_BUILD=1
+        role_pre='BUILD_'
+        role_post='_FOR_BUILD'
+        ;;
+    0)
+        export NIX_CC_WRAPPER_@infixSalt@_TARGET_HOST=1
+        role_pre=''
+        role_post=''
+        ;;
+    1)
+        export NIX_CC_WRAPPER_@infixSalt@_TARGET_TARGET=1
+        role_pre='TARGET_'
+        role_post='_FOR_TARGET'
+        ;;
+    *)
+        echo "cc-wrapper: used as improper sort of dependency" >2;
+        return 1
+        ;;
+esac
+
+# We use the `targetOffset` to choose the right env hook to accumulate the right
+# sort of deps (those with that offset).
+addEnvHooks "$targetOffset" ccWrapper_addCVars
 
 # Note 1: these come *after* $out in the PATH (see setup.sh).
 # Note 2: phase separation makes this look useless to shellcheck.
@@ -117,11 +129,6 @@ if [ -n "@cc@" ]; then
 fi
 
 # shellcheck disable=SC2157
-if [ -n "@binutils_bin@" ]; then
-    addToSearchPath _PATH @binutils_bin@/bin
-fi
-
-# shellcheck disable=SC2157
 if [ -n "@libc_bin@" ]; then
     addToSearchPath _PATH @libc_bin@/bin
 fi
@@ -133,20 +140,13 @@ fi
 
 # Export tool environment variables so various build systems use the right ones.
 
-export NIX_${role}CC=@out@
-
-export ${role}CC=@named_cc@
-export ${role}CXX=@named_cxx@
+export NIX_${role_pre}CC=@out@
 
-for CMD in \
-    ar as nm objcopy ranlib strip strings size ld windres
-do
-    if
-        PATH=$_PATH type -p "@targetPrefix@$CMD" > /dev/null
-    then
-        export "${role}$(echo "$CMD" | tr "[:lower:]" "[:upper:]")=@targetPrefix@${CMD}";
-    fi
-done
+export ${role_pre}CC=@named_cc@
+export ${role_pre}CXX=@named_cxx@
+export CC${role_post}=@named_cc@
+export CXX${role_post}=@named_cxx@
 
 # No local scope in sourced file
-unset role
+unset -v role_pre role_post
+set +u
diff --git a/pkgs/build-support/cc-wrapper/utils.sh b/pkgs/build-support/cc-wrapper/utils.sh
index c43c2e12d74..4b2b1380918 100644
--- a/pkgs/build-support/cc-wrapper/utils.sh
+++ b/pkgs/build-support/cc-wrapper/utils.sh
@@ -1,3 +1,35 @@
+mangleVarList() {
+    local var="$1"
+    shift
+    local -a role_infixes=("$@")
+
+    local outputVar="${var/+/_@infixSalt@_}"
+    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}}"
+        if [ -v "$inputVar" ]; then
+            export ${outputVar}+="${!outputVar:+ }${!inputVar}"
+        fi
+    done
+}
+
+mangleVarBool() {
+    local var="$1"
+    shift
+    local -a role_infixes=("$@")
+
+    local outputVar="${var/+/_@infixSalt@_}"
+    declare -gxi ${outputVar}+=0
+    for infix in "${role_infixes[@]}"; do
+        local inputVar="${var/+/${infix}}"
+        if [ -v "$inputVar" ]; then
+            let "${outputVar} |= ${!inputVar}"
+        fi
+    done
+}
+
 skip () {
     if (( "${NIX_DEBUG:-0}" >= 1 )); then
         echo "skipping impure path $1" >&2
diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix
index b9a33497174..691d4bb74db 100644
--- a/pkgs/build-support/docker/examples.nix
+++ b/pkgs/build-support/docker/examples.nix
@@ -102,7 +102,7 @@ rec {
     ];
   };
 
-  # 5. nix example to play with the container nix store
+  # 6. nix example to play with the container nix store
   # docker run -it --rm nix nix-store -qR $(nix-build '<nixpkgs>' -A nix)
   nix = buildImageWithNixDb {
     name = "nix";
diff --git a/pkgs/build-support/emacs/setup-hook.sh b/pkgs/build-support/emacs/setup-hook.sh
index defef45b55f..e1db3e828fd 100644
--- a/pkgs/build-support/emacs/setup-hook.sh
+++ b/pkgs/build-support/emacs/setup-hook.sh
@@ -4,4 +4,8 @@ addEmacsVars () {
   fi
 }
 
-envHooks+=(addEmacsVars)
+# If this is for a wrapper derivation, emacs and the dependencies are all
+# run-time dependencies. If this is for precompiling packages into bytecode,
+# emacs is a compile-time dependency of the package.
+addEnvHooks "$targetOffset" addEmacsVars
+addEnvHooks "$targetOffset" addEmacsVars
diff --git a/pkgs/build-support/emacs/wrapper.nix b/pkgs/build-support/emacs/wrapper.nix
index bd733f1b9ba..27633c912b2 100644
--- a/pkgs/build-support/emacs/wrapper.nix
+++ b/pkgs/build-support/emacs/wrapper.nix
@@ -55,12 +55,46 @@ stdenv.mkDerivation {
   deps = runCommand "emacs-packages-deps"
    { inherit explicitRequires lndir emacs; }
    ''
+     findInputsOld() {
+         local pkg="$1"; shift
+         local var="$1"; shift
+         local propagatedBuildInputsFiles=("$@")
+
+         # TODO(@Ericson2314): Restore using associative array once Darwin
+         # nix-shell doesn't use impure bash. This should replace the O(n)
+         # case with an O(1) hash map lookup, assuming bash is implemented
+         # well :D.
+         local varSlice="$var[*]"
+         # ''${..-} to hack around old bash empty array problem
+         case "''${!varSlice-}" in
+             *" $pkg "*) return 0 ;;
+         esac
+         unset -v varSlice
+
+         eval "$var"'+=("$pkg")'
+
+         if ! [ -e "$pkg" ]; then
+             echo "build input $pkg does not exist" >&2
+             exit 1
+         fi
+
+         local file
+         for file in "''${propagatedBuildInputsFiles[@]}"; do
+             file="$pkg/nix-support/$file"
+             [[ -f "$file" ]] || continue
+
+             local pkgNext
+             for pkgNext in $(< "$file"); do
+                 findInputsOld "$pkgNext" "$var" "''${propagatedBuildInputsFiles[@]}"
+             done
+         done
+     }
      mkdir -p $out/bin
      mkdir -p $out/share/emacs/site-lisp
 
      local requires
      for pkg in $explicitRequires; do
-       findInputs $pkg requires propagated-user-env-packages
+       findInputsOld $pkg requires propagated-user-env-packages
      done
      # requires now holds all requested packages and their transitive dependencies
 
diff --git a/pkgs/build-support/fetchsvn/builder.sh b/pkgs/build-support/fetchsvn/builder.sh
index 8ed30b37fc7..c386a3f3489 100644
--- a/pkgs/build-support/fetchsvn/builder.sh
+++ b/pkgs/build-support/fetchsvn/builder.sh
@@ -22,11 +22,7 @@ if test -z "$LC_ALL"; then
     export LC_ALL="en_US.UTF-8"
 fi;
 
-# Pipe the "p" character into Subversion to force it to accept the
-# server's certificate.  This is perfectly safe: we don't care
-# whether the server is being spoofed --- only the cryptographic
-# hash of the output matters. Pass in extra p's to handle redirects.
-printf 'p\np\np\n' | svn export --trust-server-cert --non-interactive \
+svn export --trust-server-cert --non-interactive \
     ${ignoreExternals:+--ignore-externals} ${ignoreKeywords:+--ignore-keywords} \
     -r "$rev" "$url" "$out"
 
diff --git a/pkgs/build-support/gcc-wrapper-old/default.nix b/pkgs/build-support/gcc-wrapper-old/default.nix
index ae17989d932..2c2b2c0e1d5 100644
--- a/pkgs/build-support/gcc-wrapper-old/default.nix
+++ b/pkgs/build-support/gcc-wrapper-old/default.nix
@@ -8,7 +8,7 @@
 { name ? "", stdenv, lib, nativeTools, nativeLibc, nativePrefix ? ""
 , gcc ? null, libc ? null, binutils ? null, coreutils ? null, shell ? stdenv.shell
 , zlib ? null
-, hostPlatform, targetPlatform
+, hostPlatform, targetPlatform, targetPackages
 }:
 
 assert nativeTools -> nativePrefix != "";
@@ -58,18 +58,6 @@ stdenv.mkDerivation {
   zlib = if gcc != null && gcc ? langVhdl then zlib else null;
   shell = shell + shell.shellPath or "";
 
-  crossAttrs = {
-    #
-    # This is not the best way to do this. I think the reference should be
-    # the style in the gcc-cross-wrapper, but to keep a stable stdenv now I
-    # do this sufficient if/else.
-    dynamicLinker =
-      (if hostPlatform.arch == "arm" then "ld-linux.so.3" else
-       if hostPlatform.arch == "mips" then "ld.so.1" else
-       if stdenv.lib.hasSuffix "pc-gnu" hostPlatform.config then "ld.so.1" else
-       abort "don't know the name of the dynamic linker for this platform");
-  };
-
   preferLocalBuild = true;
 
   meta =
@@ -83,17 +71,6 @@ stdenv.mkDerivation {
   # The dynamic linker has different names on different platforms.
   dynamicLinker =
     if !nativeLibc then
-      (if targetPlatform.system == "i686-linux"     then "ld-linux.so.2" else
-       if targetPlatform.system == "x86_64-linux"   then "ld-linux-x86-64.so.2" else
-       # ARM with a wildcard, which can be "" or "-armhf".
-       if targetPlatform.isArm                      then "ld-linux*.so.3" else
-       if targetPlatform.system == "aarch64-linux"  then "ld-linux-aarch64.so.1" else
-       if targetPlatform.system == "powerpc-linux"  then "ld.so.1" else
-       if targetPlatform.system == "mips64el-linux" then "ld.so.1" else
-       if targetPlatform.system == "x86_64-darwin"  then "/usr/lib/dyld" else
-       if stdenv.lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1" else
-       builtins.trace
-         "Don't know the name of the dynamic linker for platform ${targetPlatform.config}, so guessing instead."
-         null)
+      targetPackages.stdenv.cc.bintools.dynamicLinker
     else "";
 }
diff --git a/pkgs/build-support/gcc-wrapper-old/setup-hook.sh b/pkgs/build-support/gcc-wrapper-old/setup-hook.sh
index d8bdf858ae5..ad3ffeffbbb 100644
--- a/pkgs/build-support/gcc-wrapper-old/setup-hook.sh
+++ b/pkgs/build-support/gcc-wrapper-old/setup-hook.sh
@@ -1,4 +1,4 @@
-addCVars () {
+gccWrapperOld_addCVars () {
     if test -d $1/include; then
         export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -isystem $1/include"
     fi
@@ -12,7 +12,7 @@ addCVars () {
     fi
 }
 
-envHooks=(${envHooks[@]} addCVars)
+envBuildBuildHooks+=(gccWrapperOld_addCVars)
 
 # Note: these come *after* $out in the PATH (see setup.sh).
 
diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix
index bc777c7e6c7..d13cdd681a2 100644
--- a/pkgs/build-support/libredirect/default.nix
+++ b/pkgs/build-support/libredirect/default.nix
@@ -14,5 +14,11 @@ stdenv.mkDerivation {
 
   meta = {
     platforms = stdenv.lib.platforms.linux;
+    description = "An LD_PRELOAD library to intercept and rewrite the paths in glibc calls";
+    longDescription = ''
+      libredirect is an LD_PRELOAD library to intercept and rewrite the paths in
+      glibc calls based on the value of $NIX_REDIRECTS, a colon-separated list
+      of path prefixes to be rewritten, e.g. "/src=/dst:/usr/=/nix/store/".
+    '';
   };
 }
diff --git a/pkgs/build-support/mkshell/default.nix b/pkgs/build-support/mkshell/default.nix
new file mode 100644
index 00000000000..a98b4affacb
--- /dev/null
+++ b/pkgs/build-support/mkshell/default.nix
@@ -0,0 +1,46 @@
+{ lib, stdenv }:
+
+# A special kind of derivation that is only meant to be consumed by the
+# nix-shell.
+{
+  inputsFrom ? [], # a list of derivations whose inputs will be made available to the environment
+  buildInputs ? [],
+  nativeBuildInputs ? [],
+  propagatedBuildInputs ? [],
+  propagatedNativeBuildInputs ? [],
+  ...
+}@attrs:
+let
+  mergeInputs = name:
+    let
+      op = item: sum: sum ++ item."${name}" or [];
+      nul = [];
+      list = [attrs] ++ inputsFrom;
+    in
+      lib.foldr op nul list;
+
+  rest = builtins.removeAttrs attrs [
+    "inputsFrom"
+    "buildInputs"
+    "nativeBuildInputs"
+    "propagatedBuildInputs"
+    "propagatedNativeBuildInputs"
+  ];
+in
+
+stdenv.mkDerivation ({
+  name = "nix-shell";
+  phases = ["nobuildPhase"];
+
+  buildInputs = mergeInputs "buildInputs";
+  nativeBuildInputs = mergeInputs "nativeBuildInputs";
+  propagatedBuildInputs = mergeInputs "propagatedBuildInputs";
+  propagatedNativeBuildInputs = mergeInputs "propagatedNativeBuildInputs";
+
+  nobuildPhase = ''
+    echo
+    echo "This derivation is not meant to be built, aborting";
+    echo
+    exit 1
+  '';
+} // rest)
diff --git a/pkgs/build-support/release/source-tarball.nix b/pkgs/build-support/release/source-tarball.nix
index 5e178544644..c7129ae83f9 100644
--- a/pkgs/build-support/release/source-tarball.nix
+++ b/pkgs/build-support/release/source-tarball.nix
@@ -123,7 +123,7 @@ stdenv.mkDerivation (
 
       # Tarball builds are generally important, so give them a high
       # default priority.
-      schedulingPriority = "200";
+      schedulingPriority = 200;
     };
   }
 
diff --git a/pkgs/build-support/rust/build-rust-crate.nix b/pkgs/build-support/rust/build-rust-crate.nix
new file mode 100644
index 00000000000..72bb3b80492
--- /dev/null
+++ b/pkgs/build-support/rust/build-rust-crate.nix
@@ -0,0 +1,382 @@
+# Code for buildRustCrate, a Nix function that builds Rust code, just
+# like Cargo, but using Nix instead.
+#
+# This can be useful for deploying packages with NixOps, and to share
+# binary dependencies between projects.
+
+{ lib, buildPlatform, stdenv, defaultCrateOverrides, fetchCrate, ncurses, rustc  }:
+
+let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
+                   dependencies, completeDeps, completeBuildDeps,
+                   crateFeatures, libName, build, release, libPath,
+                   crateType, metadata, crateBin, finalBins,
+                   verbose, colors }:
+
+      let depsDir = lib.concatStringsSep " " dependencies;
+          completeDepsDir = lib.concatStringsSep " " completeDeps;
+          completeBuildDepsDir = lib.concatStringsSep " " completeBuildDeps;
+          makeDeps = dependencies:
+            (lib.concatMapStringsSep " " (dep:
+              let extern = lib.strings.replaceStrings ["-"] ["_"] dep.libName; in
+              (if dep.crateType == "lib" then
+                 " --extern ${extern}=${dep.out}/lib/lib${extern}-${dep.metadata}.rlib"
+              else
+                 " --extern ${extern}=${dep.out}/lib/lib${extern}-${dep.metadata}${buildPlatform.extensions.sharedLibrary}")
+            ) dependencies);
+          deps = makeDeps dependencies;
+          buildDeps = makeDeps buildDependencies;
+          optLevel = if release then 3 else 0;
+          rustcOpts = (if release then "-C opt-level=3" else "-C debuginfo=2");
+          rustcMeta = "-C metadata=${metadata} -C extra-filename=-${metadata}";
+          version_ = lib.splitString "-" crateVersion;
+          versionPre = if lib.tail version_ == [] then "" else builtins.elemAt version_ 1;
+          version = lib.splitString "." (lib.head version_);
+          authors = lib.concatStringsSep ":" crateAuthors;
+      in ''
+      norm=""
+      bold=""
+      green=""
+      boldgreen=""
+      if [[ "${colors}" -eq "always" ]]; then
+        norm="$(printf '\033[0m')" #returns to "normal"
+        bold="$(printf '\033[0;1m')" #set bold
+        green="$(printf '\033[0;32m')" #set green
+        boldgreen="$(printf '\033[0;1;32m')" #set bold, and set green.
+      fi
+
+      echo_build_heading() {
+       start=""
+       end=""
+       if [[ x"${colors}" -eq x"always" ]]; then
+         start="$(printf '\033[0;1;32m')" #set bold, and set green.
+         end="$(printf '\033[0m')" #returns to "normal"
+       fi
+       if (( $# == 1 )); then
+         echo "$start""Building $1""$end"
+       else
+         echo "$start""Building $1 ($2)""$end"
+       fi
+      }
+
+      noisily() {
+        start=""
+        end=""
+        if [[ x"${colors}" -eq x"always" ]]; then
+          start="$(printf '\033[0;1;32m')" #set bold, and set green.
+          end="$(printf '\033[0m')" #returns to "normal"
+        fi
+	${lib.optionalString verbose ''
+            echo -n "$start"Running "$end"
+            echo $@
+	''}
+	$@
+      }
+
+      symlink_dependency() {
+      # $1 is the nix-store path of a dependency
+        i=$1
+	dest=target/deps
+	if [ ! -z $2 ]; then
+           if [ "$2" = "--buildDep" ]; then
+             dest=target/buildDeps
+           fi
+	fi
+        ln -s -f $i/lib/*.rlib $dest #*/
+        ln -s -f $i/lib/*.so $i/lib/*.dylib $dest #*/
+        if [ -e "$i/lib/link" ]; then
+            cat $i/lib/link >> target/link
+            cat $i/lib/link >> target/link.final
+        fi
+        if [ -e $i/env ]; then
+            source $i/env
+        fi
+      }
+
+      build_lib() {
+         lib_src=$1
+         echo_build_heading $lib_src ${libName}
+
+         noisily rustc --crate-name $CRATE_NAME $lib_src --crate-type ${crateType} \
+           ${rustcOpts} ${rustcMeta} ${crateFeatures} --out-dir target/lib \
+           --emit=dep-info,link -L dependency=target/deps ${deps} --cap-lints allow \
+           $BUILD_OUT_DIR $EXTRA_BUILD $EXTRA_FEATURES --color ${colors}
+
+         EXTRA_LIB=" --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-${metadata}.rlib"
+         if [ -e target/deps/lib$CRATE_NAME-${metadata}${buildPlatform.extensions.sharedLibrary} ]; then
+            EXTRA_LIB="$EXTRA_LIB --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-${metadata}${buildPlatform.extensions.sharedLibrary}"
+         fi
+      }
+
+      build_bin() {
+        crate_name=$1
+        crate_name_=$(echo $crate_name | sed -e "s/-/_/g")
+	main_file=""
+	if [[ ! -z $2 ]]; then
+          main_file=$2
+	fi
+	echo_build_heading $@
+	noisily rustc --crate-name $crate_name_ $main_file --crate-type bin ${rustcOpts}\
+          ${crateFeatures} --out-dir target/bin --emit=dep-info,link -L dependency=target/deps \
+          $LINK ${deps}$EXTRA_LIB --cap-lints allow \
+          $BUILD_OUT_DIR $EXTRA_BUILD $EXTRA_FEATURES --color ${colors}
+        if [ "$crate_name_" -ne "$crate_name" ]; then
+          mv target/bin/$crate_name_ target/bin/$crate_name
+        fi
+      }
+
+      runHook preBuild
+      mkdir -p target/{deps,lib,build,buildDeps}
+      chmod uga+w target -R
+      for i in ${completeDepsDir}; do
+        symlink_dependency $i
+      done
+      for i in ${completeBuildDepsDir}; do
+         symlink_dependency $i --buildDep
+      done
+      if [ -e target/link ]; then
+        sort -u target/link > target/link.sorted
+        mv target/link.sorted target/link
+        sort -u target/link.final > target/link.final.sorted
+        mv target/link.final.sorted target/link.final
+        tr '\n' ' ' < target/link > target/link_
+      fi
+      EXTRA_BUILD=""
+      BUILD_OUT_DIR=""
+      export CARGO_PKG_NAME=${crateName}
+      export CARGO_PKG_VERSION=${crateVersion}
+      export CARGO_PKG_AUTHORS="${authors}"
+      export CARGO_CFG_TARGET_ARCH=${buildPlatform.parsed.cpu.name}
+      export CARGO_CFG_TARGET_OS=${buildPlatform.parsed.kernel.name}
+
+      export CARGO_CFG_TARGET_ENV="gnu"
+      export CARGO_MANIFEST_DIR="."
+      export DEBUG="${toString (!release)}"
+      export OPT_LEVEL="${toString optLevel}"
+      export TARGET="${buildPlatform.config}"
+      export HOST="${buildPlatform.config}"
+      export PROFILE=${if release then "release" else "debug"}
+      export OUT_DIR=$(pwd)/target/build/${crateName}.out
+      export CARGO_PKG_VERSION_MAJOR=${builtins.elemAt version 0}
+      export CARGO_PKG_VERSION_MINOR=${builtins.elemAt version 1}
+      export CARGO_PKG_VERSION_PATCH=${builtins.elemAt version 2}
+      if [ -n "${versionPre}" ]; then
+        export CARGO_PKG_VERSION_PRE="${versionPre}"
+      fi
+
+      BUILD=""
+      if [[ ! -z "${build}" ]] ; then
+         BUILD=${build}
+      elif [[ -e "build.rs" ]]; then
+         BUILD="build.rs"
+      fi
+      if [[ ! -z "$BUILD" ]] ; then
+         echo_build_heading "$BUILD" ${libName}
+         mkdir -p target/build/${crateName}
+         EXTRA_BUILD_FLAGS=""
+         if [ -e target/link_ ]; then
+           EXTRA_BUILD_FLAGS=$(cat target/link_)
+         fi
+         if [ -e target/link.build ]; then
+           EXTRA_BUILD_FLAGS="$EXTRA_BUILD_FLAGS $(cat 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 \
+          -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
+         set +e
+         EXTRA_BUILD=$(sed -n "s/^cargo:rustc-flags=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ')
+         EXTRA_FEATURES=$(sed -n "s/^cargo:rustc-cfg=\(.*\)/--cfg \1/p" target/build/${crateName}.opt | tr '\n' ' ')
+         EXTRA_LINK=$(sed -n "s/^cargo:rustc-link-lib=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ')
+         EXTRA_LINK_SEARCH=$(sed -n "s/^cargo:rustc-link-search=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ')
+         CRATENAME=$(echo ${crateName} | sed -e "s/\(.*\)-sys$/\U\1/")
+         grep -P "^cargo:(?!(rustc-|warning=|rerun-if-changed=|rerun-if-env-changed))" target/build/${crateName}.opt \
+           | sed -e "s/cargo:\([^=]*\)=\(.*\)/export DEP_$(echo $CRATENAME)_\U\1\E=\2/" > target/env
+
+         set -e
+         if [ -n "$(ls target/build/${crateName}.out)" ]; then
+
+            if [ -e "${libPath}" ] ; then
+               cp -r target/build/${crateName}.out/* $(dirname ${libPath}) #*/
+            else
+               cp -r target/build/${crateName}.out/* src #*/
+            fi
+         fi
+      fi
+
+      EXTRA_LIB=""
+      CRATE_NAME=$(echo ${libName} | sed -e "s/-/_/g")
+
+      if [ -e target/link_ ]; then
+        EXTRA_BUILD="$(cat target/link_) $EXTRA_BUILD"
+      fi
+
+      if [ -e "${libPath}" ] ; then
+         build_lib ${libPath}
+      elif [ -e src/lib.rs ] ; then
+         build_lib src/lib.rs
+      elif [ -e src/${libName}.rs ] ; then
+         build_lib src/${libName}.rs
+      fi
+
+      echo "$EXTRA_LINK_SEARCH" | while read i; do
+         if [ ! -z "$i" ]; then
+           for lib in $i; do
+             echo "-L $lib" >> target/link
+             L=$(echo $lib | sed -e "s#$(pwd)/target/build#$out/lib#")
+             echo "-L $L" >> target/link.final
+           done
+         fi
+      done
+      echo "$EXTRA_LINK" | while read i; do
+         if [ ! -z "$i" ]; then
+           for lib in $i; do
+             echo "-l $lib" >> target/link
+             echo "-l $lib" >> target/link.final
+           done
+         fi
+      done
+
+      if [ -e target/link ]; then
+         sort -u target/link.final > target/link.final.sorted
+         mv target/link.final.sorted target/link.final
+         sort -u target/link > target/link.sorted
+         mv target/link.sorted target/link
+
+         tr '\n' ' ' < target/link > target/link_
+         LINK=$(cat target/link_)
+       fi
+
+      mkdir -p target/bin
+      echo "${crateBin}" | sed -n 1'p' | tr ',' '\n' | while read BIN; do
+         if [ ! -z "$BIN" ]; then
+           build_bin $BIN
+         fi
+      done
+      ${lib.optionalString (crateBin == "") ''
+        if [[ -e src/main.rs ]]; then
+          build_bin ${crateName} src/main.rs
+        fi
+        for i in src/bin/*.rs; do #*/
+          build_bin "$(basename $i .rs)" "$i"
+        done
+      ''}
+      # Remove object files to avoid "wrong ELF type"
+      find target -type f -name "*.o" -print0 | xargs -0 rm -f
+      runHook postBuild
+    '' + finalBins;
+
+    installCrate = crateName: ''
+      mkdir -p $out
+      if [ -s target/env ]; then
+        cp target/env $out/env
+      fi
+      if [ -s target/link.final ]; then
+        mkdir -p $out/lib
+        cp target/link.final $out/lib/link
+      fi
+      if [ "$(ls -A target/lib)" ]; then
+        mkdir -p $out/lib
+        cp target/lib/* $out/lib #*/
+      fi
+      if [ "$(ls -A target/build)" ]; then # */
+        mkdir -p $out/lib
+        cp -r target/build/* $out/lib # */
+      fi
+      if [ "$(ls -A target/bin)" ]; then
+        mkdir -p $out/bin
+        cp -P target/bin/* $out/bin # */
+      fi
+    '';
+in
+
+crate_: lib.makeOverridable ({ rust, release, verbose, features, buildInputs, crateOverrides }:
+
+let crate = crate_ // (lib.attrByPath [ crate_.crateName ] (attr: {}) crateOverrides crate_);
+    buildInputs_ = buildInputs;
+in
+stdenv.mkDerivation rec {
+
+    inherit (crate) crateName;
+
+    src = if lib.hasAttr "src" crate then
+        crate.src
+      else
+        fetchCrate { inherit (crate) crateName version sha256; };
+    name = "rust_${crate.crateName}-${crate.version}";
+    buildInputs = [ rust ncurses ] ++ (crate.buildInputs or []) ++ buildInputs_;
+    dependencies =
+      builtins.map
+        (dep: dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; })
+        (crate.dependencies or []);
+
+    buildDependencies =
+      builtins.map
+        (dep: dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; })
+        (crate.buildDependencies or []);
+
+    completeDeps = lib.lists.unique (dependencies ++ lib.lists.concatMap (dep: dep.completeDeps) dependencies);
+    completeBuildDeps = lib.lists.unique (
+      buildDependencies
+      ++ lib.lists.concatMap (dep: dep.completeBuildDeps ++ dep.completeDeps) buildDependencies
+    );
+
+    crateFeatures = if crate ? features then
+        lib.concatMapStringsSep " " (f: "--cfg feature=\\\"${f}\\\"") (crate.features ++ features)
+      else "";
+
+    libName = if crate ? libName then crate.libName else crate.crateName;
+    libPath = if crate ? libPath then crate.libPath else "";
+
+    metadata = builtins.substring 0 10 (builtins.hashString "sha256" (crateName + "-" + crateVersion));
+
+    crateBin = if crate ? crateBin then
+       builtins.foldl' (bins: bin:
+          let name =
+              lib.strings.replaceStrings ["-"] ["_"]
+                 (if bin ? name then bin.name else crateName);
+              path = if bin ? path then bin.path else "src/main.rs";
+          in
+          bins + (if bin == "" then "" else ",") + "${name} ${path}"
+
+       ) "" crate.crateBin
+    else "";
+
+    finalBins = if crate ? crateBin then
+       builtins.foldl' (bins: bin:
+          let name = lib.strings.replaceStrings ["-"] ["_"]
+                      (if bin ? name then bin.name else crateName);
+              new_name = if bin ? name then bin.name else crateName;
+          in
+          if name == new_name then bins else
+          (bins + "mv target/bin/${name} target/bin/${new_name};")
+
+       ) "" crate.crateBin
+    else "";
+
+    build = if crate ? build then crate.build else "";
+    crateVersion = crate.version;
+    crateAuthors = if crate ? authors && lib.isList crate.authors then crate.authors else [];
+    crateType =
+      if lib.attrByPath ["procMacro"] false crate then "proc-macro" else
+      if lib.attrByPath ["plugin"] false crate then "dylib" else "lib";
+    colors = lib.attrByPath [ "colors" ] "always" crate;
+    buildPhase = buildCrate {
+      inherit crateName dependencies buildDependencies completeDeps completeBuildDeps
+              crateFeatures libName build release libPath crateType crateVersion
+              crateAuthors metadata crateBin finalBins verbose colors;
+    };
+    installPhase = installCrate crateName;
+
+}) {
+  rust = rustc;
+  release = true;
+  verbose = true;
+  features = [];
+  buildInputs = [];
+  crateOverrides = defaultCrateOverrides;
+}
diff --git a/pkgs/build-support/rust/cargo-vendor.nix b/pkgs/build-support/rust/cargo-vendor.nix
index 6b50f8b83e7..9c379eaa333 100644
--- a/pkgs/build-support/rust/cargo-vendor.nix
+++ b/pkgs/build-support/rust/cargo-vendor.nix
@@ -8,13 +8,15 @@ let
     x86_64-linux = "1hxlavcxy374yypfamlkygjg662lhll8j434qcvdawkvlidg5ii5";
     x86_64-darwin = "1jkvhh710gwjnnjx59kaplx2ncfvkx9agfa76rr94sbjqq4igddm";
   };
-  hash = hashes. ${system} or (throw "missing bootstrap hash for platform ${system}");
+  hash = hashes. ${system} or badSystem;
+
+  badSystem = throw "missing bootstrap hash for platform ${system}";
 
   platforms = {
     x86_64-linux = "x86_64-unknown-linux-musl";
     x86_64-darwin = "x86_64-apple-darwin";
   };
-  platform = platforms . ${system};
+  platform = platforms . ${system} or badSystem;
 
 in stdenv.mkDerivation {
   name = "cargo-vendor-${version}";
diff --git a/pkgs/build-support/rust/carnix.nix b/pkgs/build-support/rust/carnix.nix
new file mode 100644
index 00000000000..adb7139758c
--- /dev/null
+++ b/pkgs/build-support/rust/carnix.nix
@@ -0,0 +1,875 @@
+# Generated by carnix 0.5.0: carnix -o carnix.nix --src ./. Cargo.lock
+{ lib, buildPlatform, buildRustCrate, fetchgit }:
+let kernel = buildPlatform.parsed.kernel.name;
+    abi = buildPlatform.parsed.abi.name;
+    hasFeature = feature:
+      lib.lists.any
+        (originName: feature.${originName})
+        (builtins.attrNames feature);
+
+    hasDefault = feature:
+      let defaultFeatures = builtins.attrNames (feature."default" or {}); in
+      (defaultFeatures == [])
+      || (lib.lists.any (originName: feature."default".${originName}) defaultFeatures);
+
+    mkFeatures = feat: lib.lists.foldl (features: featureName:
+      if featureName != "" && hasFeature feat.${featureName} then
+        [ featureName ] ++ features
+      else
+        features
+    ) (if hasDefault feat then [ "default" ] else []) (builtins.attrNames feat);
+    aho_corasick_0_6_3_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "aho-corasick";
+      version = "0.6.3";
+      authors = [ "Andrew Gallant <jamslam@gmail.com>" ];
+      sha256 = "1cpqzf6acj8lm06z3f1cg41wn6c2n9l3v49nh0dvimv4055qib6k";
+      libName = "aho_corasick";
+      crateBin = [ {  name = "aho-corasick-dot"; } ];
+      inherit dependencies buildDependencies features;
+    };
+    ansi_term_0_10_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "ansi_term";
+      version = "0.10.2";
+      authors = [ "ogham@bsago.me" "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>" "Josh Triplett <josh@joshtriplett.org>" ];
+      sha256 = "07k0hfmlhv43lihyxb9d81l5mq5zlpqvv30dkfd3knmv2ginasn9";
+      inherit dependencies buildDependencies features;
+    };
+    atty_0_2_3_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "atty";
+      version = "0.2.3";
+      authors = [ "softprops <d.tangren@gmail.com>" ];
+      sha256 = "0zl0cjfgarp5y78nd755lpki5bbkj4hgmi88v265m543yg29i88f";
+      inherit dependencies buildDependencies features;
+    };
+    backtrace_0_3_4_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "backtrace";
+      version = "0.3.4";
+      authors = [ "Alex Crichton <alex@alexcrichton.com>" "The Rust Project Developers" ];
+      sha256 = "1caba8w3rqd5ghr88ghyz5wgkf81dgx18bj1llkax6qmianc6gk7";
+      inherit dependencies buildDependencies features;
+    };
+    backtrace_sys_0_1_16_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "backtrace-sys";
+      version = "0.1.16";
+      authors = [ "Alex Crichton <alex@alexcrichton.com>" ];
+      sha256 = "1cn2c8q3dn06crmnk0p62czkngam4l8nf57wy33nz1y5g25pszwy";
+      build = "build.rs";
+      inherit dependencies buildDependencies features;
+    };
+    bitflags_0_7_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "bitflags";
+      version = "0.7.0";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "1hr72xg5slm0z4pxs2hiy4wcyx3jva70h58b7mid8l0a4c8f7gn5";
+      inherit dependencies buildDependencies features;
+    };
+    bitflags_1_0_1_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "bitflags";
+      version = "1.0.1";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "0p4b3nr0s5nda2qmm7xdhnvh4lkqk3xd8l9ffmwbvqw137vx7mj1";
+      inherit dependencies buildDependencies features;
+    };
+    carnix_0_5_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "carnix";
+      version = "0.5.2";
+      authors = [ "pe@pijul.org <pe@pijul.org>" ];
+      sha256 = "1znj345jziksxxkq7ap3i8p3fp3x4794qggac35d0banj7ml3fv8";
+      inherit dependencies buildDependencies features;
+    };
+    cc_1_0_3_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "cc";
+      version = "1.0.3";
+      authors = [ "Alex Crichton <alex@alexcrichton.com>" ];
+      sha256 = "193pwqgh79w6k0k29svyds5nnlrwx44myqyrw605d5jj4yk2zmpr";
+      inherit dependencies buildDependencies features;
+    };
+    cfg_if_0_1_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "cfg-if";
+      version = "0.1.2";
+      authors = [ "Alex Crichton <alex@alexcrichton.com>" ];
+      sha256 = "0x06hvrrqy96m97593823vvxcgvjaxckghwyy2jcyc8qc7c6cyhi";
+      inherit dependencies buildDependencies features;
+    };
+    clap_2_28_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "clap";
+      version = "2.28.0";
+      authors = [ "Kevin K. <kbknapp@gmail.com>" ];
+      sha256 = "0m0rj9xw6mja4gdhqmaldv0q5y5jfsfzbyzfd70mm3857aynq03k";
+      inherit dependencies buildDependencies features;
+    };
+    dbghelp_sys_0_2_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "dbghelp-sys";
+      version = "0.2.0";
+      authors = [ "Peter Atashian <retep998@gmail.com>" ];
+      sha256 = "0ylpi3bbiy233m57hnisn1df1v0lbl7nsxn34b0anzsgg440hqpq";
+      libName = "dbghelp";
+      build = "build.rs";
+      inherit dependencies buildDependencies features;
+    };
+    dtoa_0_4_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "dtoa";
+      version = "0.4.2";
+      authors = [ "David Tolnay <dtolnay@gmail.com>" ];
+      sha256 = "1bxsh6fags7nr36vlz07ik2a1rzyipc8x1y30kjk832hf2pzadmw";
+      inherit dependencies buildDependencies features;
+    };
+    either_1_4_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "either";
+      version = "1.4.0";
+      authors = [ "bluss" ];
+      sha256 = "04kpfd84lvyrkb2z4sljlz2d3d5qczd0sb1yy37fgijq2yx3vb37";
+      inherit dependencies buildDependencies features;
+    };
+    env_logger_0_4_3_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "env_logger";
+      version = "0.4.3";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "0nrx04p4xa86d5kc7aq4fwvipbqji9cmgy449h47nc9f1chafhgg";
+      inherit dependencies buildDependencies features;
+    };
+    error_chain_0_11_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "error-chain";
+      version = "0.11.0";
+      authors = [ "Brian Anderson <banderson@mozilla.com>" "Paul Colomiets <paul@colomiets.name>" "Colin Kiegel <kiegel@gmx.de>" "Yamakaky <yamakaky@yamaworld.fr>" ];
+      sha256 = "19nz17q6dzp0mx2jhh9qbj45gkvvgcl7zq9z2ai5a8ihbisfj6d7";
+      inherit dependencies buildDependencies features;
+    };
+    fuchsia_zircon_0_2_1_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "fuchsia-zircon";
+      version = "0.2.1";
+      authors = [ "Raph Levien <raph@google.com>" ];
+      sha256 = "0yd4rd7ql1vdr349p6vgq2dnwmpylky1kjp8g1zgvp250jxrhddb";
+      inherit dependencies buildDependencies features;
+    };
+    fuchsia_zircon_sys_0_2_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "fuchsia-zircon-sys";
+      version = "0.2.0";
+      authors = [ "Raph Levien <raph@google.com>" ];
+      sha256 = "1yrqsrjwlhl3di6prxf5xmyd82gyjaysldbka5wwk83z11mpqh4w";
+      inherit dependencies buildDependencies features;
+    };
+    itertools_0_7_3_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "itertools";
+      version = "0.7.3";
+      authors = [ "bluss" ];
+      sha256 = "128a69cnmgpj38rs6lcwzya773d2vx7f9y7012iycjf9yi2pyckj";
+      inherit dependencies buildDependencies features;
+    };
+    itoa_0_3_4_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "itoa";
+      version = "0.3.4";
+      authors = [ "David Tolnay <dtolnay@gmail.com>" ];
+      sha256 = "1nfkzz6vrgj0d9l3yzjkkkqzdgs68y294fjdbl7jq118qi8xc9d9";
+      inherit dependencies buildDependencies features;
+    };
+    kernel32_sys_0_2_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "kernel32-sys";
+      version = "0.2.2";
+      authors = [ "Peter Atashian <retep998@gmail.com>" ];
+      sha256 = "1lrw1hbinyvr6cp28g60z97w32w8vsk6pahk64pmrv2fmby8srfj";
+      libName = "kernel32";
+      build = "build.rs";
+      inherit dependencies buildDependencies features;
+    };
+    lazy_static_0_2_11_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "lazy_static";
+      version = "0.2.11";
+      authors = [ "Marvin Löbel <loebel.marvin@gmail.com>" ];
+      sha256 = "1x6871cvpy5b96yv4c7jvpq316fp5d4609s9py7qk6cd6x9k34vm";
+      inherit dependencies buildDependencies features;
+    };
+    libc_0_2_33_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "libc";
+      version = "0.2.33";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "1l7synziccnvarsq2kk22vps720ih6chmn016bhr2bq54hblbnl1";
+      inherit dependencies buildDependencies features;
+    };
+    libsqlite3_sys_0_9_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "libsqlite3-sys";
+      version = "0.9.0";
+      authors = [ "John Gallagher <jgallagher@bignerdranch.com>" ];
+      sha256 = "1pnx3i9h85si6cs4nhazfb28hsvk7dn0arnfvpdzpjdnj9z38q57";
+      build = "build.rs";
+      inherit dependencies buildDependencies features;
+    };
+    linked_hash_map_0_4_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "linked-hash-map";
+      version = "0.4.2";
+      authors = [ "Stepan Koltsov <stepan.koltsov@gmail.com>" "Andrew Paseltiner <apaseltiner@gmail.com>" ];
+      sha256 = "04da208h6jb69f46j37jnvsw2i1wqplglp4d61csqcrhh83avbgl";
+      inherit dependencies buildDependencies features;
+    };
+    log_0_3_8_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "log";
+      version = "0.3.8";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "1c43z4z85sxrsgir4s1hi84558ab5ic7jrn5qgmsiqcv90vvn006";
+      inherit dependencies buildDependencies features;
+    };
+    lru_cache_0_1_1_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "lru-cache";
+      version = "0.1.1";
+      authors = [ "Stepan Koltsov <stepan.koltsov@gmail.com>" ];
+      sha256 = "1hl6kii1g54sq649gnscv858mmw7a02xj081l4vcgvrswdi2z8fw";
+      inherit dependencies buildDependencies features;
+    };
+    memchr_1_0_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "memchr";
+      version = "1.0.2";
+      authors = [ "Andrew Gallant <jamslam@gmail.com>" "bluss" ];
+      sha256 = "0dfb8ifl9nrc9kzgd5z91q6qg87sh285q1ih7xgrsglmqfav9lg7";
+      inherit dependencies buildDependencies features;
+    };
+    nom_3_2_1_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "nom";
+      version = "3.2.1";
+      authors = [ "contact@geoffroycouprie.com" ];
+      sha256 = "1vcllxrz9hdw6j25kn020ka3psz1vkaqh1hm3yfak2240zrxgi07";
+      inherit dependencies buildDependencies features;
+    };
+    num_traits_0_1_40_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "num-traits";
+      version = "0.1.40";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "1fr8ghp4i97q3agki54i0hpmqxv3s65i2mqd1pinc7w7arc3fplw";
+      inherit dependencies buildDependencies features;
+    };
+    pkg_config_0_3_9_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "pkg-config";
+      version = "0.3.9";
+      authors = [ "Alex Crichton <alex@alexcrichton.com>" ];
+      sha256 = "06k8fxgrsrxj8mjpjcq1n7mn2p1shpxif4zg9y5h09c7vy20s146";
+      inherit dependencies buildDependencies features;
+    };
+    quote_0_3_15_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "quote";
+      version = "0.3.15";
+      authors = [ "David Tolnay <dtolnay@gmail.com>" ];
+      sha256 = "09il61jv4kd1360spaj46qwyl21fv1qz18fsv2jra8wdnlgl5jsg";
+      inherit dependencies buildDependencies features;
+    };
+    rand_0_3_18_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "rand";
+      version = "0.3.18";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "15d7c3myn968dzjs0a2pgv58hzdavxnq6swgj032lw2v966ir4xv";
+      inherit dependencies buildDependencies features;
+    };
+    redox_syscall_0_1_32_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "redox_syscall";
+      version = "0.1.32";
+      authors = [ "Jeremy Soller <jackpot51@gmail.com>" ];
+      sha256 = "1axxj8x6ngh6npkzqc5h216fajkcyrdxdgb7m2f0n5xfclbk47fv";
+      libName = "syscall";
+      inherit dependencies buildDependencies features;
+    };
+    redox_termios_0_1_1_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "redox_termios";
+      version = "0.1.1";
+      authors = [ "Jeremy Soller <jackpot51@gmail.com>" ];
+      sha256 = "04s6yyzjca552hdaqlvqhp3vw0zqbc304md5czyd3axh56iry8wh";
+      libPath = "src/lib.rs";
+      inherit dependencies buildDependencies features;
+    };
+    regex_0_2_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "regex";
+      version = "0.2.2";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "1f1zrrynfylg0vcfyfp60bybq4rp5g1yk2k7lc7fyz7mmc7k2qr7";
+      inherit dependencies buildDependencies features;
+    };
+    regex_syntax_0_4_1_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "regex-syntax";
+      version = "0.4.1";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "01yrsm68lj86ad1whgg1z95c2pfsvv58fz8qjcgw7mlszc0c08ls";
+      inherit dependencies buildDependencies features;
+    };
+    rusqlite_0_13_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "rusqlite";
+      version = "0.13.0";
+      authors = [ "John Gallagher <jgallagher@bignerdranch.com>" ];
+      sha256 = "1hj2464ar2y4324sk3jx7m9byhkcp60krrrs1v1i8dlhhlnkb9hc";
+      inherit dependencies buildDependencies features;
+    };
+    rustc_demangle_0_1_5_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "rustc-demangle";
+      version = "0.1.5";
+      authors = [ "Alex Crichton <alex@alexcrichton.com>" ];
+      sha256 = "096kkcx9j747700fhxj1s4rlwkj21pqjmvj64psdj6bakb2q13nc";
+      inherit dependencies buildDependencies features;
+    };
+    serde_1_0_21_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "serde";
+      version = "1.0.21";
+      authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" ];
+      sha256 = "10almq7pvx8s4ryiqk8gf7fj5igl0yq6dcjknwc67rkmxd8q50w3";
+      inherit dependencies buildDependencies features;
+    };
+    serde_derive_1_0_21_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "serde_derive";
+      version = "1.0.21";
+      authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" ];
+      sha256 = "0r20qyimm9scfaz7lc0swnhik9d045zklmbidd0zzpd4b2f3jsqm";
+      procMacro = true;
+      inherit dependencies buildDependencies features;
+    };
+    serde_derive_internals_0_17_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "serde_derive_internals";
+      version = "0.17.0";
+      authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" ];
+      sha256 = "1g1j3v6pj9wbcz3v3w4smjpwrcdwjicmf6yd5cbai04as9iwhw74";
+      inherit dependencies buildDependencies features;
+    };
+    serde_json_1_0_6_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "serde_json";
+      version = "1.0.6";
+      authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" ];
+      sha256 = "1kacyc59splwbg8gr7qs32pp9smgy1khq0ggnv07yxhs7h355vjz";
+      inherit dependencies buildDependencies features;
+    };
+    strsim_0_6_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "strsim";
+      version = "0.6.0";
+      authors = [ "Danny Guo <dannyguo91@gmail.com>" ];
+      sha256 = "1lz85l6y68hr62lv4baww29yy7g8pg20dlr0lbaswxmmcb0wl7gd";
+      inherit dependencies buildDependencies features;
+    };
+    syn_0_11_11_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "syn";
+      version = "0.11.11";
+      authors = [ "David Tolnay <dtolnay@gmail.com>" ];
+      sha256 = "0yw8ng7x1dn5a6ykg0ib49y7r9nhzgpiq2989rqdp7rdz3n85502";
+      inherit dependencies buildDependencies features;
+    };
+    synom_0_11_3_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "synom";
+      version = "0.11.3";
+      authors = [ "David Tolnay <dtolnay@gmail.com>" ];
+      sha256 = "1l6d1s9qjfp6ng2s2z8219igvlv7gyk8gby97sdykqc1r93d8rhc";
+      inherit dependencies buildDependencies features;
+    };
+    tempdir_0_3_5_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "tempdir";
+      version = "0.3.5";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "0rirc5prqppzgd15fm8ayan349lgk2k5iqdkrbwrwrv5pm4znsnz";
+      inherit dependencies buildDependencies features;
+    };
+    termion_1_5_1_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "termion";
+      version = "1.5.1";
+      authors = [ "ticki <Ticki@users.noreply.github.com>" "gycos <alexandre.bury@gmail.com>" "IGI-111 <igi-111@protonmail.com>" ];
+      sha256 = "02gq4vd8iws1f3gjrgrgpajsk2bk43nds5acbbb4s8dvrdvr8nf1";
+      inherit dependencies buildDependencies features;
+    };
+    textwrap_0_9_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "textwrap";
+      version = "0.9.0";
+      authors = [ "Martin Geisler <martin@geisler.net>" ];
+      sha256 = "18jg79ndjlwndz01mlbh82kkr2arqm658yn5kwp65l5n1hz8w4yb";
+      inherit dependencies buildDependencies features;
+    };
+    thread_local_0_3_4_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "thread_local";
+      version = "0.3.4";
+      authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ];
+      sha256 = "1y6cwyhhx2nkz4b3dziwhqdvgq830z8wjp32b40pjd8r0hxqv2jr";
+      inherit dependencies buildDependencies features;
+    };
+    time_0_1_38_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "time";
+      version = "0.1.38";
+      authors = [ "The Rust Project Developers" ];
+      sha256 = "1ws283vvz7c6jfiwn53rmc6kybapr4pjaahfxxrz232b0qzw7gcp";
+      inherit dependencies buildDependencies features;
+    };
+    toml_0_4_5_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "toml";
+      version = "0.4.5";
+      authors = [ "Alex Crichton <alex@alexcrichton.com>" ];
+      sha256 = "06zxqhn3y58yzjfaykhcrvlf7p2dnn54kn3g4apmja3cn5b18lkk";
+      inherit dependencies buildDependencies features;
+    };
+    unicode_width_0_1_4_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "unicode-width";
+      version = "0.1.4";
+      authors = [ "kwantam <kwantam@gmail.com>" ];
+      sha256 = "1rp7a04icn9y5c0lm74nrd4py0rdl0af8bhdwq7g478n1xifpifl";
+      inherit dependencies buildDependencies features;
+    };
+    unicode_xid_0_0_4_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "unicode-xid";
+      version = "0.0.4";
+      authors = [ "erick.tryzelaar <erick.tryzelaar@gmail.com>" "kwantam <kwantam@gmail.com>" ];
+      sha256 = "1dc8wkkcd3s6534s5aw4lbjn8m67flkkbnajp5bl8408wdg8rh9v";
+      inherit dependencies buildDependencies features;
+    };
+    unreachable_1_0_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "unreachable";
+      version = "1.0.0";
+      authors = [ "Jonathan Reem <jonathan.reem@gmail.com>" ];
+      sha256 = "1am8czbk5wwr25gbp2zr007744fxjshhdqjz9liz7wl4pnv3whcf";
+      inherit dependencies buildDependencies features;
+    };
+    utf8_ranges_1_0_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "utf8-ranges";
+      version = "1.0.0";
+      authors = [ "Andrew Gallant <jamslam@gmail.com>" ];
+      sha256 = "0rzmqprwjv9yp1n0qqgahgm24872x6c0xddfym5pfndy7a36vkn0";
+      inherit dependencies buildDependencies features;
+    };
+    vcpkg_0_2_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "vcpkg";
+      version = "0.2.2";
+      authors = [ "Jim McGrath <jimmc2@gmail.com>" ];
+      sha256 = "1fl5j0ksnwrnsrf1b1a9lqbjgnajdipq0030vsbhx81mb7d9478a";
+      inherit dependencies buildDependencies features;
+    };
+    vec_map_0_8_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "vec_map";
+      version = "0.8.0";
+      authors = [ "Alex Crichton <alex@alexcrichton.com>" "Jorge Aparicio <japaricious@gmail.com>" "Alexis Beingessner <a.beingessner@gmail.com>" "Brian Anderson <>" "tbu- <>" "Manish Goregaokar <>" "Aaron Turon <aturon@mozilla.com>" "Adolfo Ochagavía <>" "Niko Matsakis <>" "Steven Fackler <>" "Chase Southwood <csouth3@illinois.edu>" "Eduard Burtescu <>" "Florian Wilkens <>" "Félix Raimundo <>" "Tibor Benke <>" "Markus Siemens <markus@m-siemens.de>" "Josh Branchaud <jbranchaud@gmail.com>" "Huon Wilson <dbau.pp@gmail.com>" "Corey Farwell <coref@rwell.org>" "Aaron Liblong <>" "Nick Cameron <nrc@ncameron.org>" "Patrick Walton <pcwalton@mimiga.net>" "Felix S Klock II <>" "Andrew Paseltiner <apaseltiner@gmail.com>" "Sean McArthur <sean.monstar@gmail.com>" "Vadim Petrochenkov <>" ];
+      sha256 = "07sgxp3cf1a4cxm9n3r27fcvqmld32bl2576mrcahnvm34j11xay";
+      inherit dependencies buildDependencies features;
+    };
+    void_1_0_2_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "void";
+      version = "1.0.2";
+      authors = [ "Jonathan Reem <jonathan.reem@gmail.com>" ];
+      sha256 = "0h1dm0dx8dhf56a83k68mijyxigqhizpskwxfdrs1drwv2cdclv3";
+      inherit dependencies buildDependencies features;
+    };
+    winapi_0_2_8_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "winapi";
+      version = "0.2.8";
+      authors = [ "Peter Atashian <retep998@gmail.com>" ];
+      sha256 = "0a45b58ywf12vb7gvj6h3j264nydynmzyqz8d8rqxsj6icqv82as";
+      inherit dependencies buildDependencies features;
+    };
+    winapi_build_0_1_1_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+      crateName = "winapi-build";
+      version = "0.1.1";
+      authors = [ "Peter Atashian <retep998@gmail.com>" ];
+      sha256 = "1lxlpi87rkhxcwp2ykf1ldw3p108hwm24nywf3jfrvmff4rjhqga";
+      libName = "build";
+      inherit dependencies buildDependencies features;
+    };
+
+in
+rec {
+  aho_corasick_0_6_3 = aho_corasick_0_6_3_ rec {
+    dependencies = [ memchr_1_0_2 ];
+  };
+  memchr_1_0_2_features."default".from_aho_corasick_0_6_3__default = true;
+  ansi_term_0_10_2 = ansi_term_0_10_2_ rec {};
+  atty_0_2_3 = atty_0_2_3_ rec {
+    dependencies = (if kernel == "redox" then [ termion_1_5_1 ] else [])
+      ++ (if (kernel == "linux" || kernel == "darwin") then [ libc_0_2_33 ] else [])
+      ++ (if kernel == "windows" then [ kernel32_sys_0_2_2 winapi_0_2_8 ] else []);
+  };
+  termion_1_5_1_features."default".from_atty_0_2_3__default = true;
+  libc_0_2_33_features."default".from_atty_0_2_3__default = false;
+  kernel32_sys_0_2_2_features."default".from_atty_0_2_3__default = true;
+  winapi_0_2_8_features."default".from_atty_0_2_3__default = true;
+  backtrace_0_3_4 = backtrace_0_3_4_ rec {
+    dependencies = [ cfg_if_0_1_2 rustc_demangle_0_1_5 ]
+      ++ (if (kernel == "linux" || kernel == "darwin") && !(kernel == "fuchsia") && !(kernel == "emscripten") && !(kernel == "darwin") && !(kernel == "ios") then [ backtrace_sys_0_1_16 ]
+      ++ (if lib.lists.any (x: x == "backtrace-sys") features then [backtrace_sys_0_1_16] else []) else [])
+      ++ (if (kernel == "linux" || kernel == "darwin") then [ libc_0_2_33 ] else [])
+      ++ (if kernel == "windows" then [ dbghelp_sys_0_2_0 kernel32_sys_0_2_2 winapi_0_2_8 ]
+      ++ (if lib.lists.any (x: x == "dbghelp-sys") features then [dbghelp_sys_0_2_0] else [])      ++ (if lib.lists.any (x: x == "kernel32-sys") features then [kernel32_sys_0_2_2] else [])      ++ (if lib.lists.any (x: x == "winapi") features then [winapi_0_2_8] else []) else []);
+    features = mkFeatures backtrace_0_3_4_features;
+  };
+  backtrace_0_3_4_features."".self = true;
+  backtrace_0_3_4_features."kernel32-sys".self_dbghelp = hasFeature (backtrace_0_3_4_features."dbghelp" or {});
+  backtrace_0_3_4_features."winapi".self_dbghelp = hasFeature (backtrace_0_3_4_features."dbghelp" or {});
+  backtrace_0_3_4_features."dbghelp-sys".self_dbghelp = hasFeature (backtrace_0_3_4_features."dbghelp" or {});
+  backtrace_0_3_4_features."libunwind".self_default = hasDefault backtrace_0_3_4_features;
+  backtrace_0_3_4_features."libbacktrace".self_default = hasDefault backtrace_0_3_4_features;
+  backtrace_0_3_4_features."coresymbolication".self_default = hasDefault backtrace_0_3_4_features;
+  backtrace_0_3_4_features."dladdr".self_default = hasDefault backtrace_0_3_4_features;
+  backtrace_0_3_4_features."dbghelp".self_default = hasDefault backtrace_0_3_4_features;
+  backtrace_0_3_4_features."addr2line".self_gimli-symbolize = hasFeature (backtrace_0_3_4_features."gimli-symbolize" or {});
+  backtrace_0_3_4_features."findshlibs".self_gimli-symbolize = hasFeature (backtrace_0_3_4_features."gimli-symbolize" or {});
+  backtrace_0_3_4_features."backtrace-sys".self_libbacktrace = hasFeature (backtrace_0_3_4_features."libbacktrace" or {});
+  backtrace_0_3_4_features."rustc-serialize".self_serialize-rustc = hasFeature (backtrace_0_3_4_features."serialize-rustc" or {});
+  backtrace_0_3_4_features."serde".self_serialize-serde = hasFeature (backtrace_0_3_4_features."serialize-serde" or {});
+  backtrace_0_3_4_features."serde_derive".self_serialize-serde = hasFeature (backtrace_0_3_4_features."serialize-serde" or {});
+  addr2line_0_0_0_features."default".from_backtrace_0_3_4__default = true;
+  cfg_if_0_1_2_features."default".from_backtrace_0_3_4__default = true;
+  cpp_demangle_0_0_0_features."default".from_backtrace_0_3_4__default = false;
+  findshlibs_0_0_0_features."default".from_backtrace_0_3_4__default = true;
+  rustc_demangle_0_1_5_features."default".from_backtrace_0_3_4__default = true;
+  rustc_serialize_0_0_0_features."default".from_backtrace_0_3_4__default = true;
+  serde_0_0_0_features."default".from_backtrace_0_3_4__default = true;
+  serde_derive_0_0_0_features."default".from_backtrace_0_3_4__default = true;
+  backtrace_sys_0_1_16_features."default".from_backtrace_0_3_4__default = true;
+  libc_0_2_33_features."default".from_backtrace_0_3_4__default = true;
+  dbghelp_sys_0_2_0_features."default".from_backtrace_0_3_4__default = true;
+  kernel32_sys_0_2_2_features."default".from_backtrace_0_3_4__default = true;
+  winapi_0_2_8_features."default".from_backtrace_0_3_4__default = true;
+  backtrace_sys_0_1_16 = backtrace_sys_0_1_16_ rec {
+    dependencies = [ libc_0_2_33 ];
+    buildDependencies = [ cc_1_0_3 ];
+  };
+  libc_0_2_33_features."default".from_backtrace_sys_0_1_16__default = true;
+  bitflags_0_7_0 = bitflags_0_7_0_ rec {};
+  bitflags_1_0_1 = bitflags_1_0_1_ rec {
+    features = mkFeatures bitflags_1_0_1_features;
+  };
+  bitflags_1_0_1_features."example_generated".self_default = hasDefault bitflags_1_0_1_features;
+  carnix_0_5_2 = carnix_0_5_2_ rec {
+    dependencies = [ clap_2_28_0 env_logger_0_4_3 error_chain_0_11_0 itertools_0_7_3 log_0_3_8 nom_3_2_1 regex_0_2_2 rusqlite_0_13_0 serde_1_0_21 serde_derive_1_0_21 serde_json_1_0_6 tempdir_0_3_5 toml_0_4_5 ];
+  };
+  clap_2_28_0_features."default".from_carnix_0_5_2__default = true;
+  env_logger_0_4_3_features."default".from_carnix_0_5_2__default = true;
+  error_chain_0_11_0_features."default".from_carnix_0_5_2__default = true;
+  itertools_0_7_3_features."default".from_carnix_0_5_2__default = true;
+  log_0_3_8_features."default".from_carnix_0_5_2__default = true;
+  nom_3_2_1_features."default".from_carnix_0_5_2__default = true;
+  regex_0_2_2_features."default".from_carnix_0_5_2__default = true;
+  rusqlite_0_13_0_features."default".from_carnix_0_5_2__default = true;
+  serde_1_0_21_features."default".from_carnix_0_5_2__default = true;
+  serde_derive_1_0_21_features."default".from_carnix_0_5_2__default = true;
+  serde_json_1_0_6_features."default".from_carnix_0_5_2__default = true;
+  tempdir_0_3_5_features."default".from_carnix_0_5_2__default = true;
+  toml_0_4_5_features."default".from_carnix_0_5_2__default = true;
+  cc_1_0_3 = cc_1_0_3_ rec {
+    dependencies = [];
+    features = mkFeatures cc_1_0_3_features;
+  };
+  cc_1_0_3_features."rayon".self_parallel = hasFeature (cc_1_0_3_features."parallel" or {});
+  rayon_0_0_0_features."default".from_cc_1_0_3__default = true;
+  cfg_if_0_1_2 = cfg_if_0_1_2_ rec {};
+  clap_2_28_0 = clap_2_28_0_ rec {
+    dependencies = [ ansi_term_0_10_2 atty_0_2_3 bitflags_1_0_1 strsim_0_6_0 textwrap_0_9_0 unicode_width_0_1_4 vec_map_0_8_0 ]
+      ++ (if lib.lists.any (x: x == "ansi_term") features then [ansi_term_0_10_2] else [])      ++ (if lib.lists.any (x: x == "atty") features then [atty_0_2_3] else [])      ++ (if lib.lists.any (x: x == "strsim") features then [strsim_0_6_0] else [])      ++ (if lib.lists.any (x: x == "vec_map") features then [vec_map_0_8_0] else []);
+    features = mkFeatures clap_2_28_0_features;
+  };
+  clap_2_28_0_features."".self = true;
+  clap_2_28_0_features."ansi_term".self_color = hasFeature (clap_2_28_0_features."color" or {});
+  clap_2_28_0_features."atty".self_color = hasFeature (clap_2_28_0_features."color" or {});
+  clap_2_28_0_features."suggestions".self_default = hasDefault clap_2_28_0_features;
+  clap_2_28_0_features."color".self_default = hasDefault clap_2_28_0_features;
+  clap_2_28_0_features."vec_map".self_default = hasDefault clap_2_28_0_features;
+  clap_2_28_0_features."yaml".self_doc = hasFeature (clap_2_28_0_features."doc" or {});
+  clap_2_28_0_features."clippy".self_lints = hasFeature (clap_2_28_0_features."lints" or {});
+  clap_2_28_0_features."strsim".self_suggestions = hasFeature (clap_2_28_0_features."suggestions" or {});
+  clap_2_28_0_features."term_size".self_wrap_help = hasFeature (clap_2_28_0_features."wrap_help" or {});
+  clap_2_28_0_features."yaml-rust".self_yaml = hasFeature (clap_2_28_0_features."yaml" or {});
+  ansi_term_0_10_2_features."default".from_clap_2_28_0__default = true;
+  atty_0_2_3_features."default".from_clap_2_28_0__default = true;
+  bitflags_1_0_1_features."default".from_clap_2_28_0__default = true;
+  clippy_0_0_0_features."default".from_clap_2_28_0__default = true;
+  strsim_0_6_0_features."default".from_clap_2_28_0__default = true;
+  term_size_0_0_0_features."default".from_clap_2_28_0__default = true;
+  textwrap_0_9_0_features."term_size".from_clap_2_28_0__wrap_help = hasFeature (clap_2_28_0_features."wrap_help" or {});
+  textwrap_0_9_0_features."default".from_clap_2_28_0__default = true;
+  unicode_width_0_1_4_features."default".from_clap_2_28_0__default = true;
+  vec_map_0_8_0_features."default".from_clap_2_28_0__default = true;
+  yaml_rust_0_0_0_features."default".from_clap_2_28_0__default = true;
+  dbghelp_sys_0_2_0 = dbghelp_sys_0_2_0_ rec {
+    dependencies = [ winapi_0_2_8 ];
+    buildDependencies = [ winapi_build_0_1_1 ];
+  };
+  winapi_0_2_8_features."default".from_dbghelp_sys_0_2_0__default = true;
+  dtoa_0_4_2 = dtoa_0_4_2_ rec {};
+  either_1_4_0 = either_1_4_0_ rec {
+    dependencies = [];
+    features = mkFeatures either_1_4_0_features;
+  };
+  either_1_4_0_features."use_std".self_default = hasDefault either_1_4_0_features;
+  serde_0_0_0_features."derive".from_either_1_4_0 = true;
+  serde_0_0_0_features."default".from_either_1_4_0__default = true;
+  env_logger_0_4_3 = env_logger_0_4_3_ rec {
+    dependencies = [ log_0_3_8 regex_0_2_2 ]
+      ++ (if lib.lists.any (x: x == "regex") features then [regex_0_2_2] else []);
+    features = mkFeatures env_logger_0_4_3_features;
+  };
+  env_logger_0_4_3_features."".self = true;
+  env_logger_0_4_3_features."regex".self_default = hasDefault env_logger_0_4_3_features;
+  log_0_3_8_features."default".from_env_logger_0_4_3__default = true;
+  regex_0_2_2_features."default".from_env_logger_0_4_3__default = true;
+  error_chain_0_11_0 = error_chain_0_11_0_ rec {
+    dependencies = [ backtrace_0_3_4 ]
+      ++ (if lib.lists.any (x: x == "backtrace") features then [backtrace_0_3_4] else []);
+    features = mkFeatures error_chain_0_11_0_features;
+  };
+  error_chain_0_11_0_features."".self = true;
+  error_chain_0_11_0_features."backtrace".self_default = hasDefault error_chain_0_11_0_features;
+  error_chain_0_11_0_features."example_generated".self_default = hasDefault error_chain_0_11_0_features;
+  backtrace_0_3_4_features."default".from_error_chain_0_11_0__default = true;
+  fuchsia_zircon_0_2_1 = fuchsia_zircon_0_2_1_ rec {
+    dependencies = [ fuchsia_zircon_sys_0_2_0 ];
+  };
+  fuchsia_zircon_sys_0_2_0_features."default".from_fuchsia_zircon_0_2_1__default = true;
+  fuchsia_zircon_sys_0_2_0 = fuchsia_zircon_sys_0_2_0_ rec {
+    dependencies = [ bitflags_0_7_0 ];
+  };
+  bitflags_0_7_0_features."default".from_fuchsia_zircon_sys_0_2_0__default = true;
+  itertools_0_7_3 = itertools_0_7_3_ rec {
+    dependencies = [ either_1_4_0 ];
+    features = mkFeatures itertools_0_7_3_features;
+  };
+  itertools_0_7_3_features."use_std".self_default = hasDefault itertools_0_7_3_features;
+  either_1_4_0_features."default".from_itertools_0_7_3__default = false;
+  itoa_0_3_4 = itoa_0_3_4_ rec {
+    features = mkFeatures itoa_0_3_4_features;
+  };
+  itoa_0_3_4_features."".self = true;
+  kernel32_sys_0_2_2 = kernel32_sys_0_2_2_ rec {
+    dependencies = [ winapi_0_2_8 ];
+    buildDependencies = [ winapi_build_0_1_1 ];
+  };
+  winapi_0_2_8_features."default".from_kernel32_sys_0_2_2__default = true;
+  lazy_static_0_2_11 = lazy_static_0_2_11_ rec {
+    dependencies = [];
+    features = mkFeatures lazy_static_0_2_11_features;
+  };
+  lazy_static_0_2_11_features."compiletest_rs".self_compiletest = hasFeature (lazy_static_0_2_11_features."compiletest" or {});
+  lazy_static_0_2_11_features."nightly".self_spin_no_std = hasFeature (lazy_static_0_2_11_features."spin_no_std" or {});
+  lazy_static_0_2_11_features."spin".self_spin_no_std = hasFeature (lazy_static_0_2_11_features."spin_no_std" or {});
+  compiletest_rs_0_0_0_features."default".from_lazy_static_0_2_11__default = true;
+  spin_0_0_0_features."default".from_lazy_static_0_2_11__default = true;
+  libc_0_2_33 = libc_0_2_33_ rec {
+    features = mkFeatures libc_0_2_33_features;
+  };
+  libc_0_2_33_features."use_std".self_default = hasDefault libc_0_2_33_features;
+  libsqlite3_sys_0_9_0 = libsqlite3_sys_0_9_0_ rec {
+    dependencies = (if abi == "msvc" then [] else []);
+    buildDependencies = [ pkg_config_0_3_9 ]
+      ++ (if lib.lists.any (x: x == "pkg-config") features then [pkg_config_0_3_9] else []);
+    features = mkFeatures libsqlite3_sys_0_9_0_features;
+  };
+  libsqlite3_sys_0_9_0_features."bindgen".self_buildtime_bindgen = hasFeature (libsqlite3_sys_0_9_0_features."buildtime_bindgen" or {});
+  libsqlite3_sys_0_9_0_features."pkg-config".self_buildtime_bindgen = hasFeature (libsqlite3_sys_0_9_0_features."buildtime_bindgen" or {});
+  libsqlite3_sys_0_9_0_features."vcpkg".self_buildtime_bindgen = hasFeature (libsqlite3_sys_0_9_0_features."buildtime_bindgen" or {});
+  libsqlite3_sys_0_9_0_features."cc".self_bundled = hasFeature (libsqlite3_sys_0_9_0_features."bundled" or {});
+  libsqlite3_sys_0_9_0_features."min_sqlite_version_3_6_8".self_default = hasDefault libsqlite3_sys_0_9_0_features;
+  libsqlite3_sys_0_9_0_features."pkg-config".self_min_sqlite_version_3_6_11 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_6_11" or {});
+  libsqlite3_sys_0_9_0_features."vcpkg".self_min_sqlite_version_3_6_11 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_6_11" or {});
+  libsqlite3_sys_0_9_0_features."pkg-config".self_min_sqlite_version_3_6_23 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_6_23" or {});
+  libsqlite3_sys_0_9_0_features."vcpkg".self_min_sqlite_version_3_6_23 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_6_23" or {});
+  libsqlite3_sys_0_9_0_features."pkg-config".self_min_sqlite_version_3_6_8 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_6_8" or {});
+  libsqlite3_sys_0_9_0_features."vcpkg".self_min_sqlite_version_3_6_8 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_6_8" or {});
+  libsqlite3_sys_0_9_0_features."pkg-config".self_min_sqlite_version_3_7_16 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_7_16" or {});
+  libsqlite3_sys_0_9_0_features."vcpkg".self_min_sqlite_version_3_7_16 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_7_16" or {});
+  libsqlite3_sys_0_9_0_features."pkg-config".self_min_sqlite_version_3_7_3 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_7_3" or {});
+  libsqlite3_sys_0_9_0_features."vcpkg".self_min_sqlite_version_3_7_3 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_7_3" or {});
+  libsqlite3_sys_0_9_0_features."pkg-config".self_min_sqlite_version_3_7_4 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_7_4" or {});
+  libsqlite3_sys_0_9_0_features."vcpkg".self_min_sqlite_version_3_7_4 = hasFeature (libsqlite3_sys_0_9_0_features."min_sqlite_version_3_7_4" or {});
+  linked_hash_map_0_4_2 = linked_hash_map_0_4_2_ rec {
+    dependencies = [];
+    features = mkFeatures linked_hash_map_0_4_2_features;
+  };
+  linked_hash_map_0_4_2_features."heapsize".self_heapsize_impl = hasFeature (linked_hash_map_0_4_2_features."heapsize_impl" or {});
+  linked_hash_map_0_4_2_features."serde".self_serde_impl = hasFeature (linked_hash_map_0_4_2_features."serde_impl" or {});
+  linked_hash_map_0_4_2_features."serde_test".self_serde_impl = hasFeature (linked_hash_map_0_4_2_features."serde_impl" or {});
+  clippy_0_0_0_features."default".from_linked_hash_map_0_4_2__default = true;
+  heapsize_0_0_0_features."default".from_linked_hash_map_0_4_2__default = true;
+  serde_0_0_0_features."default".from_linked_hash_map_0_4_2__default = true;
+  serde_test_0_0_0_features."default".from_linked_hash_map_0_4_2__default = true;
+  log_0_3_8 = log_0_3_8_ rec {
+    features = mkFeatures log_0_3_8_features;
+  };
+  log_0_3_8_features."use_std".self_default = hasDefault log_0_3_8_features;
+  lru_cache_0_1_1 = lru_cache_0_1_1_ rec {
+    dependencies = [ linked_hash_map_0_4_2 ];
+    features = mkFeatures lru_cache_0_1_1_features;
+  };
+  lru_cache_0_1_1_features."heapsize".self_heapsize_impl = hasFeature (lru_cache_0_1_1_features."heapsize_impl" or {});
+  heapsize_0_0_0_features."default".from_lru_cache_0_1_1__default = true;
+  linked_hash_map_0_4_2_features."heapsize_impl".from_lru_cache_0_1_1__heapsize_impl = hasFeature (lru_cache_0_1_1_features."heapsize_impl" or {});
+  linked_hash_map_0_4_2_features."default".from_lru_cache_0_1_1__default = true;
+  memchr_1_0_2 = memchr_1_0_2_ rec {
+    dependencies = [ libc_0_2_33 ]
+      ++ (if lib.lists.any (x: x == "libc") features then [libc_0_2_33] else []);
+    features = mkFeatures memchr_1_0_2_features;
+  };
+  memchr_1_0_2_features."".self = true;
+  memchr_1_0_2_features."use_std".self_default = hasDefault memchr_1_0_2_features;
+  memchr_1_0_2_features."libc".self_default = hasDefault memchr_1_0_2_features;
+  memchr_1_0_2_features."libc".self_use_std = hasFeature (memchr_1_0_2_features."use_std" or {});
+  libc_0_2_33_features."use_std".from_memchr_1_0_2__use_std = hasFeature (memchr_1_0_2_features."use_std" or {});
+  libc_0_2_33_features."default".from_memchr_1_0_2__default = false;
+  nom_3_2_1 = nom_3_2_1_ rec {
+    dependencies = [ memchr_1_0_2 ];
+    features = mkFeatures nom_3_2_1_features;
+  };
+  nom_3_2_1_features."std".self_default = hasDefault nom_3_2_1_features;
+  nom_3_2_1_features."stream".self_default = hasDefault nom_3_2_1_features;
+  nom_3_2_1_features."compiler_error".self_nightly = hasFeature (nom_3_2_1_features."nightly" or {});
+  nom_3_2_1_features."regex".self_regexp = hasFeature (nom_3_2_1_features."regexp" or {});
+  nom_3_2_1_features."regexp".self_regexp_macros = hasFeature (nom_3_2_1_features."regexp_macros" or {});
+  nom_3_2_1_features."lazy_static".self_regexp_macros = hasFeature (nom_3_2_1_features."regexp_macros" or {});
+  compiler_error_0_0_0_features."default".from_nom_3_2_1__default = true;
+  lazy_static_0_0_0_features."default".from_nom_3_2_1__default = true;
+  memchr_1_0_2_features."use_std".from_nom_3_2_1__std = hasFeature (nom_3_2_1_features."std" or {});
+  memchr_1_0_2_features."default".from_nom_3_2_1__default = false;
+  regex_0_0_0_features."default".from_nom_3_2_1__default = true;
+  num_traits_0_1_40 = num_traits_0_1_40_ rec {};
+  pkg_config_0_3_9 = pkg_config_0_3_9_ rec {};
+  quote_0_3_15 = quote_0_3_15_ rec {};
+  rand_0_3_18 = rand_0_3_18_ rec {
+    dependencies = [ libc_0_2_33 ]
+      ++ (if kernel == "fuchsia" then [ fuchsia_zircon_0_2_1 ] else []);
+    features = mkFeatures rand_0_3_18_features;
+  };
+  rand_0_3_18_features."i128_support".self_nightly = hasFeature (rand_0_3_18_features."nightly" or {});
+  libc_0_2_33_features."default".from_rand_0_3_18__default = true;
+  fuchsia_zircon_0_2_1_features."default".from_rand_0_3_18__default = true;
+  redox_syscall_0_1_32 = redox_syscall_0_1_32_ rec {};
+  redox_termios_0_1_1 = redox_termios_0_1_1_ rec {
+    dependencies = [ redox_syscall_0_1_32 ];
+  };
+  redox_syscall_0_1_32_features."default".from_redox_termios_0_1_1__default = true;
+  regex_0_2_2 = regex_0_2_2_ rec {
+    dependencies = [ aho_corasick_0_6_3 memchr_1_0_2 regex_syntax_0_4_1 thread_local_0_3_4 utf8_ranges_1_0_0 ];
+    features = mkFeatures regex_0_2_2_features;
+  };
+  regex_0_2_2_features."simd".self_simd-accel = hasFeature (regex_0_2_2_features."simd-accel" or {});
+  aho_corasick_0_6_3_features."default".from_regex_0_2_2__default = true;
+  memchr_1_0_2_features."default".from_regex_0_2_2__default = true;
+  regex_syntax_0_4_1_features."default".from_regex_0_2_2__default = true;
+  simd_0_0_0_features."default".from_regex_0_2_2__default = true;
+  thread_local_0_3_4_features."default".from_regex_0_2_2__default = true;
+  utf8_ranges_1_0_0_features."default".from_regex_0_2_2__default = true;
+  regex_syntax_0_4_1 = regex_syntax_0_4_1_ rec {};
+  rusqlite_0_13_0 = rusqlite_0_13_0_ rec {
+    dependencies = [ bitflags_1_0_1 libsqlite3_sys_0_9_0 lru_cache_0_1_1 time_0_1_38 ];
+    features = mkFeatures rusqlite_0_13_0_features;
+  };
+  rusqlite_0_13_0_features."".self = true;
+  bitflags_1_0_1_features."default".from_rusqlite_0_13_0__default = true;
+  chrono_0_0_0_features."default".from_rusqlite_0_13_0__default = true;
+  libsqlite3_sys_0_9_0_features."min_sqlite_version_3_6_11".from_rusqlite_0_13_0__backup = hasFeature (rusqlite_0_13_0_features."backup" or {});
+  libsqlite3_sys_0_9_0_features."min_sqlite_version_3_7_4".from_rusqlite_0_13_0__blob = hasFeature (rusqlite_0_13_0_features."blob" or {});
+  libsqlite3_sys_0_9_0_features."buildtime_bindgen".from_rusqlite_0_13_0__buildtime_bindgen = hasFeature (rusqlite_0_13_0_features."buildtime_bindgen" or {});
+  libsqlite3_sys_0_9_0_features."bundled".from_rusqlite_0_13_0__bundled = hasFeature (rusqlite_0_13_0_features."bundled" or {});
+  libsqlite3_sys_0_9_0_features."min_sqlite_version_3_7_3".from_rusqlite_0_13_0__functions = hasFeature (rusqlite_0_13_0_features."functions" or {});
+  libsqlite3_sys_0_9_0_features."sqlcipher".from_rusqlite_0_13_0__sqlcipher = hasFeature (rusqlite_0_13_0_features."sqlcipher" or {});
+  libsqlite3_sys_0_9_0_features."min_sqlite_version_3_6_23".from_rusqlite_0_13_0__trace = hasFeature (rusqlite_0_13_0_features."trace" or {});
+  libsqlite3_sys_0_9_0_features."default".from_rusqlite_0_13_0__default = true;
+  lru_cache_0_1_1_features."default".from_rusqlite_0_13_0__default = true;
+  serde_json_0_0_0_features."default".from_rusqlite_0_13_0__default = true;
+  time_0_1_38_features."default".from_rusqlite_0_13_0__default = true;
+  rustc_demangle_0_1_5 = rustc_demangle_0_1_5_ rec {};
+  serde_1_0_21 = serde_1_0_21_ rec {
+    dependencies = [];
+    features = mkFeatures serde_1_0_21_features;
+  };
+  serde_1_0_21_features."unstable".self_alloc = hasFeature (serde_1_0_21_features."alloc" or {});
+  serde_1_0_21_features."std".self_default = hasDefault serde_1_0_21_features;
+  serde_1_0_21_features."serde_derive".self_derive = hasFeature (serde_1_0_21_features."derive" or {});
+  serde_1_0_21_features."serde_derive".self_playground = hasFeature (serde_1_0_21_features."playground" or {});
+  serde_derive_0_0_0_features."default".from_serde_1_0_21__default = true;
+  serde_derive_1_0_21 = serde_derive_1_0_21_ rec {
+    dependencies = [ quote_0_3_15 serde_derive_internals_0_17_0 syn_0_11_11 ];
+  };
+  quote_0_3_15_features."default".from_serde_derive_1_0_21__default = true;
+  serde_derive_internals_0_17_0_features."default".from_serde_derive_1_0_21__default = false;
+  syn_0_11_11_features."visit".from_serde_derive_1_0_21 = true;
+  syn_0_11_11_features."default".from_serde_derive_1_0_21__default = true;
+  serde_derive_internals_0_17_0 = serde_derive_internals_0_17_0_ rec {
+    dependencies = [ syn_0_11_11 synom_0_11_3 ];
+  };
+  syn_0_11_11_features."parsing".from_serde_derive_internals_0_17_0 = true;
+  syn_0_11_11_features."default".from_serde_derive_internals_0_17_0__default = false;
+  synom_0_11_3_features."default".from_serde_derive_internals_0_17_0__default = true;
+  serde_json_1_0_6 = serde_json_1_0_6_ rec {
+    dependencies = [ dtoa_0_4_2 itoa_0_3_4 num_traits_0_1_40 serde_1_0_21 ];
+    features = mkFeatures serde_json_1_0_6_features;
+  };
+  serde_json_1_0_6_features."linked-hash-map".self_preserve_order = hasFeature (serde_json_1_0_6_features."preserve_order" or {});
+  dtoa_0_4_2_features."default".from_serde_json_1_0_6__default = true;
+  itoa_0_3_4_features."default".from_serde_json_1_0_6__default = true;
+  linked_hash_map_0_0_0_features."default".from_serde_json_1_0_6__default = true;
+  num_traits_0_1_40_features."default".from_serde_json_1_0_6__default = true;
+  serde_1_0_21_features."default".from_serde_json_1_0_6__default = true;
+  strsim_0_6_0 = strsim_0_6_0_ rec {};
+  syn_0_11_11 = syn_0_11_11_ rec {
+    dependencies = [ quote_0_3_15 synom_0_11_3 unicode_xid_0_0_4 ]
+      ++ (if lib.lists.any (x: x == "quote") features then [quote_0_3_15] else [])      ++ (if lib.lists.any (x: x == "synom") features then [synom_0_11_3] else [])      ++ (if lib.lists.any (x: x == "unicode-xid") features then [unicode_xid_0_0_4] else []);
+    features = mkFeatures syn_0_11_11_features;
+  };
+  syn_0_11_11_features."".self = true;
+  syn_0_11_11_features."parsing".self_default = hasDefault syn_0_11_11_features;
+  syn_0_11_11_features."printing".self_default = hasDefault syn_0_11_11_features;
+  syn_0_11_11_features."unicode-xid".self_parsing = hasFeature (syn_0_11_11_features."parsing" or {});
+  syn_0_11_11_features."synom".self_parsing = hasFeature (syn_0_11_11_features."parsing" or {});
+  syn_0_11_11_features."quote".self_printing = hasFeature (syn_0_11_11_features."printing" or {});
+  quote_0_3_15_features."default".from_syn_0_11_11__default = true;
+  synom_0_11_3_features."default".from_syn_0_11_11__default = true;
+  unicode_xid_0_0_4_features."default".from_syn_0_11_11__default = true;
+  synom_0_11_3 = synom_0_11_3_ rec {
+    dependencies = [ unicode_xid_0_0_4 ];
+  };
+  unicode_xid_0_0_4_features."default".from_synom_0_11_3__default = true;
+  tempdir_0_3_5 = tempdir_0_3_5_ rec {
+    dependencies = [ rand_0_3_18 ];
+  };
+  rand_0_3_18_features."default".from_tempdir_0_3_5__default = true;
+  termion_1_5_1 = termion_1_5_1_ rec {
+    dependencies = (if !(kernel == "redox") then [ libc_0_2_33 ] else [])
+      ++ (if kernel == "redox" then [ redox_syscall_0_1_32 redox_termios_0_1_1 ] else []);
+  };
+  libc_0_2_33_features."default".from_termion_1_5_1__default = true;
+  redox_syscall_0_1_32_features."default".from_termion_1_5_1__default = true;
+  redox_termios_0_1_1_features."default".from_termion_1_5_1__default = true;
+  textwrap_0_9_0 = textwrap_0_9_0_ rec {
+    dependencies = [ unicode_width_0_1_4 ];
+  };
+  hyphenation_0_0_0_features."default".from_textwrap_0_9_0__default = true;
+  term_size_0_0_0_features."default".from_textwrap_0_9_0__default = true;
+  unicode_width_0_1_4_features."default".from_textwrap_0_9_0__default = true;
+  thread_local_0_3_4 = thread_local_0_3_4_ rec {
+    dependencies = [ lazy_static_0_2_11 unreachable_1_0_0 ];
+  };
+  lazy_static_0_2_11_features."default".from_thread_local_0_3_4__default = true;
+  unreachable_1_0_0_features."default".from_thread_local_0_3_4__default = true;
+  time_0_1_38 = time_0_1_38_ rec {
+    dependencies = [ libc_0_2_33 ]
+      ++ (if kernel == "redox" then [ redox_syscall_0_1_32 ] else [])
+      ++ (if kernel == "windows" then [ kernel32_sys_0_2_2 winapi_0_2_8 ] else []);
+  };
+  libc_0_2_33_features."default".from_time_0_1_38__default = true;
+  rustc_serialize_0_0_0_features."default".from_time_0_1_38__default = true;
+  redox_syscall_0_1_32_features."default".from_time_0_1_38__default = true;
+  kernel32_sys_0_2_2_features."default".from_time_0_1_38__default = true;
+  winapi_0_2_8_features."default".from_time_0_1_38__default = true;
+  toml_0_4_5 = toml_0_4_5_ rec {
+    dependencies = [ serde_1_0_21 ];
+  };
+  serde_1_0_21_features."default".from_toml_0_4_5__default = true;
+  unicode_width_0_1_4 = unicode_width_0_1_4_ rec {
+    features = mkFeatures unicode_width_0_1_4_features;
+  };
+  unicode_width_0_1_4_features."".self = true;
+  unicode_xid_0_0_4 = unicode_xid_0_0_4_ rec {
+    features = mkFeatures unicode_xid_0_0_4_features;
+  };
+  unicode_xid_0_0_4_features."".self = true;
+  unreachable_1_0_0 = unreachable_1_0_0_ rec {
+    dependencies = [ void_1_0_2 ];
+  };
+  void_1_0_2_features."default".from_unreachable_1_0_0__default = false;
+  utf8_ranges_1_0_0 = utf8_ranges_1_0_0_ rec {};
+  vcpkg_0_2_2 = vcpkg_0_2_2_ rec {};
+  vec_map_0_8_0 = vec_map_0_8_0_ rec {
+    dependencies = [];
+    features = mkFeatures vec_map_0_8_0_features;
+  };
+  vec_map_0_8_0_features."serde".self_eders = hasFeature (vec_map_0_8_0_features."eders" or {});
+  vec_map_0_8_0_features."serde_derive".self_eders = hasFeature (vec_map_0_8_0_features."eders" or {});
+  serde_0_0_0_features."default".from_vec_map_0_8_0__default = true;
+  serde_derive_0_0_0_features."default".from_vec_map_0_8_0__default = true;
+  void_1_0_2 = void_1_0_2_ rec {
+    features = mkFeatures void_1_0_2_features;
+  };
+  void_1_0_2_features."std".self_default = hasDefault void_1_0_2_features;
+  winapi_0_2_8 = winapi_0_2_8_ rec {};
+  winapi_build_0_1_1 = winapi_build_0_1_1_ rec {};
+}
diff --git a/pkgs/build-support/rust/default-crate-overrides.nix b/pkgs/build-support/rust/default-crate-overrides.nix
new file mode 100644
index 00000000000..c074d46a7f7
--- /dev/null
+++ b/pkgs/build-support/rust/default-crate-overrides.nix
@@ -0,0 +1,10 @@
+{ pkgconfig, sqlite, openssl, ... }:
+
+{
+  libsqlite3-sys = attrs: {
+    buildInputs = [ pkgconfig sqlite ];
+  };
+  openssl-sys = attrs: {
+    buildInputs = [ pkgconfig openssl ];
+  };
+}
diff --git a/pkgs/build-support/rust/fetchcrate.nix b/pkgs/build-support/rust/fetchcrate.nix
new file mode 100644
index 00000000000..95dfd38b12a
--- /dev/null
+++ b/pkgs/build-support/rust/fetchcrate.nix
@@ -0,0 +1,35 @@
+{ lib, fetchurl, unzip }:
+
+{ crateName
+, version
+, sha256
+, ... } @ args:
+
+lib.overrideDerivation (fetchurl ({
+
+  name = "${crateName}-${version}.tar.gz";
+  url = "https://crates.io/api/v1/crates/${crateName}/${version}/download";
+  recursiveHash = true;
+
+  downloadToTemp = true;
+
+  postFetch =
+    ''
+      export PATH=${unzip}/bin:$PATH
+
+      unpackDir="$TMPDIR/unpack"
+      mkdir "$unpackDir"
+      cd "$unpackDir"
+
+      renamed="$TMPDIR/${crateName}-${version}.tar.gz"
+      mv "$downloadedFile" "$renamed"
+      unpackFile "$renamed"
+      fn=$(cd "$unpackDir" && echo *)
+      if [ -f "$unpackDir/$fn" ]; then
+        mkdir $out
+      fi
+      mv "$unpackDir/$fn" "$out"
+    '';
+} // removeAttrs args [ "crateName" "version" ]))
+# Hackety-hack: we actually need unzip hooks, too
+(x: {nativeBuildInputs = x.nativeBuildInputs++ [unzip];})
diff --git a/pkgs/build-support/setup-hooks/find-xml-catalogs.sh b/pkgs/build-support/setup-hooks/find-xml-catalogs.sh
index b742d5a8ffd..85364a61f61 100644
--- a/pkgs/build-support/setup-hooks/find-xml-catalogs.sh
+++ b/pkgs/build-support/setup-hooks/find-xml-catalogs.sh
@@ -18,5 +18,5 @@ if [ -z "$libxmlHookDone" ]; then
     # xmllint and xsltproc from looking in /etc/xml/catalog.
     export XML_CATALOG_FILES
     if [ -z "$XML_CATALOG_FILES" ]; then XML_CATALOG_FILES=" "; fi
-    envHooks+=(addXMLCatalogs)
+    addEnvHooks "$hostOffset" addXMLCatalogs
 fi
diff --git a/pkgs/build-support/setup-hooks/ld-is-cc-hook.sh b/pkgs/build-support/setup-hooks/ld-is-cc-hook.sh
new file mode 100644
index 00000000000..b53e184b095
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/ld-is-cc-hook.sh
@@ -0,0 +1,5 @@
+ld-is-cc-hook() {
+    LD=$CC
+}
+
+preConfigureHooks+=(ld-is-cc-hook)
diff --git a/pkgs/build-support/setup-hooks/separate-debug-info.sh b/pkgs/build-support/setup-hooks/separate-debug-info.sh
index c90d2cd5201..19dbb10d18e 100644
--- a/pkgs/build-support/setup-hooks/separate-debug-info.sh
+++ b/pkgs/build-support/setup-hooks/separate-debug-info.sh
@@ -19,7 +19,7 @@ _separateDebugInfo() {
         if ! isELF "$i"; then continue; fi
 
         # Extract the Build ID. FIXME: there's probably a cleaner way.
-        local id="$(readelf -n "$i" | sed 's/.*Build ID: \([0-9a-f]*\).*/\1/; t; d')"
+        local id="$($READELF -n "$i" | sed 's/.*Build ID: \([0-9a-f]*\).*/\1/; t; d')"
         if [ "${#id}" != 40 ]; then
             echo "could not find build ID of $i, skipping" >&2
             continue
@@ -28,8 +28,8 @@ _separateDebugInfo() {
         # Extract the debug info.
         header "separating debug info from $i (build ID $id)"
         mkdir -p "$dst/${id:0:2}"
-        objcopy --only-keep-debug "$i" "$dst/${id:0:2}/${id:2}.debug"
-        strip --strip-debug "$i"
+        $OBJCOPY --only-keep-debug "$i" "$dst/${id:0:2}/${id:2}.debug"
+        $STRIP --strip-debug "$i"
 
         # Also a create a symlink <original-name>.debug.
         ln -sfn ".build-id/${id:0:2}/${id:2}.debug" "$dst/../$(basename "$i")"
diff --git a/pkgs/build-support/setup-hooks/set-java-classpath.sh b/pkgs/build-support/setup-hooks/set-java-classpath.sh
index 047da91bc97..5d3548dc2e8 100644
--- a/pkgs/build-support/setup-hooks/set-java-classpath.sh
+++ b/pkgs/build-support/setup-hooks/set-java-classpath.sh
@@ -10,4 +10,4 @@ addPkgToClassPath () {
     done
 }
 
-envHooks+=(addPkgToClassPath)
+addEnvHooks "$targetOffset" addPkgToClassPath
diff --git a/pkgs/build-support/setup-hooks/setup-debug-info-dirs.sh b/pkgs/build-support/setup-hooks/setup-debug-info-dirs.sh
index 2fd2a2d6da6..96bf48cf123 100644
--- a/pkgs/build-support/setup-hooks/setup-debug-info-dirs.sh
+++ b/pkgs/build-support/setup-hooks/setup-debug-info-dirs.sh
@@ -2,4 +2,4 @@ setupDebugInfoDirs () {
     addToSearchPath NIX_DEBUG_INFO_DIRS $1/lib/debug
 }
 
-envHooks+=(setupDebugInfoDirs)
+addEnvHooks "$targetOffset" setupDebugInfoDirs
diff --git a/pkgs/build-support/setup-hooks/strip.sh b/pkgs/build-support/setup-hooks/strip.sh
index 0bf37e10d87..fc4c7bfbaf9 100644
--- a/pkgs/build-support/setup-hooks/strip.sh
+++ b/pkgs/build-support/setup-hooks/strip.sh
@@ -3,24 +3,45 @@
 fixupOutputHooks+=(_doStrip)
 
 _doStrip() {
-    if [ -z "$dontStrip" ]; then
+    # We don't bother to strip build platform code because it shouldn't make it
+    # to $out anyways---if it does, that's a bigger problem that a lack of
+    # stripping will help catch.
+    local -ra flags=(dontStripHost dontStripTarget)
+    local -ra stripCmds=(STRIP TARGET_STRIP)
+
+    # Optimization
+    if [[ "$STRIP" == "$TARGET_STRIP" ]]; then
+        dontStripTarget+=1
+    fi
+
+    local i
+    for i in ${!stripCmds[@]}; do
+        local -n flag="${flags[$i]}"
+        local -n stripCmd="${stripCmds[$i]}"
+
+        # `dontStrip` disables them all
+        if [[ "$dontStrip" || "$flag" ]] || ! type -f "$stripCmd" 2>/dev/null
+        then continue; fi
+
         stripDebugList=${stripDebugList:-lib lib32 lib64 libexec bin sbin}
         if [ -n "$stripDebugList" ]; then
-            stripDirs "$stripDebugList" "${stripDebugFlags:--S}"
+            stripDirs "$stripCmd" "$stripDebugList" "${stripDebugFlags:--S}"
         fi
 
         stripAllList=${stripAllList:-}
         if [ -n "$stripAllList" ]; then
-            stripDirs "$stripAllList" "${stripAllFlags:--s}"
+            stripDirs "$stripCmd" "$stripAllList" "${stripAllFlags:--s}"
         fi
-    fi
+    done
 }
 
 stripDirs() {
-    local dirs="$1"
-    local stripFlags="$2"
+    local cmd="$1"
+    local dirs="$2"
+    local stripFlags="$3"
     local dirsNew=
 
+    local d
     for d in ${dirs}; do
         if [ -d "$prefix/$d" ]; then
             dirsNew="${dirsNew} $prefix/$d "
@@ -29,8 +50,8 @@ stripDirs() {
     dirs=${dirsNew}
 
     if [ -n "${dirs}" ]; then
-        header "stripping (with flags $stripFlags) in$dirs"
-        find $dirs -type f -print0 | xargs -0 ${xargsFlags:--r} strip $commonStripFlags $stripFlags 2>/dev/null || true
+        header "stripping (with command $cmd and flags $stripFlags) in$dirs"
+        find $dirs -type f -print0 | xargs -0 ${xargsFlags:--r} $cmd $commonStripFlags $stripFlags 2>/dev/null || true
         stopNest
     fi
 }
diff --git a/pkgs/build-support/setup-hooks/win-dll-link.sh b/pkgs/build-support/setup-hooks/win-dll-link.sh
index 9658b9f8259..6130f32bef8 100644
--- a/pkgs/build-support/setup-hooks/win-dll-link.sh
+++ b/pkgs/build-support/setup-hooks/win-dll-link.sh
@@ -25,7 +25,7 @@ _linkDLLs() {
     linkCount=0
     # Iterate over any DLL that we depend on.
     local dll
-    for dll in $(objdump -p *.{exe,dll} | sed -n 's/.*DLL Name: \(.*\)/\1/p' | sort -u); do
+    for dll in $($OBJDUMP -p *.{exe,dll} | sed -n 's/.*DLL Name: \(.*\)/\1/p' | sort -u); do
         if [ -e "./$dll" ]; then continue; fi
         # Locate the DLL - it should be an *executable* file on $DLLPATH.
         local dllPath="$(PATH="$DLLPATH" type -P "$dll")"
diff --git a/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh b/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh
index 79b8d5b73fa..25ac12996cc 100644
--- a/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh
+++ b/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh
@@ -6,7 +6,7 @@ find_gio_modules() {
     fi
 }
 
-envHooks+=(find_gio_modules)
+addEnvHooks "$targetOffset" find_gio_modules
 
 # Note: $gappsWrapperArgs still gets defined even if $dontWrapGApps is set.
 wrapGAppsHook() {
diff --git a/pkgs/build-support/singularity-tools/default.nix b/pkgs/build-support/singularity-tools/default.nix
index 3c27b9fc1ad..62cf13e5202 100644
--- a/pkgs/build-support/singularity-tools/default.nix
+++ b/pkgs/build-support/singularity-tools/default.nix
@@ -61,6 +61,7 @@ rec {
             mkfs -t ext3 -b 4096 /dev/${vmTools.hd}
             mount /dev/${vmTools.hd} disk
             cd disk
+            mkdir proc sys dev
 
             # Run root script
             ${stdenv.lib.optionalString (runAsRoot != null) ''
@@ -92,8 +93,10 @@ rec {
             cd disk
 
             export PATH=$PATH:${e2fsprogs}/bin/
-            singularity create -s $((1 + size * 4 / 1024 + ${toString extraSpace})) $out
-            tar -c . | singularity import $out
+            echo creating
+            singularity image.create -s $((1 + size * 4 / 1024 + ${toString extraSpace})) $out
+            echo importing
+            tar -c . | singularity image.import $out
           '');
 
     in result;
diff --git a/pkgs/build-support/trivial-builders.nix b/pkgs/build-support/trivial-builders.nix
index 7d44feb5ca6..9664abeb465 100644
--- a/pkgs/build-support/trivial-builders.nix
+++ b/pkgs/build-support/trivial-builders.nix
@@ -95,8 +95,8 @@ rec {
 
 
   # Make a package that just contains a setup hook with the given contents.
-  makeSetupHook = { deps ? [], substitutions ? {} }: script:
-    runCommand "hook" substitutions
+  makeSetupHook = { name ? "hook", deps ? [], substitutions ? {} }: script:
+    runCommand name substitutions
       (''
         mkdir -p $out/nix-support
         cp ${script} $out/nix-support/setup-hook
diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix
index fdd7c2013b4..64f4a759e1b 100644
--- a/pkgs/build-support/vm/default.nix
+++ b/pkgs/build-support/vm/default.nix
@@ -60,21 +60,6 @@ rec {
     ''; # */
 
 
-  createDeviceNodes = dev:
-    ''
-      mknod -m 666 ${dev}/null    c 1 3
-      mknod -m 666 ${dev}/zero    c 1 5
-      mknod -m 666 ${dev}/full    c 1 7
-      mknod -m 666 ${dev}/random  c 1 8
-      mknod -m 666 ${dev}/urandom c 1 9
-      mknod -m 666 ${dev}/tty     c 5 0
-      mknod -m 666 ${dev}/ttyS0   c 4 64
-      mknod ${dev}/rtc     c 254 0
-      . /sys/class/block/${hd}/uevent
-      mknod ${dev}/${hd} b $MAJOR $MINOR
-    '';
-
-
   stage1Init = writeScript "vm-run-stage1" ''
     #! ${initrdUtils}/bin/ash -e
 
@@ -109,8 +94,7 @@ rec {
       insmod $i
     done
 
-    mount -t tmpfs none /dev
-    ${createDeviceNodes "/dev"}
+    mount -t devtmpfs devtmpfs /dev
 
     ifconfig lo up
 
@@ -224,7 +208,7 @@ rec {
       -device virtio-rng-pci \
       -virtfs local,path=${storeDir},security_model=none,mount_tag=store \
       -virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
-      -drive file=$diskImage,if=virtio,cache=unsafe,werror=report \
+      ''${diskImage:+-drive file=$diskImage,if=virtio,cache=unsafe,werror=report} \
       -kernel ${kernel}/${img} \
       -initrd ${initrd}/initrd \
       -append "console=ttyS0 panic=1 command=${stage2Init} out=$out mountDisk=$mountDisk loglevel=4" \
@@ -239,8 +223,6 @@ rec {
     mkdir xchg
     mv saved-env xchg/
 
-    diskImage=''${diskImage:-/dev/null}
-
     eval "$preVM"
 
     if [ "$enableParallelBuilding" = 1 ]; then
@@ -256,7 +238,7 @@ rec {
     # the -K option to preserve the temporary build directory).
     cat > ./run-vm <<EOF
     #! ${bash}/bin/sh
-    diskImage=$diskImage
+    ''${diskImage:+diskImage=$diskImage}
     TMPDIR=$TMPDIR
     cd $TMPDIR
     ${qemuCommand}
@@ -302,7 +284,6 @@ rec {
     touch /mnt/.debug
 
     mkdir /mnt/proc /mnt/dev /mnt/sys
-    ${createDeviceNodes "/mnt/dev"}
   '';
 
 
@@ -353,7 +334,6 @@ rec {
         ${kmod}/bin/modprobe iso9660
         ${kmod}/bin/modprobe ufs
         ${kmod}/bin/modprobe cramfs
-        mknod /dev/loop0 b 7 0
 
         mkdir -p $out
         mkdir -p tmp
@@ -377,8 +357,6 @@ rec {
         ${kmod}/bin/modprobe mtdblock
         ${kmod}/bin/modprobe jffs2
         ${kmod}/bin/modprobe zlib
-        mknod /dev/mtd0 c 90 0
-        mknod /dev/mtdblock0 b 31 0
 
         mkdir -p $out
         mkdir -p tmp
@@ -1322,6 +1300,19 @@ rec {
       archs = ["noarch" "x86_64"];
       packages = commonCentOSPackages ++ [ "procps-ng" ];
     };
+
+    centos74x86_64 = rec {
+      name = "centos-7.4-x86_64";
+      fullName = "CentOS 7.4 (x86_64)";
+      # N.B. Switch to vault.centos.org when the next release comes out
+      urlPrefix = http://mirror.centos.org/centos-7/7.4.1708/os/x86_64;
+      packagesList = fetchurl {
+        url = "${urlPrefix}/repodata/b686d3a0f337323e656d9387b9a76ce6808b26255fc3a138b1a87d3b1cb95ed5-primary.xml.gz";
+        sha256 = "1mayp4f3nzd8n4wa3hsz4lk8p076djkvk1wkdmjkwcipyfhd71mn";
+      };
+      archs = ["noarch" "x86_64"];
+      packages = commonCentOSPackages ++ [ "procps-ng" ];
+    };
   };
 
 
@@ -1967,22 +1958,22 @@ rec {
     };
 
     debian8i386 = {
-      name = "debian-8.9-jessie-i386";
-      fullName = "Debian 8.9 Jessie (i386)";
+      name = "debian-8.10-jessie-i386";
+      fullName = "Debian 8.10 Jessie (i386)";
       packagesList = fetchurl {
         url = mirror://debian/dists/jessie/main/binary-i386/Packages.xz;
-        sha256 = "3c78bdf3b693f2f37737c52d6a7718b3a545956f2a853da79f04a2d15541e811";
+        sha256 = "b3aa33bfe0256f72b7aad07b6c714b790d9a20d86c1a448a6f36b35652a82ff0";
       };
       urlPrefix = mirror://debian;
       packages = commonDebianPackages;
     };
 
     debian8x86_64 = {
-      name = "debian-8.9-jessie-amd64";
-      fullName = "Debian 8.9 Jessie (amd64)";
+      name = "debian-8.10-jessie-amd64";
+      fullName = "Debian 8.10 Jessie (amd64)";
       packagesList = fetchurl {
         url = mirror://debian/dists/jessie/main/binary-amd64/Packages.xz;
-        sha256 = "0605589ae7a63c690f37bd2567dc12e02a2eb279d9dc200a7310072ad3593e53";
+        sha256 = "689e77cdf5334a3fffa5ca504e8131ee9ec88a7616f12c9ea5a3d5ac3100a710";
       };
       urlPrefix = mirror://debian;
       packages = commonDebianPackages;