Implement automatically setting up a vendor dir from source

* If the source root contains a Cargo.lock file it will be used to
  create a vendor directory
* Otherwise a (descriptive) error will be thrown describing how to
  remediate
* The caller can, of course, manually specify their own `cargoVendorDir`
  which will skip the default vendoring
This commit is contained in:
Ivan Petkov 2021-12-28 15:15:10 -08:00
parent 5abd4f6054
commit b8d083cd7e
No known key found for this signature in database
GPG Key ID: BB6F9EFC065832B6
4 changed files with 95 additions and 27 deletions

View File

@ -2,8 +2,10 @@
, configureCargoCommonVarsHook
, configureCargoVendoredDepsHook
, copyCargoTargetToOutputHook
, inheritCargoTargetHook
, lib
, stdenv
, vendorCargoDeps
}:
{ doCompressTarget ? true
@ -12,27 +14,54 @@
, outputs ? [ "out" ]
, ...
}@args:
stdenv.mkDerivation (args // {
inherit
doCompressTarget
doCopyTarget;
let
vendorFromCargoLockPath = path:
let
cargoLock = path + "/Cargo.lock";
in
if builtins.pathExists cargoLock
then vendorCargoDeps { inherit cargoLock; }
else
throw ''
unable to find Cargo.lock at ${path}. please ensure one of the following:
- a Cargo.lock exists at the root of the source directory of the derivation
- set `cargoVendorDir = vendorCargoDeps { cargoLock = ./some/path/to/Cargo.lock; }`
- set `cargoVendorDir = null` to skip vendoring altogether
'';
nativeBuildInputs = nativeBuildInputs ++ [
cargo
configureCargoCommonVarsHook
configureCargoVendoredDepsHook
copyCargoTargetToOutputHook
];
defaultValues = {
inherit
doCompressTarget
doCopyTarget;
outputs = outputs ++ lib.optional doCopyTarget "target";
buildPhase = ''
runHook preBuild
cargo check --release
runHook postBuild
'';
buildPhase = ''
cargo check --release
'';
installPhase = ''
runHook preInstall
mkdir -p $out
runHook postInstall
'';
installPhase = ''
runHook preInstall
mkdir -p $out
runHook postInstall
'';
})
cargoVendorDir =
if args ? src
then vendorFromCargoLockPath args.src
else null;
};
additions = {
outputs = outputs ++ lib.optional doCopyTarget "target";
nativeBuildInputs = nativeBuildInputs ++ [
cargo
configureCargoCommonVarsHook
configureCargoVendoredDepsHook
copyCargoTargetToOutputHook
inheritCargoTargetHook
];
};
in
stdenv.mkDerivation (defaultValues // args // additions)

View File

@ -1,20 +1,19 @@
copyCargoTargetToOutput() {
echo "Executing copyCargoTargetToOutput"
trap "echo Finished copyCargoTargetToOutput" RETURN
if [ "1" != "${doCopyTarget-}" ]; then
return
fi
if [ "1" != "${doCompressTarget-}" ]; then
# Copy the cargo `target` directory to the `target` output
mv "${CARGO_TARGET_DIR:-target}" "${target}"
return
fi
export SOURCE_DATE_EPOCH=1
mkdir -p "${target}"
if [ "1" != "${doCompressTarget-}" ]; then
# Copy the cargo `target` directory to the `target` output
mv "${CARGO_TARGET_DIR:-target}" "${target}/target"
return
fi
# See: https://reproducible-builds.org/docs/archives/
tar --sort=name \
--mtime="@${SOURCE_DATE_EPOCH}" \

View File

@ -1,4 +1,5 @@
{ makeSetupHook
, rsync
, zstd
}:
@ -20,4 +21,13 @@
zstd = "${zstd}/bin/zstd";
};
} ./copyCargoTargetToOutputHook.sh;
inheritCargoTargetHook = makeSetupHook
{
name = "inheritCargoTargetHook";
substitutions = {
rsync = "${rsync}/bin/rsync";
zstd = "${zstd}/bin/zstd";
};
} ./inheritCargoTargetHook.sh;
}

View File

@ -0,0 +1,30 @@
inheritCargoTarget() {
echo "Executing inheritCargoTarget"
local cargoTarget="${CARGO_TARGET_DIR:-target}"
mkdir -p "${cargoTarget}"
if [ -f "${inheritCargoTarget}/target.tar.zst" ]; then
@zstd@ -d "${inheritCargoTarget}/target.tar.zst" --stdout | \
tar -x -C "${cargoTarget}" --strip-components=1
elif [ -d "${inheritCargoTarget}/target" ]; then
@rsync@ \
--recursive \
--links \
--executability \
--chmod=+w \
--no-perms \
--no-owner \
--no-group \
"${inheritCargoTarget}/target" "${cargoTarget}"
else
echo "${inheritCargoTarget} looks invalid, are you sure it is pointing to a ".target" output?"
false
fi
}
if [ -n "${inheritCargoTarget-}" ]; then
preBuildHooks+=(inheritCargoTarget)
else
echo "inheritCargoTarget not set"
fi