Skip to content

Commit

Permalink
mkDummySrc: rework to only stub bins if they actually exist
Browse files Browse the repository at this point in the history
  • Loading branch information
ipetkov committed Dec 1, 2024
1 parent da87d1a commit 7e09a69
Show file tree
Hide file tree
Showing 19 changed files with 74 additions and 174 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

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

Expand All @@ -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;
});

Expand Down Expand Up @@ -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;
};
Expand Down

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
Expand Up @@ -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
Expand Down
50 changes: 43 additions & 7 deletions lib/mkDummySrc.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ let
inherit (builtins)
dirOf
concatStringsSep
hasAttr
match
storeDir;

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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}
Expand Down
14 changes: 13 additions & 1 deletion lib/setupHooks/inheritCargoArtifactsHook.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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' ')' \
Expand Down

0 comments on commit 7e09a69

Please sign in to comment.