From 7e09a69d6713e926b38bfcbd7028cac15fcd0012 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Sat, 30 Nov 2024 16:41:52 -0800 Subject: [PATCH] mkDummySrc: rework to only stub bins if they actually exist --- CHANGELOG.md | 6 +++ checks/default.nix | 11 +++- .../bin/crane-dummy-mkDummySrcSimple/main.rs | 10 ---- .../single-alt/expected/src/lib.rs | 14 ------ .../bin/crane-dummy-mkDummySrcSimple/main.rs | 14 ------ .../foo/src/bin/crane-dummy-foo/main.rs | 14 ------ .../bin/crane-dummy-workspace-bindeps/main.rs | 14 ------ .../workspace-bindeps/expected/src/lib.rs | 14 ------ .../expected/src}/main.rs | 0 .../hello/src/bin/crane-dummy-hello/main.rs | 14 ------ .../print/src/bin/crane-dummy-print/main.rs | 14 ------ .../expected/print/src/lib.rs | 14 ------ .../expected/print/src}/main.rs | 0 .../world/src/bin/crane-dummy-world/main.rs | 14 ------ .../bar/baz/src/bin/crane-dummy-bar/main.rs | 14 ------ .../qux/src/bin/crane-dummy-qux/main.rs | 14 ------ docs/API.md | 3 ++ lib/mkDummySrc.nix | 50 ++++++++++++++++--- lib/setupHooks/inheritCargoArtifactsHook.sh | 14 +++++- 19 files changed, 74 insertions(+), 174 deletions(-) delete mode 100644 checks/mkDummySrcTests/custom-dummyrs/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs delete mode 100644 checks/mkDummySrcTests/single-alt/expected/src/lib.rs delete mode 100644 checks/mkDummySrcTests/single/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs delete mode 100644 checks/mkDummySrcTests/workspace-bindeps/expected/foo/src/bin/crane-dummy-foo/main.rs delete mode 100644 checks/mkDummySrcTests/workspace-bindeps/expected/src/bin/crane-dummy-workspace-bindeps/main.rs delete mode 100644 checks/mkDummySrcTests/workspace-bindeps/expected/src/lib.rs rename checks/mkDummySrcTests/{customized/expected/src/bin/crane-dummy-mkDummySrcSimple => workspace-bindeps/expected/src}/main.rs (100%) delete mode 100644 checks/mkDummySrcTests/workspace-inheritance/expected/hello/src/bin/crane-dummy-hello/main.rs delete mode 100644 checks/mkDummySrcTests/workspace-inheritance/expected/print/src/bin/crane-dummy-print/main.rs delete mode 100644 checks/mkDummySrcTests/workspace-inheritance/expected/print/src/lib.rs rename checks/mkDummySrcTests/{single-alt/expected/src/bin/crane-dummy-mkDummySrcSimple => workspace-inheritance/expected/print/src}/main.rs (100%) delete mode 100644 checks/mkDummySrcTests/workspace-inheritance/expected/world/src/bin/crane-dummy-world/main.rs delete mode 100644 checks/mkDummySrcTests/workspace/expected/member/foo/bar/baz/src/bin/crane-dummy-bar/main.rs delete mode 100644 checks/mkDummySrcTests/workspace/expected/member/qux/src/bin/crane-dummy-qux/main.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 810b56a3..bd0944a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed * **Breaking**: dropped compatibility for Nix versions below 2.24.10 * **Breaking**: dropped compatibility for nixpkgs-23.11 +* `mkDummySrc` has been reworked to match cargo's `autobin` detection logic, + meaning that only real binary targets defined by the project will be dummified + if they exist (no more injecting `src/bin/crane-dummy-*`). This does mean that + adding a new bin target definition will invalidate caches and require + rebuilding all dependencies once more. (If this is a frequent enough + occurrence for your project to cause headaches, please open an issue!) ## [0.19.4] - 2024-11-30 diff --git a/checks/default.nix b/checks/default.nix index b7a92bb0..608df859 100644 --- a/checks/default.nix +++ b/checks/default.nix @@ -469,7 +469,7 @@ in lib.optionalAttrs x64Linux (noStdLib.buildPackage { src = noStdLib.cleanCargoSource ./no_std; CARGO_BUILD_TARGET = "x86_64-unknown-none"; - cargoCheckExtraArgs = "--lib --bins --examples"; + cargoCheckExtraArgs = "--bins --examples"; doCheck = false; }); @@ -485,7 +485,7 @@ in lib.optionalAttrs x64Linux (bindepsLib.buildPackage { src = bindepsLib.cleanCargoSource ./bindeps; CARGO_BUILD_TARGET = "x86_64-unknown-none"; - cargoCheckExtraArgs = "--lib --bins --examples"; + cargoCheckExtraArgs = "--bins --examples"; doCheck = false; }); @@ -808,6 +808,13 @@ in pname = "workspace-root"; }; + # https://github.com/ipetkov/crane/issues/268 + workspaceRootSpecificBin = myLib.buildPackage { + src = myLib.cleanCargoSource ./workspace-root; + pname = "workspace-root"; + cargoExtraArgs = "--bin print"; + }; + workspaceGit = myLib.buildPackage { src = myLib.cleanCargoSource ./workspace-git; }; diff --git a/checks/mkDummySrcTests/custom-dummyrs/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs b/checks/mkDummySrcTests/custom-dummyrs/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs deleted file mode 100644 index 4607b1c4..00000000 --- a/checks/mkDummySrcTests/custom-dummyrs/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(no_core, lang_items, start)] -#[no_std] -#[no_core] -// #[no_gods] -// #[no_masters] - -#[start] -fn main(_: isize, _: *const *const u8) -> isize { - 0 -} diff --git a/checks/mkDummySrcTests/single-alt/expected/src/lib.rs b/checks/mkDummySrcTests/single-alt/expected/src/lib.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/single-alt/expected/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/single/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs b/checks/mkDummySrcTests/single/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/single/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/workspace-bindeps/expected/foo/src/bin/crane-dummy-foo/main.rs b/checks/mkDummySrcTests/workspace-bindeps/expected/foo/src/bin/crane-dummy-foo/main.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/workspace-bindeps/expected/foo/src/bin/crane-dummy-foo/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/workspace-bindeps/expected/src/bin/crane-dummy-workspace-bindeps/main.rs b/checks/mkDummySrcTests/workspace-bindeps/expected/src/bin/crane-dummy-workspace-bindeps/main.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/workspace-bindeps/expected/src/bin/crane-dummy-workspace-bindeps/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/workspace-bindeps/expected/src/lib.rs b/checks/mkDummySrcTests/workspace-bindeps/expected/src/lib.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/workspace-bindeps/expected/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/customized/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs b/checks/mkDummySrcTests/workspace-bindeps/expected/src/main.rs similarity index 100% rename from checks/mkDummySrcTests/customized/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs rename to checks/mkDummySrcTests/workspace-bindeps/expected/src/main.rs diff --git a/checks/mkDummySrcTests/workspace-inheritance/expected/hello/src/bin/crane-dummy-hello/main.rs b/checks/mkDummySrcTests/workspace-inheritance/expected/hello/src/bin/crane-dummy-hello/main.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/workspace-inheritance/expected/hello/src/bin/crane-dummy-hello/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/workspace-inheritance/expected/print/src/bin/crane-dummy-print/main.rs b/checks/mkDummySrcTests/workspace-inheritance/expected/print/src/bin/crane-dummy-print/main.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/workspace-inheritance/expected/print/src/bin/crane-dummy-print/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/workspace-inheritance/expected/print/src/lib.rs b/checks/mkDummySrcTests/workspace-inheritance/expected/print/src/lib.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/workspace-inheritance/expected/print/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/single-alt/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs b/checks/mkDummySrcTests/workspace-inheritance/expected/print/src/main.rs similarity index 100% rename from checks/mkDummySrcTests/single-alt/expected/src/bin/crane-dummy-mkDummySrcSimple/main.rs rename to checks/mkDummySrcTests/workspace-inheritance/expected/print/src/main.rs diff --git a/checks/mkDummySrcTests/workspace-inheritance/expected/world/src/bin/crane-dummy-world/main.rs b/checks/mkDummySrcTests/workspace-inheritance/expected/world/src/bin/crane-dummy-world/main.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/workspace-inheritance/expected/world/src/bin/crane-dummy-world/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/workspace/expected/member/foo/bar/baz/src/bin/crane-dummy-bar/main.rs b/checks/mkDummySrcTests/workspace/expected/member/foo/bar/baz/src/bin/crane-dummy-bar/main.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/workspace/expected/member/foo/bar/baz/src/bin/crane-dummy-bar/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/checks/mkDummySrcTests/workspace/expected/member/qux/src/bin/crane-dummy-qux/main.rs b/checks/mkDummySrcTests/workspace/expected/member/qux/src/bin/crane-dummy-qux/main.rs deleted file mode 100644 index b6a90ffb..00000000 --- a/checks/mkDummySrcTests/workspace/expected/member/qux/src/bin/crane-dummy-qux/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::all)] -#![allow(dead_code)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_std)] -#![cfg_attr(any(target_os = "none", target_os = "uefi"), no_main)] - -#[allow(unused_extern_crates)] -extern crate core; - -#[cfg_attr(any(target_os = "none", target_os = "uefi"), panic_handler)] -fn panic(_info: &::core::panic::PanicInfo<'_>) -> ! { - loop {} -} - -pub fn main() {} diff --git a/docs/API.md b/docs/API.md index 2adbf1fa..0e52c808 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1268,6 +1268,9 @@ build caches. More specifically: - Any changes to the `[package]` definition such as name and version - Any changes to the name or path of any target (such as benches, bins, examples, libs, or tests) + - Any removal or new definition of a `[[bin]]` target, or, any removal or new + definition of a file under `src/bin` when `autolib` is enabled in the + `Cargo.toml` file (this setting is `true` by default) #### Required attributes * `src`: a source directory which should be turned into a "dummy" form diff --git a/lib/mkDummySrc.nix b/lib/mkDummySrc.nix index 3f03390f..4a7ef466 100644 --- a/lib/mkDummySrc.nix +++ b/lib/mkDummySrc.nix @@ -19,7 +19,6 @@ let inherit (builtins) dirOf concatStringsSep - hasAttr match storeDir; @@ -162,6 +161,9 @@ let cargoTomlDest = builtins.unsafeDiscardStringContext (removePrefix cargoTomlsBase (toString p)); parentDir = "$out/${dirOf cargoTomlDest}"; + # NB: do not use string interpolation or toString or else the path checks won't work + shallowJoinPath = rest: p + "/../${rest}"; + # Override the cleaned Cargo.toml with a build script which points to our dummy # source. We need a build script present to cache build-dependencies, which can be # achieved by dropping a build.rs file in the source directory. Except that is the most @@ -187,10 +189,44 @@ let else cleanedCargoToml; - safeStubLib = - if hasAttr "lib" trimmedCargoToml - then cpDummy parentDir (trimmedCargoToml.lib.path or "src/lib.rs") - else ""; + + hasDir = root: sub: root.${sub} or "" == "directory"; + hasFile = root: sub: root.${sub} or "" == "regular"; + + crateRoot = builtins.readDir (shallowJoinPath "."); + srcDir = lib.optionalAttrs (hasDir crateRoot "src") (builtins.readDir (shallowJoinPath "src")); + hasLibrs = (trimmedCargoToml.package.autolib or true) && hasFile srcDir "lib.rs"; + autobins = trimmedCargoToml.package.autobins or true; + hasMainrs = autobins && hasFile srcDir "main.rs"; + srcBinDir = lib.optionalAttrs (autobins && hasDir srcDir "bin") (builtins.readDir (shallowJoinPath "src/bin")); + + # NB: sort the result here to be as deterministic as possible and avoid rebuilds if + # directory listings happen to change their order + discoveredBins = concatStringsSep " " (lib.sortOn (x: x) (lib.filter (p: p != null) + (lib.flip map (lib.attrsToList srcBinDir) ({ name, value }: + let + short = "src/bin/${name}"; + long = "${short}/main.rs"; + in + lib.escapeShellArg ( + if value == "regular" + then short + else if value == "directory" && builtins.pathExists (shallowJoinPath long) + then long + else null + ) + )) + )); + + stubBins = ''( + cd ${parentDir} + echo ${discoveredBins} | xargs --no-run-if-empty -n1 dirname | sort -u | xargs --no-run-if-empty mkdir -p + echo ${discoveredBins} | xargs --no-run-if-empty -n1 cp -f ${dummyrs} + )''; + + safeStubLib = lib.optionalString + (trimmedCargoToml ? lib || hasLibrs) + (cpDummy parentDir (trimmedCargoToml.lib.path or "src/lib.rs")); safeStubList = attr: defaultPath: let @@ -205,8 +241,8 @@ let cp ${writeTOML "Cargo.toml" trimmedCargoToml} $out/${cargoTomlDest} '' + optionalString (trimmedCargoToml ? package) '' # To build regular and dev dependencies (cargo build + cargo test) - ${cpDummy parentDir "src/lib.rs"} - ${cpDummy parentDir "src/bin/crane-dummy-${trimmedCargoToml.package.name or "no-name"}/main.rs"} + ${lib.optionalString hasMainrs (cpDummy parentDir "src/main.rs")} + ${stubBins} # Stub all other targets in case they have particular feature combinations ${safeStubLib} diff --git a/lib/setupHooks/inheritCargoArtifactsHook.sh b/lib/setupHooks/inheritCargoArtifactsHook.sh index 582c06b9..0235159e 100644 --- a/lib/setupHooks/inheritCargoArtifactsHook.sh +++ b/lib/setupHooks/inheritCargoArtifactsHook.sh @@ -74,10 +74,22 @@ inheritCargoArtifacts() { --executability \ --exclude 'deps/*.rlib' \ --exclude 'deps/*.rmeta' \ - --exclude '.cargo-lock' \ "${preparedArtifacts}/" \ "${cargoTargetDir}/" + # NB: cargo also doesn't like it if `.cargo-lock` files remain with a + # timestamp in the distant past so we need to delete them here + # NB: `.cargo-lock` files tend to appear in "top level" profile artifact directories. + # Those directories usually contain a `*.d` file for each binary target, but these are NOT + # content addressed, so we will want to copy them directly so they become writable in place + find "${cargoTargetDir}" -name '.cargo-lock' -delete \ + -execdir bash -c ' + for f in *.d; do + cp --preserve=timestamps --no-preserve=ownership --remove-destination "$(readlink "${f}")" "${f}" + chmod u+w "${f}" + done + ' \; + local linkCandidates=$(mktemp linkCandidatesXXXX.txt) find "${preparedArtifacts}" \ '(' -path '*/deps/*.rlib' -or -path '*/deps/*.rmeta' ')' \