about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndreas Rammhold <andreas@rammhold.de>2020-04-13 16:25:16 +0200
committerGitHub <noreply@github.com>2020-04-13 16:25:16 +0200
commit310b5f6c3439a0c15840a6605b8e9bdddda3428e (patch)
tree33c898d3a59ea9338e94e9db708cd25d0ac58704
parentee90904d5ec37f0c5841df6aae5460c9e57d34aa (diff)
parentbb660fe2284e16b2bea1710edf4dba0452c6bbc3 (diff)
downloadnixlib-310b5f6c3439a0c15840a6605b8e9bdddda3428e.tar
nixlib-310b5f6c3439a0c15840a6605b8e9bdddda3428e.tar.gz
nixlib-310b5f6c3439a0c15840a6605b8e9bdddda3428e.tar.bz2
nixlib-310b5f6c3439a0c15840a6605b8e9bdddda3428e.tar.lz
nixlib-310b5f6c3439a0c15840a6605b8e9bdddda3428e.tar.xz
nixlib-310b5f6c3439a0c15840a6605b8e9bdddda3428e.tar.zst
nixlib-310b5f6c3439a0c15840a6605b8e9bdddda3428e.zip
Merge pull request #84179 from kolloch/build-rust-crate-multi-version-rename
buildRustCrate: Allow version specific dependency renaming + parameter doc
-rw-r--r--pkgs/build-support/rust/build-rust-crate/default.nix152
-rw-r--r--pkgs/build-support/rust/build-rust-crate/test/default.nix45
2 files changed, 188 insertions, 9 deletions
diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix
index a175ba9d7f6e..d9ed26f1d94a 100644
--- a/pkgs/build-support/rust/build-rust-crate/default.nix
+++ b/pkgs/build-support/rust/build-rust-crate/default.nix
@@ -13,14 +13,30 @@ let
       then "macos"
       else stdenv.hostPlatform.parsed.kernel.name;
 
