Skip to content

Commit 5511a93

Browse files
authoredSep 16, 2016
Auto merge of #36439 - alexcrichton:fix-rustbuild, r=japaric
rustbuild: Fix dependency tracking with new Cargo The recent Cargo update changed filenames, which broke a lot of incremental rustbuild builds. What it thought were the output files were indeed no longer the output files! (wreaking havoc). This commit updates this to stop guessing filenames of Cargo and just manage stamp files instead.
2 parents 1265cbf + 194a91b commit 5511a93

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed
 

‎src/bootstrap/compile.rs

+37-8
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
//! compiler. This module is also responsible for assembling the sysroot as it
1717
//! goes along from the output of the previous stage.
1818
19+
use std::cmp;
1920
use std::collections::HashMap;
20-
use std::fs;
21+
use std::fs::{self, File};
2122
use std::path::{Path, PathBuf};
2223
use std::process::Command;
2324

2425
use build_helper::output;
26+
use filetime::FileTime;
2527

2628
use util::{exe, staticlib, libdir, mtime, is_dylib, copy};
2729
use {Build, Compiler, Mode};
@@ -76,6 +78,7 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
7678
}
7779

7880
build.run(&mut cargo);
81+
update_mtime(&libstd_stamp(build, compiler, target));
7982
std_link(build, target, compiler, compiler.host);
8083
}
8184

@@ -149,11 +152,12 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
149152
println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
150153
compiler.host, target);
151154
let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
152-
build.clear_if_dirty(&out_dir, &libstd_shim(build, compiler, target));
155+
build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
153156
let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build");
154157
cargo.arg("--manifest-path")
155158
.arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
156159
build.run(&mut cargo);
160+
update_mtime(&libtest_stamp(build, compiler, target));
157161
test_link(build, target, compiler, compiler.host);
158162
}
159163

@@ -181,7 +185,7 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
181185
compiler.stage, compiler.host, target);
182186

183187
let out_dir = build.cargo_out(compiler, Mode::Librustc, target);
184-
build.clear_if_dirty(&out_dir, &libtest_shim(build, compiler, target));
188+
build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target));
185189

186190
let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build");
187191
cargo.arg("--features").arg(build.rustc_features())
@@ -246,14 +250,14 @@ pub fn rustc_link(build: &Build,
246250

247251
/// Cargo's output path for the standard library in a given stage, compiled
248252
/// by a particular compiler for the specified target.
249-
fn libstd_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
250-
build.cargo_out(compiler, Mode::Libstd, target).join("libstd_shim.rlib")
253+
fn libstd_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
254+
build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
251255
}
252256

253257
/// Cargo's output path for libtest in a given stage, compiled by a particular
254258
/// compiler for the specified target.
255-
fn libtest_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
256-
build.cargo_out(compiler, Mode::Libtest, target).join("libtest_shim.rlib")
259+
fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
260+
build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
257261
}
258262

259263
fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
@@ -366,10 +370,35 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
366370
// Maybe when libstd is compiled it should clear out the rustc of the
367371
// corresponding stage?
368372
// let out_dir = build.cargo_out(stage, &host, Mode::Librustc, target);
369-
// build.clear_if_dirty(&out_dir, &libstd_shim(build, stage, &host, target));
373+
// build.clear_if_dirty(&out_dir, &libstd_stamp(build, stage, &host, target));
370374

371375
let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build");
372376
cargo.arg("--manifest-path")
373377
.arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool)));
374378
build.run(&mut cargo);
375379
}
380+
381+
/// Updates the mtime of a stamp file if necessary, only changing it if it's
382+
/// older than some other file in the same directory.
383+
///
384+
/// We don't know what file Cargo is going to output (because there's a hash in
385+
/// the file name) but we know where it's going to put it. We use this helper to
386+
/// detect changes to that output file by looking at the modification time for
387+
/// all files in a directory and updating the stamp if any are newer.
388+
fn update_mtime(path: &Path) {
389+
let mut max = None;
390+
if let Ok(entries) = path.parent().unwrap().read_dir() {
391+
for entry in entries.map(|e| t!(e)) {
392+
if t!(entry.file_type()).is_file() {
393+
let meta = t!(entry.metadata());
394+
let time = FileTime::from_last_modification_time(&meta);
395+
max = cmp::max(max, Some(time));
396+
}
397+
}
398+
}
399+
400+
if !max.is_none() && max <= Some(mtime(path)) {
401+
return
402+
}
403+
t!(File::create(path));
404+
}

‎src/bootstrap/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,8 @@ impl Build {
579579
if mtime(&stamp) < mtime(input) {
580580
self.verbose(&format!("Dirty - {}", dir.display()));
581581
let _ = fs::remove_dir_all(dir);
582+
} else if stamp.exists() {
583+
return
582584
}
583585
t!(fs::create_dir_all(dir));
584586
t!(File::create(stamp));

0 commit comments

Comments
 (0)