about summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
authorVladimír Čunát <vcunat@gmail.com>2018-02-20 20:33:17 +0100
committerVladimír Čunát <vcunat@gmail.com>2018-02-20 20:33:40 +0100
commit1d15dadbec4f3d0a1f98e877e77518afe9245148 (patch)
tree76b034c0dbd376b7e588802a9946154499631258 /pkgs/build-support
parent43a88e3d8a68a008abea0bca0b17805aa4910764 (diff)
parentb60ef32617383e78c32ca3d69754df5a5f550183 (diff)
downloadnixlib-1d15dadbec4f3d0a1f98e877e77518afe9245148.tar
nixlib-1d15dadbec4f3d0a1f98e877e77518afe9245148.tar.gz
nixlib-1d15dadbec4f3d0a1f98e877e77518afe9245148.tar.bz2
nixlib-1d15dadbec4f3d0a1f98e877e77518afe9245148.tar.lz
nixlib-1d15dadbec4f3d0a1f98e877e77518afe9245148.tar.xz
nixlib-1d15dadbec4f3d0a1f98e877e77518afe9245148.tar.zst
nixlib-1d15dadbec4f3d0a1f98e877e77518afe9245148.zip
Merge branch 'master' into staging
Larger rebuilds from master.
Diffstat (limited to 'pkgs/build-support')
-rw-r--r--pkgs/build-support/fetchurl/default.nix33
-rw-r--r--pkgs/build-support/release/debian-build.nix2
-rw-r--r--pkgs/build-support/rust/build-rust-crate.nix296
-rw-r--r--pkgs/build-support/rust/carnix.nix16
-rw-r--r--pkgs/build-support/rust/default.nix30
5 files changed, 229 insertions, 148 deletions
diff --git a/pkgs/build-support/fetchurl/default.nix b/pkgs/build-support/fetchurl/default.nix
index 3e47d4a4b683..0bf529caa75e 100644
--- a/pkgs/build-support/fetchurl/default.nix
+++ b/pkgs/build-support/fetchurl/default.nix
@@ -1,4 +1,4 @@
-{ stdenvNoCC, curl }: # Note that `curl' may be `null', in case of the native stdenvNoCC.
+{ lib, stdenvNoCC, curl }: # Note that `curl' may be `null', in case of the native stdenvNoCC.
 
 let
 
@@ -20,7 +20,7 @@ let
   # "gnu", etc.).
   sites = builtins.attrNames mirrors;
 
-  impureEnvVars = stdenvNoCC.lib.fetchers.proxyImpureEnvVars ++ [
+  impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
     # This variable allows the user to pass additional options to curl
     "NIX_CURL_FLAGS"
 
@@ -89,22 +89,28 @@ in
 , passthru ? {}
 }:
 
-assert builtins.isList urls;
-assert (urls == []) != (url == "");
 assert sha512 != "" -> builtins.compareVersions "1.11" builtins.nixVersion <= 0;
 
-
 let
 
-  hasHash = showURLs || (outputHash != "" && outputHashAlgo != "")
-    || sha1 != "" || sha256 != "" || sha512 != "";
-  urls_ = if urls != [] then urls else [url];
+  urls_ =
+    if urls != [] && url == "" then
+      (if lib.isList urls then urls
+       else throw "`urls` is not a list")
+    else if urls == [] && url != "" then [url]
+    else throw "fetchurl requires either `url` or `urls` to be set";
+
+  hash_ =
+    if md5 != "" then throw "fetchurl does not support md5 anymore, please use sha256 or sha512"
+    else if (outputHash != "" && outputHashAlgo != "") then { inherit outputHashAlgo outputHash; }
+    else if sha512 != "" then { outputHashAlgo = "sha512"; outputHash = sha512; }
+    else if sha256 != "" then { outputHashAlgo = "sha256"; outputHash = sha256; }
+    else if sha1   != "" then { outputHashAlgo = "sha1";   outputHash = sha1; }
+    else throw "fetchurl requires a hash for fixed-output derivation: ${lib.concatStringsSep ", " urls_}";
 
 in
 
