-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
Problem
Cargo works around dependencies passed from rustc's depfile with a trailing slash so that Windows-style paths work as expected:
cargo/src/cargo/core/compiler/fingerprint/dep_info.rs
Lines 410 to 416 in bee8cb7
while file.ends_with('\\') { | |
file.pop(); | |
file.push(' '); | |
file.push_str(deps.next().ok_or_else(|| { | |
crate::util::internal("malformed dep-info format, trailing \\") | |
})?); | |
} |
The dependency format being what it is requires that paths don't end with a trailing backslash.
When writing its own depfile, however, there is an edge case where cargo accidentally does emit a path with a trailing backslash.
What seems to happen is that rust_cwd
seems to be a path with a trailing backslash on Windows.
Joining any path with an empty path is effectively a no-op. Imporantly, this means that the trailing backslash is preserved.
In here
cargo/src/cargo/core/compiler/fingerprint/dep_info.rs
Lines 347 to 352 in bee8cb7
let abs_file = rustc_cwd.join(file); | |
// If canonicalization fails, just use the abs path. There is currently | |
// a bug where --remap-path-prefix is affecting .d files, causing them | |
// to point to non-existent paths. | |
let canon_file = | |
crate::util::try_canonicalize(&abs_file).unwrap_or_else(|_| abs_file.clone()); |
cargo joins rust_cwd
with the potentially-empty path, then passes it to canonicalize/absolute, both of which will also keep the trailing backslash. Because the check mentioned above is not repeaded here, an invalid .d
dependency line is emitted.
Steps
There are two ways I know of to trigger the bug:
- via cargo build script passing an empty string:
fn main() {
println!("cargo::rerun-if-changed=");
}
This can easily happen with a computed path that ends up being empty, for example:
fn main() {
let some_calculated_path = calculate_path(); // might become an empty path!
println!("cargo::rerun-if-changed={}", some_calculated_path.display());
}
We end up with this in the target depfile target\debug\a.d
:
X:\rustprojs\buggy-test\target\debug\a.exe: X:\rustprojs\buggy-test\ X:\rustprojs\buggy-test\build.rs X:\rustprojs\buggy-test\src\main.rs
- (nightly-only) via proc macro that passes
"."
(but not""
!) astracked_path
:
#![feature(track_path)]
use proc_macro::TokenStream;
#[proc_macro]
pub fn testing(stream: TokenStream) -> TokenStream {
proc_macro::tracked_path::path(".");
stream
}
This can similarly easily happen with a calculated path that is .
-relative at some point.
We end up with:
X:\rustprojs\buggy-test\target\debug\a.exe: X:\rustprojs\buggy-test\ X:\rustprojs\buggy-test\build.rs X:\rustprojs\buggy-test\procmacro\src\lib.rs X:\rustprojs\buggy-test\src\main.rs
Because of the trailing backslash, the first dependency becomes 'X:\rustprojs\buggy-test\ X:\rustprojs\buggy-test\build.rs'
, which of course is an invalid path.
Relatedly, adding a backslash to the path in the proc macro causes us to fail building:
#![feature(track_path)]
use proc_macro::TokenStream;
#[proc_macro]
pub fn testing(stream: TokenStream) -> TokenStream {
proc_macro::tracked_path::path(".\\");
stream
}
Results in this, triggering the check/workaround mentioned at the top:
error: could not parse/generate dep info at: X:\rustprojs\buggy-test\target\debug\deps\a.d
Caused by:
malformed dep-info format, trailing \
note: this is an unexpected cargo internal error
note: we would appreciate a bug report: https://github.com/rust-lang/cargo/issues/
Possible Solution(s)
A few ways would come to mind:
- Ensure
rust_cwd
does not have a trailing slash - Check that
abs_file
is different fromrust_cwd
- Apply the same
\
check mentioned at the top when writing out cargo's depfile - (likely not valid across platforms) Remove trailing backslashes in general as they are never valid for depfiles
I'd be happy to provide a patch if I could get some guidance on what the preferred way to fix this is.
Notes
No response
Version
Verified on stable and on the current nightly:
cargo 1.92.0-nightly (81c3f77a4 2025-10-10)
release: 1.92.0-nightly
commit-hash: 81c3f77a467359c8be6bc747dc93ec66a6e4ce11
commit-date: 2025-10-10
host: x86_64-pc-windows-msvc
libgit2: 1.9.1 (sys:0.20.2 vendored)
libcurl: 8.15.0-DEV (sys:0.4.83+curl-8.15.0 vendored ssl:Schannel)
os: Windows 10.0.26200 (Windows 11 Professional) [64-bit]