diff --git a/doc/languages-frameworks/rust.section.md b/doc/languages-frameworks/rust.section.md index 70aced7d5cb1..008909e5c76a 100644 --- a/doc/languages-frameworks/rust.section.md +++ b/doc/languages-frameworks/rust.section.md @@ -107,6 +107,54 @@ rustPlatform.buildRustPackage rec { } ``` +### Importing a `Cargo.lock` file + +Using `cargoSha256` or `cargoHash` is tedious when using +`buildRustPackage` within a project, since it requires that the hash +is updated after every change to `Cargo.lock`. Therefore, +`buildRustPackage` also supports vendoring dependencies directly from +a `Cargo.lock` file using the `cargoLock` argument. For example: + +```nix +rustPlatform.buildRustPackage rec { + pname = "myproject"; + version = "1.0.0"; + + cargoLock = { + lockFile = ./Cargo.lock; + } + + # ... +} +``` + +This will retrieve the dependencies using fixed-output derivations from +the specified lockfile. + +The output hash of each dependency that uses a git source must be +specified in the `outputHashes` attribute. For example: + +```nix +rustPlatform.buildRustPackage rec { + pname = "myproject"; + version = "1.0.0"; + + cargoLock = { + lockFile = ./Cargo.lock; + outputHashes = { + "finalfusion-0.14.0" = "17f4bsdzpcshwh74w5z119xjy2if6l2wgyjy56v621skr2r8y904"; + }; + } + + # ... +} +``` + +If you do not specify an output hash for a git dependency, building +the package will fail and inform you of which crate needs to be +added. To find the correct hash, you can first use `lib.fakeSha256` or +`lib.fakeHash` as a stub hash. Building the package (and thus the +vendored dependencies) will then inform you of the correct hash. ### Cross compilation diff --git a/pkgs/build-support/rust/default.nix b/pkgs/build-support/rust/default.nix index ff9ca642daad..711276116a66 100644 --- a/pkgs/build-support/rust/default.nix +++ b/pkgs/build-support/rust/default.nix @@ -7,6 +7,7 @@ , cargoInstallHook , cargoSetupHook , fetchCargoTarball +, importCargoLock , runCommandNoCC , rustPlatform , callPackage @@ -41,6 +42,7 @@ , cargoDepsHook ? "" , buildType ? "release" , meta ? {} +, cargoLock ? null , cargoVendorDir ? null , checkType ? buildType , depsExtraArgs ? {} @@ -55,19 +57,22 @@ , buildAndTestSubdir ? null , ... } @ args: -assert cargoVendorDir == null -> !(cargoSha256 == "" && cargoHash == ""); +assert cargoVendorDir == null && cargoLock == null -> cargoSha256 == "" && cargoHash == "" + -> throw "cargoSha256, cargoHash, cargoVendorDir, or cargoLock must be set"; assert buildType == "release" || buildType == "debug"; let - cargoDeps = if cargoVendorDir == null - then fetchCargoTarball ({ - inherit src srcs sourceRoot unpackPhase cargoUpdateHook; - name = cargoDepsName; - hash = cargoHash; - patches = cargoPatches; - sha256 = cargoSha256; - } // depsExtraArgs) + cargoDeps = + if cargoVendorDir == null + then if cargoLock != null then importCargoLock cargoLock + else fetchCargoTarball ({ + inherit src srcs sourceRoot unpackPhase cargoUpdateHook; + name = cargoDepsName; + hash = cargoHash; + patches = cargoPatches; + sha256 = cargoSha256; + } // depsExtraArgs) else null; # If we have a cargoSha256 fixed-output derivation, validate it at build time @@ -96,7 +101,7 @@ in # See https://os.phil-opp.com/testing/ for more information. assert useSysroot -> !(args.doCheck or true); -stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // lib.optionalAttrs useSysroot { +stdenv.mkDerivation ((removeAttrs args [ "depsExtraArgs" "cargoLock" ]) // lib.optionalAttrs useSysroot { RUSTFLAGS = "--sysroot ${sysroot} " + (args.RUSTFLAGS or ""); } // { inherit buildAndTestSubdir cargoDeps; diff --git a/pkgs/development/compilers/rust/make-rust-platform.nix b/pkgs/development/compilers/rust/make-rust-platform.nix index 2343fd749011..2a38933df16c 100644 --- a/pkgs/development/compilers/rust/make-rust-platform.nix +++ b/pkgs/development/compilers/rust/make-rust-platform.nix @@ -13,7 +13,7 @@ rec { buildRustPackage = callPackage ../../../build-support/rust { inherit cargoBuildHook cargoCheckHook cargoInstallHook cargoSetupHook - fetchCargoTarball rustc; + fetchCargoTarball importCargoLock rustc; }; importCargoLock = buildPackages.callPackage ../../../build-support/rust/import-cargo-lock.nix {};