From 93097326ee1411ee7508ebad13b20299a6dbef08 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Thu, 11 Nov 2021 15:09:17 -0800 Subject: [PATCH] Fix copying cargo artifacts from deps * Previously the CARGO_TARGET_DIR environment was set to the `out` directory which resulted in cargo placing all of its artifacts there instead of the default `target` directory * Later on, the build scripts would then copy the (empty) `target` directory to `$out` resulting in cargo rebuilding the entire dependency tree from scratch whenever the top level crate's source was changed * Now we omit the CARGO_TARGET_DIR environment variable and inspect the `target` directory for any binaries instead of the `out` directory --- build.nix | 5 ++--- test.nix | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/build.nix b/build.nix index b8b12ba..b6f56a4 100644 --- a/build.nix +++ b/build.nix @@ -240,7 +240,6 @@ let # threads as there are cores. This is often too much parallelism so we # reduce it to $NIX_BUILD_CORES if not specified by the caller. export RUST_TEST_THREADS="''${RUST_TEST_THREADS:-$NIX_BUILD_CORES}" - export CARGO_TARGET_DIR="out" log "cargo_version (read): $cargo_version" log "cargo_message_format (set): $cargo_message_format" @@ -369,7 +368,7 @@ let done < <(jq -cMr "$cargo_bins_jq_filter" <"$cargo_build_output_json") else log "$cargo_build_output_json: file wasn't written, using less reliable copying method" - find out -type f -executable \ + find target -type f -executable \ -not -name '*.so' -a -not -name '*.dylib' \ -exec cp {} $out/bin \; fi @@ -390,7 +389,7 @@ let done < <(jq -cMr "$cargo_libs_jq_filter" <"$cargo_build_output_json") else log "$cargo_build_output_json: file wasn't written, using less reliable copying method" - find out -type f \ + find target -type f \ -name '*.so' -or -name '*.dylib' -or -name '*.a' \ -exec cp {} $out/lib \; fi diff --git a/test.nix b/test.nix index df826cf..0986e34 100644 --- a/test.nix +++ b/test.nix @@ -97,11 +97,58 @@ let touch $out ''; + # Tests that the builtDependencies derivation can successfully be unpacked + # and that it actually contains cargo's output artifacts. If the result is + # ever empty, cargo will still succeed in building the top level crate, except + # it will need to rebuild all dependencies from scratch, which is wasteful. + # See https://github.com/nix-community/naersk/issues/202 + depsTargetNotEmpty = pkgs.runCommand "depsTargetNotEmpty" + { inherit (simple-dep) builtDependencies; } + '' + for dep in $builtDependencies; do + # Make destination directory for unarchiving + mkdir dst + ${pkgs.zstd}/bin/zstd -d "$dep/target.tar.zst" --stdout | tar -x -C ./dst + + if [ -z "$(ls -A ./dst)" ]; then + echo target directory is empty: "$dep" + return 1 + fi + + rm -rf ./dst + done + + # Success + touch $out + ''; + + # Same as the test above except checks when the builtDependencies + # derivation is not compressed. + depsUncompressedTargetNotEmpty = pkgs.runCommand "depsUncompressedTargetNotEmpty" + { inherit (simple-dep-no-compress) builtDependencies; } + '' + for dep in $builtDependencies; do + if [ -z "$(ls -A "$dep"/target)" ]; then + echo target directory is empty: "$dep" + return 1 + fi + done + + # Success + touch $out + ''; + simple-dep = naersk.buildPackage { src = ./test/simple-dep; doCheck = true; }; + simple-dep-no-compress = naersk.buildPackage { + src = ./test/simple-dep; + doCheck = true; + compressTarget = false; + }; + simple-dep-doc = naersk.buildPackage { src = ./test/simple-dep;