Skip to content

Commit b1add4b

Browse files
committed
Auto merge of #7030 - Mark-Simulacrum:support-new-dep-info, r=alexcrichton
Support absolute paths in dep-info files These changes are a little more invasive then I would've liked, but I couldn't come up with a significantly better way to structure this. Comments (or backwards-compat) concerns are appreciated, of course! cc rust-lang/rust#61727 r? @alexcrichton
2 parents fa05862 + 34fd5cc commit b1add4b

File tree

4 files changed

+138
-15
lines changed

4 files changed

+138
-15
lines changed

src/cargo/core/compiler/fingerprint.rs

+53-7
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ impl LocalFingerprint {
549549
// unit has never been compiled!
550550
LocalFingerprint::CheckDepInfo { dep_info } => {
551551
let dep_info = target_root.join(dep_info);
552-
if let Some(paths) = parse_dep_info(pkg_root, &dep_info)? {
552+
if let Some(paths) = parse_dep_info(pkg_root, target_root, &dep_info)? {
553553
Ok(find_stale_file(&dep_info, paths.iter()))
554554
} else {
555555
Ok(Some(StaleFile::Missing(dep_info)))
@@ -1408,15 +1408,30 @@ fn log_compare(unit: &Unit<'_>, compare: &CargoResult<()>) {
14081408
}
14091409

14101410
// Parse the dep-info into a list of paths
1411-
pub fn parse_dep_info(pkg_root: &Path, dep_info: &Path) -> CargoResult<Option<Vec<PathBuf>>> {
1411+
pub fn parse_dep_info(
1412+
pkg_root: &Path,
1413+
target_root: &Path,
1414+
dep_info: &Path,
1415+
) -> CargoResult<Option<Vec<PathBuf>>> {
14121416
let data = match paths::read_bytes(dep_info) {
14131417
Ok(data) => data,
14141418
Err(_) => return Ok(None),
14151419
};
14161420
let paths = data
14171421
.split(|&x| x == 0)
14181422
.filter(|x| !x.is_empty())
1419-
.map(|p| util::bytes2path(p).map(|p| pkg_root.join(p)))
1423+
.map(|p| {
1424+
let ty = match DepInfoPathType::from_byte(p[0]) {
1425+
Some(ty) => ty,
1426+
None => return Err(internal("dep-info invalid")),
1427+
};
1428+
let path = util::bytes2path(&p[1..])?;
1429+
match ty {
1430+
DepInfoPathType::PackageRootRelative => Ok(pkg_root.join(path)),
1431+
// N.B. path might be absolute here in which case the join will have no effect
1432+
DepInfoPathType::TargetRootRelative => Ok(target_root.join(path)),
1433+
}
1434+
})
14201435
.collect::<Result<Vec<_>, _>>()?;
14211436
if paths.is_empty() {
14221437
Ok(None)
@@ -1503,6 +1518,25 @@ fn filename<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> String {
15031518
format!("{}{}-{}", flavor, kind, file_stem)
15041519
}
15051520

1521+
#[repr(u8)]
1522+
enum DepInfoPathType {
1523+
// src/, e.g. src/lib.rs
1524+
PackageRootRelative = 1,
1525+
// target/debug/deps/lib...
1526+
// or an absolute path /.../sysroot/...
1527+
TargetRootRelative = 2,
1528+
}
1529+
1530+
impl DepInfoPathType {
1531+
fn from_byte(b: u8) -> Option<DepInfoPathType> {
1532+
match b {
1533+
1 => Some(DepInfoPathType::PackageRootRelative),
1534+
2 => Some(DepInfoPathType::TargetRootRelative),
1535+
_ => None,
1536+
}
1537+
}
1538+
}
1539+
15061540
/// Parses the dep-info file coming out of rustc into a Cargo-specific format.
15071541
///
15081542
/// This function will parse `rustc_dep_info` as a makefile-style dep info to
@@ -1522,8 +1556,9 @@ fn filename<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> String {
15221556
pub fn translate_dep_info(
15231557
rustc_dep_info: &Path,
15241558
cargo_dep_info: &Path,
1525-
pkg_root: &Path,
15261559
rustc_cwd: &Path,
1560+
pkg_root: &Path,
1561+
target_root: &Path,
15271562
) -> CargoResult<()> {
15281563
let target = parse_rustc_dep_info(rustc_dep_info)?;
15291564
let deps = &target
@@ -1533,9 +1568,20 @@ pub fn translate_dep_info(
15331568

15341569
let mut new_contents = Vec::new();
15351570
for file in deps {
1536-
let absolute = rustc_cwd.join(file);
1537-
let path = absolute.strip_prefix(pkg_root).unwrap_or(&absolute);
1538-
new_contents.extend(util::path2bytes(path)?);
1571+
let file = rustc_cwd.join(file);
1572+
let (ty, path) = if let Ok(stripped) = file.strip_prefix(pkg_root) {
1573+
(DepInfoPathType::PackageRootRelative, stripped)
1574+
} else if let Ok(stripped) = file.strip_prefix(target_root) {
1575+
(DepInfoPathType::TargetRootRelative, stripped)
1576+
} else {
1577+
// It's definitely not target root relative, but this is an absolute path (since it was
1578+
// joined to rustc_cwd) and as such re-joining it later to the target root will have no
1579+
// effect.
1580+
assert!(file.is_absolute(), "{:?} is absolute", file);
1581+
(DepInfoPathType::TargetRootRelative, &*file)
1582+
};
1583+
new_contents.push(ty as u8);
1584+
new_contents.extend(util::path2bytes(&path)?);
15391585
new_contents.push(0);
15401586
}
15411587
paths::write(cargo_dep_info, &new_contents)?;

src/cargo/core/compiler/mod.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -315,13 +315,19 @@ fn rustc<'a, 'cfg>(
315315
}
316316

317317
if rustc_dep_info_loc.exists() {
318-
fingerprint::translate_dep_info(&rustc_dep_info_loc, &dep_info_loc, &pkg_root, &cwd)
319-
.chain_err(|| {
320-
internal(format!(
321-
"could not parse/generate dep info at: {}",
322-
rustc_dep_info_loc.display()
323-
))
324-
})?;
318+
fingerprint::translate_dep_info(
319+
&rustc_dep_info_loc,
320+
&dep_info_loc,
321+
&cwd,
322+
&pkg_root,
323+
&root_output,
324+
)
325+
.chain_err(|| {
326+
internal(format!(
327+
"could not parse/generate dep info at: {}",
328+
rustc_dep_info_loc.display()
329+
))
330+
})?;
325331
filetime::set_file_times(dep_info_loc, timestamp, timestamp)?;
326332
}
327333

src/cargo/core/compiler/output_depinfo.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ fn add_deps_for_unit<'a, 'b>(
3939
if !unit.mode.is_run_custom_build() {
4040
// Add dependencies from rustc dep-info output (stored in fingerprint directory)
4141
let dep_info_loc = fingerprint::dep_info_loc(context, unit);
42-
if let Some(paths) = fingerprint::parse_dep_info(unit.pkg.root(), &dep_info_loc)? {
42+
if let Some(paths) = fingerprint::parse_dep_info(
43+
unit.pkg.root(),
44+
context.files().host_root(),
45+
&dep_info_loc,
46+
)? {
4347
for path in paths {
4448
deps.insert(path);
4549
}

tests/testsuite/freshness.rs

+67
Original file line numberDiff line numberDiff line change
@@ -2026,3 +2026,70 @@ fn rename_with_path_deps() {
20262026
.with_stderr("[FINISHED] [..]")
20272027
.run();
20282028
}
2029+
2030+
#[cargo_test]
2031+
fn move_target_directory_with_path_deps() {
2032+
let p = project()
2033+
.file(
2034+
"Cargo.toml",
2035+
r#"
2036+
[project]
2037+
name = "foo"
2038+
version = "0.5.0"
2039+
authors = []
2040+
2041+
[dependencies]
2042+
a = { path = "a" }
2043+
"#,
2044+
)
2045+
.file(
2046+
"a/Cargo.toml",
2047+
r#"
2048+
[project]
2049+
name = "a"
2050+
version = "0.5.0"
2051+
authors = []
2052+
"#,
2053+
)
2054+
.file("src/lib.rs", "extern crate a; pub use a::print_msg;")
2055+
.file(
2056+
"a/build.rs",
2057+
r###"
2058+
use std::env;
2059+
use std::fs;
2060+
use std::path::Path;
2061+
2062+
fn main() {
2063+
println!("cargo:rerun-if-changed=build.rs");
2064+
let out_dir = env::var("OUT_DIR").unwrap();
2065+
let dest_path = Path::new(&out_dir).join("hello.rs");
2066+
fs::write(&dest_path, r#"
2067+
pub fn message() -> &'static str {
2068+
"Hello, World!"
2069+
}
2070+
"#).unwrap();
2071+
}
2072+
"###,
2073+
)
2074+
.file(
2075+
"a/src/lib.rs",
2076+
r#"
2077+
include!(concat!(env!("OUT_DIR"), "/hello.rs"));
2078+
pub fn print_msg() { message(); }
2079+
"#,
2080+
);
2081+
let p = p.build();
2082+
2083+
let mut parent = p.root();
2084+
parent.pop();
2085+
2086+
p.cargo("build").run();
2087+
2088+
let new_target = p.root().join("target2");
2089+
fs::rename(p.root().join("target"), &new_target).unwrap();
2090+
2091+
p.cargo("build")
2092+
.env("CARGO_TARGET_DIR", &new_target)
2093+
.with_stderr("[FINISHED] [..]")
2094+
.run();
2095+
}

0 commit comments

Comments
 (0)