-    # Create rustc arguments to link against the given list of dependencies and
-    # renames
+    # Create rustc arguments to link against the given list of dependencies
+    # and renames.
+    #
+    # See docs for crateRenames below.
     mkRustcDepArgs = dependencies: crateRenames:
       lib.concatMapStringsSep " " (dep:
         let
-          extern = lib.replaceStrings ["-"] ["_"] dep.libName;
+          normalizeName = lib.replaceStrings ["-"] ["_"];
+          extern = normalizeName dep.libName;
+          # Find a choice that matches in name and optionally version.
+          findMatchOrUseExtern = choices:
+            lib.findFirst (choice:
+              (!(choice ? version)
+                 || choice.version == dep.version or ""))
+            { rename = extern; }
+            choices;
           name = if lib.hasAttr dep.crateName crateRenames then
-            lib.strings.replaceStrings ["-"] ["_"] crateRenames.${dep.crateName}
+            let choices = crateRenames.${dep.crateName};
+            in
+            normalizeName (
+              if builtins.isList choices
+              then (findMatchOrUseExtern choices).rename
+              else choices
+            )
           else
             extern;
         in (if lib.any (x: x == "lib" || x == "rlib") dep.crateType then
@@ -42,11 +58,128 @@ let
    installCrate = import ./install-crate.nix { inherit stdenv; };
 in
 
-crate_: lib.makeOverridable ({ rust, release, verbose, features, buildInputs, crateOverrides,
-  dependencies, buildDependencies, crateRenames,
-  extraRustcOpts, buildTests,
-  preUnpack, postUnpack, prePatch, patches, postPatch,
-  preConfigure, postConfigure, preBuild, postBuild, preInstall, postInstall }:
+/* The overridable pkgs.buildRustCrate function.
+ *
+ * Any unrecognized parameters will be passed as to
+ * the underlying stdenv.mkDerivation.
+ */
+ crate_: lib.makeOverridable (
+   # The rust compiler to use.
+   #
+   # Default: pkgs.rustc
+   { rust
+   # Whether to build a release version (`true`) or a debug
+   # version (`false`). Debug versions are faster to build
+   # but might be much slower at runtime.
+   , release
+   # Whether to print rustc invocations etc.
+   #
+   # Example: false
+   # Default: true
+   , verbose
+   # A list of rust/cargo features to enable while building the crate.
+   # Example: [ "std" "async" ]
+   , features
+   # Additional build inputs for building this crate.
+   #
+   # Example: [ pkgs.openssl ]
+   , buildInputs
+   # Allows to override the parameters to buildRustCrate
+   # for any rust dependency in the transitive build tree.
+   #
+   # Default: pkgs.defaultCrateOverrides
+   #
+   # Example:
+   #
+   # pkgs.defaultCrateOverrides // {
+   #   hello = attrs: { buildInputs = [ openssl ]; };
+   # }
+   , crateOverrides
+   # Rust library dependencies, i.e. other libaries that were built
+   # with buildRustCrate.
+   , dependencies
+   # Rust build dependencies, i.e. other libaries that were built
+   # with buildRustCrate and are used by a build script.
+   , buildDependencies
+   # Specify the "extern" name of a library if it differs from the library target.
+   # See above for an extended explanation.
+   #
+   # Default: no renames.
+   #
+   # Example:
+   #
+   # `crateRenames` supports two formats.
+   #
+   # The simple version is an attrset that maps the
+   # `crateName`s of the dependencies to their alternative
+   # names.
+   #
+   # ```nix
+   # {
+   #   my_crate_name = "my_alternative_name";
+   #   # ...
+   # }
+   # ```
+   #
+   # The extended version is also keyed by the `crateName`s but allows
+   # different names for different crate versions:
+   #
+   # ```nix
+   # {
+   #   my_crate_name = [
+   #       { version = "1.2.3"; rename = "my_alternative_name01"; }
+   #       { version = "3.2.3"; rename = "my_alternative_name03"; }
+   #   ]
+   #   # ...
+   # }
+   # ```
+   #
+   # This roughly corresponds to the following snippet in Cargo.toml:
+   #
+   # ```toml
+   # [dependencies]
+   # my_alternative_name01 = { package = "my_crate_name", version = "0.1" }
+   # my_alternative_name03 = { package = "my_crate_name", version = "0.3" }
+   # ```
+   #
+   # Dependencies which use the lib target name as extern name, do not need
+   # to be specified in the crateRenames, even if their crate name differs.
+   #
+   # Including multiple versions of a crate is very popular during
+   # ecosystem transitions, e.g. from futures 0.1 to futures 0.3.
+   , crateRenames
+   # A list of extra options to pass to rustc.
+   #
+   # Example: [ "-Z debuginfo=2" ]
+   # Default: []
+   , extraRustcOpts
+   # Whether to enable building tests.
+   # Use true to enable.
+   # Default: false
+   , buildTests
+   # Passed to stdenv.mkDerivation.
+   , preUnpack
+   # Passed to stdenv.mkDerivation.
+   , postUnpack
+   # Passed to stdenv.mkDerivation.
+   , prePatch
+   # Passed to stdenv.mkDerivation.
+   , patches
+   # Passed to stdenv.mkDerivation.
+   , postPatch
+   # Passed to stdenv.mkDerivation.
+   , preConfigure
+   # Passed to stdenv.mkDerivation.
+   , postConfigure
+   # Passed to stdenv.mkDerivation.
+   , preBuild
+   # Passed to stdenv.mkDerivation.
+   , postBuild
+   # Passed to stdenv.mkDerivation.
+   , preInstall
+   # Passed to stdenv.mkDerivation.
+   , postInstall
+   }:
 
 let crate = crate_ // (lib.attrByPath [ crate_.crateName ] (attr: {}) crateOverrides crate_);
     dependencies_ = dependencies;
@@ -88,6 +221,7 @@ stdenv.mkDerivation (rec {
 
     src = crate.src or (fetchCrate { inherit (crate) crateName version sha256; });
     name = "rust_${crate.crateName}-${crate.version}${lib.optionalString buildTests_ "-test"}";
+    version = crate.version;
     depsBuildBuild = [ rust stdenv.cc cargo jq ];
     buildInputs = (crate.buildInputs or []) ++ buildInputs_;
     dependencies = map lib.getLib dependencies_;
diff --git a/pkgs/build-support/rust/build-rust-crate/test/default.nix b/pkgs/build-support/rust/build-rust-crate/test/default.nix
index fba938f62372..4783129bad9a 100644
--- a/pkgs/build-support/rust/build-rust-crate/test/default.nix
+++ b/pkgs/build-support/rust/build-rust-crate/test/default.nix
@@ -197,6 +197,51 @@ let
         dependencies = [ (mkCrate { crateName = "foo"; libName = "foolib"; src = mkLib "src/lib.rs"; }) ];
         crateRenames = { "foo" = "foo_renamed"; };
       };
+      crateBinRenameMultiVersion = let
+        crateWithVersion = version: mkCrate {
+          crateName = "my_lib";
+          inherit version;
+          src = mkFile "src/lib.rs" ''
+            pub const version: &str = "${version}";
+          '';
+        };
+        depCrate01 = crateWithVersion "0.1.2";
+        depCrate02 = crateWithVersion "0.2.1";
+      in {
+        crateName = "my_bin";
+        src = symlinkJoin {
+          name = "my_bin_src";
+          paths = [
+            (mkFile  "src/main.rs" ''
+              #[test]
+              fn my_lib_01() { assert_eq!(lib01::version, "0.1.2"); }
+
+              #[test]
+              fn my_lib_02() { assert_eq!(lib02::version, "0.2.1"); }
+
+              fn main() { }
+            '')
+          ];
+        };
+        dependencies = [ depCrate01 depCrate02 ];
+        crateRenames = {
+          "my_lib" = [
+            {
+              version = "0.1.2";
+              rename = "lib01";
+            }
+            {
+              version = "0.2.1";
+              rename = "lib02";
+            }
+          ];
+        };
+        buildTests = true;
+        expectedTestOutputs = [
+          "test my_lib_01 ... ok"
+          "test my_lib_02 ... ok"
+        ];
+      };
       rustLibTestsDefault = {
         src = mkTestFile "src/lib.rs" "baz";
         buildTests = true;