Skip to content

Commit 194a91b

Browse files
committed
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.
1 parent fa9d8cc commit 194a91b

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};
@@ -66,6 +68,7 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
6668
}
6769

6870
build.run(&mut cargo);
71+
update_mtime(&libstd_stamp(build, compiler, target));
6972
std_link(build, target, compiler, compiler.host);
7073
}
7174

@@ -141,11 +144,12 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
141144
println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
142145
compiler.host, target);
143146
let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
144-
build.clear_if_dirty(&out_dir, &libstd_shim(build, compiler, target));
147+
build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
145148
let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build");
146149
cargo.arg("--manifest-path")
147150
.arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
148151
build.run(&mut cargo);
152+
update_mtime(&libtest_stamp(build, compiler, target));
149153
test_link(build, target, compiler, compiler.host);
150154
}
151155

@@ -173,7 +177,7 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
173177
compiler.stage, compiler.host, target);
174178

175179
let out_dir = build.cargo_out(compiler, Mode::Librustc, target);
176-
build.clear_if_dirty(&out_dir, &libtest_shim(build, compiler, target));
180+
build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target));
177181

178182
let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build");
179183
cargo.arg("--features").arg(build.rustc_features())
@@ -238,14 +242,14 @@ pub fn rustc_link(build: &Build,
238242

239243
/// Cargo's output path for the standard library in a given stage, compiled
240244
/// by a particular compiler for the specified target.
241-
fn libstd_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
242-
build.cargo_out(compiler, Mode::Libstd, target).join("libstd_shim.rlib")
245+
fn libstd_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
246+
build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
243247
}
244248

245249
/// Cargo's output path for libtest in a given stage, compiled by a particular
246250
/// compiler for the specified target.
247-
fn libtest_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
248-
build.cargo_out(compiler, Mode::Libtest, target).join("libtest_shim.rlib")
251+
fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
252+
build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
249253
}
250254

251255
fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
@@ -358,10 +362,35 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
358362
// Maybe when libstd is compiled it should clear out the rustc of the
359363
// corresponding stage?
360364
// let out_dir = build.cargo_out(stage, &host, Mode::Librustc, target);
361-
// build.clear_if_dirty(&out_dir, &libstd_shim(build, stage, &host, target));
365+
// build.clear_if_dirty(&out_dir, &libstd_stamp(build, stage, &host, target));
362366

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

src/bootstrap/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,8 @@ impl Build {
585585
if mtime(&stamp) < mtime(input) {
586586
self.verbose(&format!("Dirty - {}", dir.display()));
587587
let _ = fs::remove_dir_all(dir);
588+
} else if stamp.exists() {
589+
return
588590
}
589591
t!(fs::create_dir_all(dir));
590592
t!(File::create(stamp));

0 commit comments

Comments
 (0)