Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mkDummySrc: rework to only stub bins if they actually exist #752

Merged
merged 1 commit into from
Dec 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
mkDummySrc: rework to only stub bins if they actually exist
ipetkov committed Dec 1, 2024
commit 7e09a69d6713e926b38bfcbd7028cac15fcd0012
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

11 changes: 9 additions & 2 deletions checks/default.nix
Original file line number Diff line number Diff line change
@@ -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;
};

This file was deleted.

14 changes: 0 additions & 14 deletions checks/mkDummySrcTests/single-alt/expected/src/lib.rs

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

14 changes: 0 additions & 14 deletions checks/mkDummySrcTests/workspace-bindeps/expected/src/lib.rs

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

3 changes: 3 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
@@ -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
50 changes: 43 additions & 7 deletions lib/mkDummySrc.nix
Original file line number Diff line number Diff line change
@@ -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}
14 changes: 13 additions & 1 deletion lib/setupHooks/inheritCargoArtifactsHook.sh
Original file line number Diff line number Diff line change
@@ -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' ')' \