-if md5 != "" then throw "fetchurl does not support md5 anymore, please use sha256 or sha512"
-else if (!hasHash) then throw "Specify hash for fetchurl fixed-output derivation: ${stdenvNoCC.lib.concatStringsSep ", " urls_}"
-else stdenvNoCC.mkDerivation {
+stdenvNoCC.mkDerivation {
   name =
     if showURLs then "urls"
     else if name != "" then name
@@ -121,10 +127,7 @@ else stdenvNoCC.mkDerivation {
   preferHashedMirrors = true;
 
   # New-style output content requirements.
-  outputHashAlgo = if outputHashAlgo != "" then outputHashAlgo else
-      if sha512 != "" then "sha512" else if sha256 != "" then "sha256" else "sha1";
-  outputHash = if outputHash != "" then outputHash else
-      if sha512 != "" then sha512 else if sha256 != "" then sha256 else sha1;
+  inherit (hash_) outputHashAlgo outputHash;
 
   outputHashMode = if (recursiveHash || executable) then "recursive" else "flat";
 
diff --git a/pkgs/build-support/release/debian-build.nix b/pkgs/build-support/release/debian-build.nix
index f4bc3e73056d..354d929c9b65 100644
--- a/pkgs/build-support/release/debian-build.nix
+++ b/pkgs/build-support/release/debian-build.nix
@@ -78,10 +78,10 @@ vmTools.runInLinuxImage (stdenv.mkDerivation (
         header "Generated DEB package: $i"
         dpkg-deb --info "$i"
         pkgName=$(dpkg-deb -W "$i" | awk '{print $1}')
-        dpkg -i "$i"
         echo "file deb $i" >> $out/nix-support/hydra-build-products
         stopNest
       done
+      dpkg -i $out/debs/*.deb
 
       for i in $extraDebs; do
         echo "file deb-extra $(ls $i/debs/*.deb | sort | head -1)" >> $out/nix-support/hydra-build-products
diff --git a/pkgs/build-support/rust/build-rust-crate.nix b/pkgs/build-support/rust/build-rust-crate.nix
index f1f344ca3c7d..8a9a07fd7a8f 100644
--- a/pkgs/build-support/rust/build-rust-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate.nix
@@ -6,44 +6,16 @@
 
 { 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
-
+let 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);
+
+    echo_build_heading = colors: ''
       echo_build_heading() {
        start=""
        end=""
@@ -57,7 +29,8 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
          echo "$start""Building $1 ($2)""$end"
        fi
       }
-
+    '';
+    noisily = colors: verbose: ''
       noisily() {
         start=""
         end=""
@@ -71,18 +44,29 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
 	''}
 	$@
       }
+    '';
 
+    configureCrate =
+      { crateName, crateVersion, crateAuthors, build, libName, crateFeatures, colors, libPath, release, buildDependencies, completeDeps, completeBuildDeps, verbose, dependencies }:
+      let version_ = lib.splitString "-" crateVersion;
+          versionPre = if lib.tail version_ == [] then "" else builtins.elemAt version_ 1;
+          version = lib.splitString "." (lib.head version_);
+          rustcOpts = (if release then "-C opt-level=3" else "-C debuginfo=2");
+          buildDeps = makeDeps buildDependencies;
+          authors = lib.concatStringsSep ":" crateAuthors;
+          optLevel = if release then 3 else 0;
+          completeDepsDir = lib.concatStringsSep " " completeDeps;
+          completeBuildDepsDir = lib.concatStringsSep " " completeBuildDeps;
+      in ''
+      runHook preConfigure
+      ${echo_build_heading colors}
+      ${noisily colors verbose}
       symlink_dependency() {
-      # $1 is the nix-store path of a dependency
+        # $1 is the nix-store path of a dependency
+        # $2 is the target path
         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 #*/
+        ln -s -f $i/lib/*.rlib $2 #*/
+        ln -s -f $i/lib/*.so $i/lib/*.dylib $2 #*/
         if [ -e "$i/lib/link" ]; then
             cat $i/lib/link >> target/link
             cat $i/lib/link >> target/link.final
@@ -92,48 +76,15 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
         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
+        symlink_dependency $i target/deps
       done
       for i in ${completeBuildDepsDir}; do
-         symlink_dependency $i --buildDep
+         symlink_dependency $i target/buildDeps
       done
-      if [ -e target/link ]; then
+      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
@@ -145,10 +96,16 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
       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_FAMILY="unix"
+      export CARGO_CFG_UNIX=1
       export CARGO_CFG_TARGET_ENV="gnu"
+      export CARGO_CFG_TARGET_ENDIAN=${if buildPlatform.parsed.cpu.significantByte.name == "littleEndian" then "little" else "big"}
+      export CARGO_CFG_TARGET_POINTER_WIDTH=${toString buildPlatform.parsed.cpu.bits}
+      export CARGO_CFG_TARGET_VENDOR=${buildPlatform.parsed.vendor.name}
+
       export CARGO_MANIFEST_DIR="."
       export DEBUG="${toString (!release)}"
       export OPT_LEVEL="${toString optLevel}"
@@ -159,7 +116,7 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
       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
+      if [[ -n "${versionPre}" ]]; then
         export CARGO_PKG_VERSION_PRE="${versionPre}"
       fi
 
@@ -180,8 +137,8 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
            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}
+           ${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
@@ -198,33 +155,104 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
            | 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 [[ -n "$(ls target/build/${crateName}.out)" ]]; then
 
-            if [ -e "${libPath}" ] ; then
+            if [[ -e "${libPath}" ]]; then
                cp -r target/build/${crateName}.out/* $(dirname ${libPath}) #*/
             else
                cp -r target/build/${crateName}.out/* src #*/
             fi
          fi
       fi
+      runHook postConfigure
+    '';
+
+    buildCrate = { crateName, crateVersion, crateAuthors,
+                   dependencies, completeDeps, completeBuildDeps,
+                   crateFeatures, libName, build, release, libPath,
+                   crateType, metadata, crateBin, finalBins,
+                   extraRustcOpts,
+                   verbose, colors }:
+
+      let depsDir = lib.concatStringsSep " " dependencies;
+          completeDepsDir = lib.concatStringsSep " " completeDeps;
+          completeBuildDepsDir = lib.concatStringsSep " " completeBuildDeps;
+          deps = makeDeps dependencies;
+          optLevel = if release then 3 else 0;
+          rustcOpts =
+            lib.lists.foldl' (opts: opt: opts + " " + opt)
+              (if release then "-C opt-level=3" else "-C debuginfo=2")
+              extraRustcOpts;
+          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 ''
+      runHook preBuild
+      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 colors}
+      ${noisily colors verbose}
+
+      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
+      }
+
 
       EXTRA_LIB=""
       CRATE_NAME=$(echo ${libName} | sed -e "s/-/_/g")
 
-      if [ -e target/link_ ]; then
+      if [[ -e target/link_ ]]; then
         EXTRA_BUILD="$(cat target/link_) $EXTRA_BUILD"
       fi
 
-      if [ -e "${libPath}" ] ; then
+      if [[ -e "${libPath}" ]]; then
          build_lib ${libPath}
-      elif [ -e src/lib.rs ] ; then
+      elif [[ -e src/lib.rs ]]; then
          build_lib src/lib.rs
-      elif [ -e src/${libName}.rs ] ; then
+      elif [[ -e src/${libName}.rs ]]; then
          build_lib src/${libName}.rs
       fi
 
       echo "$EXTRA_LINK_SEARCH" | while read i; do
-         if [ ! -z "$i" ]; then
+         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#")
@@ -233,7 +261,7 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
          fi
       done
       echo "$EXTRA_LINK" | while read i; do
-         if [ ! -z "$i" ]; then
+         if [[ ! -z "$i" ]]; then
            for lib in $i; do
              echo "-l $lib" >> target/link
              echo "-l $lib" >> target/link.final
@@ -241,7 +269,7 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
          fi
       done
 
-      if [ -e target/link ]; then
+      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
@@ -253,7 +281,7 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
 
       mkdir -p target/bin
       echo "${crateBin}" | sed -n 1'p' | tr ',' '\n' | while read BIN; do
-         if [ ! -z "$BIN" ]; then
+         if [[ ! -z "$BIN" ]]; then
            build_bin $BIN
          fi
       done
@@ -267,27 +295,32 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
       ''}
       # Remove object files to avoid "wrong ELF type"
       find target -type f -name "*.o" -print0 | xargs -0 rm -f
+    '' + finalBins + ''
       runHook postBuild
-    '' + finalBins;
+    '';
 
-    installCrate = crateName: ''
+    installCrate = crateName: metadata: ''
+      runHook preInstall
       mkdir -p $out
-      if [ -s target/env ]; then
+      if [[ -s target/env ]]; then
         cp target/env $out/env
       fi
-      if [ -s target/link.final ]; then
+      if [[ -s target/link.final ]]; then
         mkdir -p $out/lib
         cp target/link.final $out/lib/link
       fi
-      if [ "$(ls -A target/lib)" ]; then
+      if [[ "$(ls -A target/lib)" ]]; then
         mkdir -p $out/lib
         cp target/lib/* $out/lib #*/
+        for lib in $out/lib/*.so $out/lib/*.dylib; do #*/
+          ln -s $lib $(echo $lib | sed -e "s/-${metadata}//")
+        done
       fi
-      if [ "$(ls -A target/build)" ]; then # */
+      if [[ "$(ls -A target/build)" ]]; then # */
         mkdir -p $out/lib
         cp -r target/build/* $out/lib # */
       fi
-      if [ "$(ls -A target/bin)" ]; then
+      if [[ "$(ls -A target/bin)" ]]; then
         mkdir -p $out/bin
         cp -P target/bin/* $out/bin # */
       fi
@@ -295,9 +328,16 @@ let buildCrate = { crateName, crateVersion, crateAuthors, buildDependencies,
     '';
 in
 
-crate_: lib.makeOverridable ({ rust, release, verbose, features, buildInputs, crateOverrides }:
+crate_: lib.makeOverridable ({ rust, release, verbose, features, buildInputs, crateOverrides,
+  dependencies, buildDependencies,
+  extraRustcOpts,
+  preUnpack, postUnpack, prePatch, patches, postPatch,
+  preConfigure, postConfigure, preBuild, postBuild, preInstall, postInstall }:
 
 let crate = crate_ // (lib.attrByPath [ crate_.crateName ] (attr: {}) crateOverrides crate_);
+    release_ = release;
+    dependencies_ = dependencies;
+    buildDependencies_ = buildDependencies;
     processedAttrs = [
       "src" "buildInputs" "crateBin" "crateLib" "libName" "libPath"
       "buildDependencies" "dependencies" "features"
@@ -309,6 +349,7 @@ in
 stdenv.mkDerivation (rec {
 
     inherit (crate) crateName;
+    inherit preUnpack postUnpack prePatch patches postPatch preConfigure postConfigure preBuild postBuild preInstall postInstall;
 
     src = if lib.hasAttr "src" crate then
         crate.src
@@ -319,12 +360,12 @@ stdenv.mkDerivation (rec {
     dependencies =
       builtins.map
         (dep: dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; })
-        (crate.dependencies or []);
+        dependencies_;
 
     buildDependencies =
       builtins.map
         (dep: dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; })
-        (crate.buildDependencies or []);
+        buildDependencies_;
 
     completeDeps = lib.lists.unique (dependencies ++ lib.lists.concatMap (dep: dep.completeDeps) dependencies);
     completeBuildDeps = lib.lists.unique (
@@ -339,7 +380,8 @@ stdenv.mkDerivation (rec {
     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));
+    depsMetadata = builtins.foldl' (str: dep: str + dep.metadata) "" (dependencies ++ buildDependencies);
+    metadata = builtins.substring 0 10 (builtins.hashString "sha256" (crateName + "-" + crateVersion + "___" + toString crateFeatures + "___" + depsMetadata ));
 
     crateBin = if crate ? crateBin then
        builtins.foldl' (bins: bin:
@@ -370,20 +412,42 @@ stdenv.mkDerivation (rec {
     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";
+      if lib.attrByPath ["plugin"] false crate then "dylib" else
+      if crate ? type then crate.type else "lib";
     colors = lib.attrByPath [ "colors" ] "always" crate;
-    buildPhase = buildCrate {
+    configurePhase = configureCrate {
       inherit crateName dependencies buildDependencies completeDeps completeBuildDeps
+              crateFeatures libName build release libPath crateVersion
+              crateAuthors verbose colors;
+    };
+    extraRustcOpts = if crate ? extraRustcOpts then crate.extraRustcOpts else [];
+    buildPhase = buildCrate {
+      inherit crateName dependencies completeDeps completeBuildDeps
               crateFeatures libName build release libPath crateType crateVersion
-              crateAuthors metadata crateBin finalBins verbose colors;
+              crateAuthors metadata crateBin finalBins verbose colors extraRustcOpts;
     };
-    installPhase = installCrate crateName;
+    installPhase = installCrate crateName metadata;
 
-} // extraDerivationAttrs)) {
+} // extraDerivationAttrs
+)) {
   rust = rustc;
-  release = true;
-  verbose = true;
+  release = crate_.release or true;
+  verbose = crate_.verbose or true;
+  extraRustcOpts = [];
   features = [];
   buildInputs = [];
   crateOverrides = defaultCrateOverrides;
+  preUnpack = crate_.preUnpack or "";
+  postUnpack = crate_.postUnpack or "";
+  prePatch = crate_.prePatch or "";
+  patches = crate_.patches or [];
+  postPatch = crate_.postPatch or "";
+  preConfigure = crate_.preConfigure or "";
+  postConfigure = crate_.postConfigure or "";
+  preBuild = crate_.preBuild or "";
+  postBuild = crate_.postBuild or "";
+  preInstall = crate_.preInstall or "";
+  postInstall = crate_.postInstall or "";
+  dependencies = crate_.dependencies or [];
+  buildDependencies = crate_.buildDependencies or [];
 }
diff --git a/pkgs/build-support/rust/carnix.nix b/pkgs/build-support/rust/carnix.nix
index 8b0af499c8f1..ebb46b0f5921 100644
--- a/pkgs/build-support/rust/carnix.nix
+++ b/pkgs/build-support/rust/carnix.nix
@@ -1,4 +1,4 @@
-# Generated by carnix 0.6.5: carnix -o carnix.nix Cargo.lock --src ./.
+# Generated by carnix 0.6.5: carnix -o carnix.nix Cargo.lock
 { lib, buildPlatform, buildRustCrate, fetchgit }:
 let kernel = buildPlatform.parsed.kernel.name;
     abi = buildPlatform.parsed.abi.name;
@@ -18,7 +18,7 @@ let kernel = buildPlatform.parsed.kernel.name;
     ) [] (builtins.attrNames feat);
 in
 rec {
-  carnix = f: carnix_0_6_5 { features = carnix_0_6_5_features { carnix_0_6_5 = f; }; };
+  carnix = f: carnix_0_6_6 { features = carnix_0_6_6_features { carnix_0_6_6 = f; }; };
   aho_corasick_0_6_3_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
     crateName = "aho-corasick";
     version = "0.6.3";
@@ -71,11 +71,11 @@ rec {
     sha256 = "0p4b3nr0s5nda2qmm7xdhnvh4lkqk3xd8l9ffmwbvqw137vx7mj1";
     inherit dependencies buildDependencies features;
   };
-  carnix_0_6_5_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+  carnix_0_6_6_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
     crateName = "carnix";
-    version = "0.6.5";
+    version = "0.6.6";
     authors = [ "pe@pijul.org <pe@pijul.org>" ];
-    sha256 = "0r952s5az5mhw7z2r421i5lr0w5h436hah61md2bdb3204c2pl9c";
+    sha256 = "1ai2r52j6vlrclhb7cvifx3lsg9naiy3jpsrbi3mmfmr6zbi7rdw";
     inherit dependencies buildDependencies features;
   };
   cc_1_0_3_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
@@ -623,11 +623,11 @@ rec {
       (f.bitflags_1_0_1.default or false) ||
       (bitflags_1_0_1.default or false);
   }) [];
-  carnix_0_6_5 = { features?(carnix_0_6_5_features {}) }: carnix_0_6_5_ {
+  carnix_0_6_6 = { features?(carnix_0_6_6_features {}) }: carnix_0_6_6_ {
     dependencies = mapFeatures features ([ clap_2_28_0 env_logger_0_5_3 error_chain_0_11_0 itertools_0_7_3 log_0_4_1 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 ]);
   };
-  carnix_0_6_5_features = f: updateFeatures f (rec {
-    carnix_0_6_5.default = (f.carnix_0_6_5.default or true);
+  carnix_0_6_6_features = f: updateFeatures f (rec {
+    carnix_0_6_6.default = (f.carnix_0_6_6.default or true);
     clap_2_28_0.default = true;
     env_logger_0_5_3.default = true;
     error_chain_0_11_0.default = true;
diff --git a/pkgs/build-support/rust/default.nix b/pkgs/build-support/rust/default.nix
index 63d08e1d0311..83ef146de5f8 100644
--- a/pkgs/build-support/rust/default.nix
+++ b/pkgs/build-support/rust/default.nix
@@ -4,7 +4,7 @@ let
     inherit stdenv cacert git rust cargo-vendor;
   };
 in
-{ name, cargoSha256
+{ name, cargoSha256 ? null
 , src ? null
 , srcs ? null
 , sourceRoot ? null
@@ -13,15 +13,31 @@ in
 , cargoUpdateHook ? ""
 , cargoDepsHook ? ""
 , cargoBuildFlags ? []
+
+, cargoVendorDir ? null
 , ... } @ args:
 
+assert cargoVendorDir == null -> cargoSha256 != null;
+
 let
   lib = stdenv.lib;
 
-  cargoDeps = fetchcargo {
-    inherit name src srcs sourceRoot cargoUpdateHook;
-    sha256 = cargoSha256;
-  };
+  cargoDeps = if cargoVendorDir == null
+    then fetchcargo {
+        inherit name src srcs sourceRoot cargoUpdateHook;
+        sha256 = cargoSha256;
+      }
+    else null;
+
+  setupVendorDir = if cargoVendorDir == null
+    then ''
+      unpackFile "$cargoDeps"
+      cargoDepsCopy=$(stripHash $(basename $cargoDeps))
+      chmod -R +w "$cargoDepsCopy"
+    ''
+    else ''
+      cargoDepsCopy="$sourceRoot/${cargoVendorDir}"
+    '';
 
 in stdenv.mkDerivation (args // {
   inherit cargoDeps;
@@ -39,9 +55,7 @@ in stdenv.mkDerivation (args // {
   postUnpack = ''
     eval "$cargoDepsHook"
 
-    unpackFile "$cargoDeps"
-    cargoDepsCopy=$(stripHash $(basename $cargoDeps))
-    chmod -R +w "$cargoDepsCopy"
+    ${setupVendorDir}
 
     mkdir .cargo
     cat >.cargo/config <<-EOF