mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Auto merge of #5181 - alexcrichton:selectively-write-dep-info, r=matklad
Don't rewrite dep-info files if they don't change Similar to how we treat lock files, read the contents, compare, and if they're the same don't actually write the file. Closes #5172
This commit is contained in:
commit
1eb4c8f1b4
@ -738,29 +738,13 @@ pub fn translate_dep_info(rustc_dep_info: &Path,
|
|||||||
cargo_dep_info: &Path,
|
cargo_dep_info: &Path,
|
||||||
pkg_root: &Path,
|
pkg_root: &Path,
|
||||||
rustc_cwd: &Path) -> CargoResult<()> {
|
rustc_cwd: &Path) -> CargoResult<()> {
|
||||||
let contents = paths::read(rustc_dep_info)?;
|
let target = parse_rustc_dep_info(rustc_dep_info)?;
|
||||||
let line = match contents.lines().next() {
|
let deps = &target.get(0).ok_or_else(|| {
|
||||||
Some(line) => line,
|
internal("malformed dep-info format, no targets".to_string())
|
||||||
None => return Ok(()),
|
})?.1;
|
||||||
};
|
|
||||||
let pos = line.find(": ").ok_or_else(|| {
|
|
||||||
internal(format!("dep-info not in an understood format: {}",
|
|
||||||
rustc_dep_info.display()))
|
|
||||||
})?;
|
|
||||||
let deps = &line[pos + 2..];
|
|
||||||
|
|
||||||
let mut new_contents = Vec::new();
|
let mut new_contents = Vec::new();
|
||||||
let mut deps = deps.split(' ').map(|s| s.trim()).filter(|s| !s.is_empty());
|
for file in deps {
|
||||||
while let Some(s) = deps.next() {
|
|
||||||
let mut file = s.to_string();
|
|
||||||
while file.ends_with('\\') {
|
|
||||||
file.pop();
|
|
||||||
file.push(' ');
|
|
||||||
file.push_str(deps.next().ok_or_else(|| {
|
|
||||||
internal("malformed dep-info format, trailing \\".to_string())
|
|
||||||
})?);
|
|
||||||
}
|
|
||||||
|
|
||||||
let absolute = rustc_cwd.join(file);
|
let absolute = rustc_cwd.join(file);
|
||||||
let path = absolute.strip_prefix(pkg_root).unwrap_or(&absolute);
|
let path = absolute.strip_prefix(pkg_root).unwrap_or(&absolute);
|
||||||
new_contents.extend(util::path2bytes(path)?);
|
new_contents.extend(util::path2bytes(path)?);
|
||||||
@ -770,3 +754,29 @@ pub fn translate_dep_info(rustc_dep_info: &Path,
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_rustc_dep_info(rustc_dep_info: &Path)
|
||||||
|
-> CargoResult<Vec<(String, Vec<String>)>>
|
||||||
|
{
|
||||||
|
let contents = paths::read(rustc_dep_info)?;
|
||||||
|
contents.lines()
|
||||||
|
.filter_map(|l| l.find(": ").map(|i| (l, i)))
|
||||||
|
.map(|(line, pos)| {
|
||||||
|
let target = &line[..pos];
|
||||||
|
let mut deps = line[pos + 2..].split_whitespace();
|
||||||
|
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
while let Some(s) = deps.next() {
|
||||||
|
let mut file = s.to_string();
|
||||||
|
while file.ends_with('\\') {
|
||||||
|
file.pop();
|
||||||
|
file.push(' ');
|
||||||
|
file.push_str(deps.next().ok_or_else(|| {
|
||||||
|
internal("malformed dep-info format, trailing \\".to_string())
|
||||||
|
})?);
|
||||||
|
}
|
||||||
|
ret.push(file);
|
||||||
|
}
|
||||||
|
Ok((target.to_string(), ret))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::{HashSet, BTreeSet};
|
||||||
use std::io::{Write, BufWriter};
|
use std::io::{Write, BufWriter};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -21,7 +21,7 @@ fn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResul
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_deps_for_unit<'a, 'b>(
|
fn add_deps_for_unit<'a, 'b>(
|
||||||
deps: &mut HashSet<PathBuf>,
|
deps: &mut BTreeSet<PathBuf>,
|
||||||
context: &mut Context<'a, 'b>,
|
context: &mut Context<'a, 'b>,
|
||||||
unit: &Unit<'a>,
|
unit: &Unit<'a>,
|
||||||
visited: &mut HashSet<Unit<'a>>,
|
visited: &mut HashSet<Unit<'a>>,
|
||||||
@ -67,7 +67,7 @@ fn add_deps_for_unit<'a, 'b>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> {
|
pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> {
|
||||||
let mut deps = HashSet::new();
|
let mut deps = BTreeSet::new();
|
||||||
let mut visited = HashSet::new();
|
let mut visited = HashSet::new();
|
||||||
let success = add_deps_for_unit(&mut deps, context, unit, &mut visited).is_ok();
|
let success = add_deps_for_unit(&mut deps, context, unit, &mut visited).is_ok();
|
||||||
let basedir_string;
|
let basedir_string;
|
||||||
@ -79,15 +79,31 @@ pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) ->
|
|||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
let deps = deps.iter()
|
||||||
|
.map(|f| render_filename(f, basedir))
|
||||||
|
.collect::<CargoResult<Vec<_>>>()?;
|
||||||
|
|
||||||
for &(_, ref link_dst, _) in context.target_filenames(unit)?.iter() {
|
for &(_, ref link_dst, _) in context.target_filenames(unit)?.iter() {
|
||||||
if let Some(ref link_dst) = *link_dst {
|
if let Some(ref link_dst) = *link_dst {
|
||||||
let output_path = link_dst.with_extension("d");
|
let output_path = link_dst.with_extension("d");
|
||||||
if success {
|
if success {
|
||||||
let mut outfile = BufWriter::new(File::create(output_path)?);
|
|
||||||
let target_fn = render_filename(link_dst, basedir)?;
|
let target_fn = render_filename(link_dst, basedir)?;
|
||||||
|
|
||||||
|
// If nothing changed don't recreate the file which could alter
|
||||||
|
// its mtime
|
||||||
|
if let Ok(previous) = fingerprint::parse_rustc_dep_info(&output_path) {
|
||||||
|
if previous.len() == 1 &&
|
||||||
|
previous[0].0 == target_fn &&
|
||||||
|
previous[0].1 == deps {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise write it all out
|
||||||
|
let mut outfile = BufWriter::new(File::create(output_path)?);
|
||||||
write!(outfile, "{}:", target_fn)?;
|
write!(outfile, "{}:", target_fn)?;
|
||||||
for dep in &deps {
|
for dep in &deps {
|
||||||
write!(outfile, " {}", render_filename(dep, basedir)?)?;
|
write!(outfile, " {}", dep)?;
|
||||||
}
|
}
|
||||||
writeln!(outfile, "")?;
|
writeln!(outfile, "")?;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use cargotest::support::{basic_bin_manifest, main_file, execs, project};
|
use cargotest::support::{basic_bin_manifest, main_file, execs, project};
|
||||||
|
use filetime::FileTime;
|
||||||
use hamcrest::{assert_that, existing_file};
|
use hamcrest::{assert_that, existing_file};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -79,3 +80,27 @@ fn build_dep_info_dylib() {
|
|||||||
assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
|
assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
|
||||||
assert_that(&p.example_lib("ex", "dylib").with_extension("d"), existing_file());
|
assert_that(&p.example_lib("ex", "dylib").with_extension("d"), existing_file());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_rewrite_if_no_change() {
|
||||||
|
let p = project("foo")
|
||||||
|
.file("Cargo.toml", r#"
|
||||||
|
[package]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = []
|
||||||
|
"#)
|
||||||
|
.file("src/lib.rs", "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_that(p.cargo("build"), execs().with_status(0));
|
||||||
|
let dep_info = p.root().join("target/debug/libfoo.d");
|
||||||
|
let metadata1 = dep_info.metadata().unwrap();
|
||||||
|
assert_that(p.cargo("build"), execs().with_status(0));
|
||||||
|
let metadata2 = dep_info.metadata().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
FileTime::from_last_modification_time(&metadata1),
|
||||||
|
FileTime::from_last_modification_time(&metadata2),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user