summary refs log tree commit diff
path: root/pkgs/build-support/rust/build-rust-crate
diff options
context:
space:
mode:
authorPeter Kolloch <info@eigenvalue.net>2020-04-10 00:55:44 +0200
committerPeter Kolloch <info@eigenvalue.net>2020-04-10 00:55:44 +0200
commitbb660fe2284e16b2bea1710edf4dba0452c6bbc3 (patch)
tree3bf0f3bc174eeccab2f7c4fe8b00b7beb319e477 /pkgs/build-support/rust/build-rust-crate
parent5f9af254a5d60bef7dd5b6879e5c71567f0d66e0 (diff)
downloadnixpkgs-bb660fe2284e16b2bea1710edf4dba0452c6bbc3.tar
nixpkgs-bb660fe2284e16b2bea1710edf4dba0452c6bbc3.tar.gz
nixpkgs-bb660fe2284e16b2bea1710edf4dba0452c6bbc3.tar.bz2
nixpkgs-bb660fe2284e16b2bea1710edf4dba0452c6bbc3.tar.lz
nixpkgs-bb660fe2284e16b2bea1710edf4dba0452c6bbc3.tar.xz
nixpkgs-bb660fe2284e16b2bea1710edf4dba0452c6bbc3.tar.zst
nixpkgs-bb660fe2284e16b2bea1710edf4dba0452c6bbc3.zip
buildRustCrate: Support versioned crate renames
Diffstat (limited to 'pkgs/build-support/rust/build-rust-crate')
-rw-r--r--pkgs/build-support/rust/build-rust-crate/default.nix58
-rw-r--r--pkgs/build-support/rust/build-rust-crate/test/default.nix45
2 files changed, 99 insertions, 4 deletions
diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix
index fdff9edfa73..d9ed26f1d94 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
@@ -92,12 +108,45 @@ in
    #
    # 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.
    #
@@ -172,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 fba938f6237..4783129bad9 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;