mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-23 22:20:51 +00:00
2b694c237b
It turns out that cargo implicitly depends on rustc at runtime: even `cargo help` will fail if rustc is not in the PATH. This means that we need to wrap the cargo binary to add rustc to PATH. However, I have opted into doing something slightly unusual: instead of tying down a specific cargo to use a specific rustc (i.e., wrap cargo so that "${rustc}/bin" is prefixed into PATH), instead I'm adding the rustc used to build cargo as a fallback rust compiler (i.e., wrap cargo so that "${rustc}/bin" is suffixed into PATH). This means that cargo will prefer to use a rust compiler that is in the default path, but fallback into the one used to build cargo only if there wasn't any rust compiler in the default path. The reason I'm doing this is that otherwise it could cause unexpected effects. For example, if you had a build environment with the rustcMaster and cargo derivations, you would expect cargo to use rustcMaster to compile your project (since rustcMaster would be the only compiler available in $PATH), but this wouldn't happen if we tied down cargo to use the rustc that was used to compile it (because the default cargo derivation gets compiled with the stable rust compiler). That said, I have slightly modified makeRustPlatform so that a rust platform will always use the rust compiler that was used to build cargo, because this prevents mistakenly depending on two different versions of the rust compiler (stable and unstable) in the same rust platform, something which is usually undesirable. Fixes #11053
108 lines
2.5 KiB
Nix
108 lines
2.5 KiB
Nix
{ stdenv, cacert, git, cargo, rustRegistry }:
|
|
{ name, depsSha256
|
|
, src ? null
|
|
, srcs ? null
|
|
, sourceRoot ? null
|
|
, buildInputs ? []
|
|
, cargoUpdateHook ? ""
|
|
, ... } @ args:
|
|
|
|
let
|
|
fetchDeps = import ./fetchcargo.nix {
|
|
inherit stdenv cacert git cargo rustRegistry;
|
|
};
|
|
|
|
cargoDeps = fetchDeps {
|
|
inherit name src srcs sourceRoot cargoUpdateHook;
|
|
sha256 = depsSha256;
|
|
};
|
|
|
|
in stdenv.mkDerivation (args // {
|
|
inherit cargoDeps rustRegistry;
|
|
|
|
patchRegistryDeps = ./patch-registry-deps;
|
|
|
|
buildInputs = [ git cargo cargo.rustc ] ++ buildInputs;
|
|
|
|
configurePhase = args.configurePhase or "true";
|
|
|
|
postUnpack = ''
|
|
echo "Using cargo deps from $cargoDeps"
|
|
|
|
cp -r "$cargoDeps" deps
|
|
chmod +w deps -R
|
|
|
|
# It's OK to use /dev/null as the URL because by the time we do this, cargo
|
|
# won't attempt to update the registry anymore, so the URL is more or less
|
|
# irrelevant
|
|
|
|
cat <<EOF > deps/config
|
|
[registry]
|
|
index = "file:///dev/null"
|
|
EOF
|
|
|
|
export CARGO_HOME="$(realpath deps)"
|
|
|
|
# Let's find out which $indexHash cargo uses for file:///dev/null
|
|
(cd $sourceRoot && cargo fetch &>/dev/null) || true
|
|
cd deps
|
|
indexHash="$(basename $(echo registry/index/*))"
|
|
|
|
echo "Using indexHash '$indexHash'"
|
|
|
|
rm -rf -- "registry/cache/$indexHash" \
|
|
"registry/index/$indexHash"
|
|
|
|
mv registry/cache/HASH "registry/cache/$indexHash"
|
|
|
|
echo "Using rust registry from $rustRegistry"
|
|
ln -s "$rustRegistry" "registry/index/$indexHash"
|
|
|
|
# Retrieved the Cargo.lock file which we saved during the fetch
|
|
cd ..
|
|
mv deps/Cargo.lock $sourceRoot/
|
|
|
|
(
|
|
cd $sourceRoot
|
|
|
|
cargo fetch
|
|
cargo clean
|
|
)
|
|
'' + (args.postUnpack or "");
|
|
|
|
prePatch = ''
|
|
# Patch registry dependencies, using the scripts in $patchRegistryDeps
|
|
(
|
|
set -euo pipefail
|
|
|
|
cd ../deps/registry/src/*
|
|
|
|
for script in $patchRegistryDeps/*; do
|
|
# Run in a subshell so that directory changes and shell options don't
|
|
# affect any following commands
|
|
|
|
( . $script)
|
|
done
|
|
)
|
|
'' + (args.prePatch or "");
|
|
|
|
buildPhase = args.buildPhase or ''
|
|
echo "Running cargo build --release"
|
|
cargo build --release
|
|
'';
|
|
|
|
checkPhase = args.checkPhase or ''
|
|
echo "Running cargo test"
|
|
cargo test
|
|
'';
|
|
|
|
doCheck = args.doCheck or true;
|
|
|
|
installPhase = args.installPhase or ''
|
|
mkdir -p $out/bin
|
|
for f in $(find target/release -maxdepth 1 -type f); do
|
|
cp $f $out/bin
|
|
done;
|
|
'';
|
|
})
|