Open
Description
Describe the problem you are trying to solve
When cargo registers information used later on to figure out whether or not to recompile a unit, the path to the source is tracked in the fingerprint:
cargo/src/cargo/core/compiler/mod.rs
Lines 684 to 697 in 83d086d
However this path is not canonicalized, meaning that e.g. symlinks aren't resolved before the source paths are added to the fingerprint.
This causes two kinds of issues:
- It's convenient to use symlinks to point to a local registry when using source replacement. But since the paths are not canonicalized this can cause spurious rebuilds if the symlink source changes (while the symlink target doesn't).
- Same use case as above, but say the symlink source doesn't change, while the symlink target changes. In this case cargo will reuse outdated build artifacts.
Describe the solution you'd like
The paths can be canonicalized before being returned:
diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs
index 628ac8bb..dcc668e8 100644
--- a/src/cargo/core/compiler/mod.rs
+++ b/src/cargo/core/compiler/mod.rs
@@ -688,6 +688,7 @@ fn path_args(bcx: &BuildContext<'_, '_>, unit: &Unit<'_>) -> (PathBuf, PathBuf)
TargetSourcePath::Metabuild => unit.pkg.manifest().metabuild_path(bcx.ws.target_dir()),
};
assert!(src.is_absolute());
+ let src = fs::canonicalize(&src).unwrap_or(src);
if unit.pkg.package_id().source_id().is_path() {
if let Ok(path) = src.strip_prefix(ws_root) {
return (path.to_path_buf(), ws_root.to_path_buf());
One drawback is that cache miss info (with CARGO_LOG=cargo::core::compiler::fingerprint=trace
) may confuse the user in the presence of symlinks.