From b8d083cd7e4c4481a318a6ff5b00bc1169f93d9c Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Tue, 28 Dec 2021 15:15:10 -0800 Subject: [PATCH] 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 --- lib/buildWithCargo.nix | 69 ++++++++++++++++++++--------- pkgs/copyCargoTargetToOutputHook.sh | 13 +++--- pkgs/default.nix | 10 +++++ pkgs/inheritCargoTargetHook.sh | 30 +++++++++++++ 4 files changed, 95 insertions(+), 27 deletions(-) create mode 100644 pkgs/inheritCargoTargetHook.sh diff --git a/lib/buildWithCargo.nix b/lib/buildWithCargo.nix index 670ad94..2a1c48f 100644 --- a/lib/buildWithCargo.nix +++ b/lib/buildWithCargo.nix @@ -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) diff --git a/pkgs/copyCargoTargetToOutputHook.sh b/pkgs/copyCargoTargetToOutputHook.sh index f089c12..ce7febf 100644 --- a/pkgs/copyCargoTargetToOutputHook.sh +++ b/pkgs/copyCargoTargetToOutputHook.sh @@ -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}" \ diff --git a/pkgs/default.nix b/pkgs/default.nix index f8097d6..2f0c23b 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -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; } diff --git a/pkgs/inheritCargoTargetHook.sh b/pkgs/inheritCargoTargetHook.sh new file mode 100644 index 0000000..cbf6667 --- /dev/null +++ b/pkgs/inheritCargoTargetHook.sh @@ -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