|
16 | 16 | //! compiler. This module is also responsible for assembling the sysroot as it
|
17 | 17 | //! goes along from the output of the previous stage.
|
18 | 18 |
|
| 19 | +use std::cmp; |
19 | 20 | use std::collections::HashMap;
|
20 |
| -use std::fs; |
| 21 | +use std::fs::{self, File}; |
21 | 22 | use std::path::{Path, PathBuf};
|
22 | 23 | use std::process::Command;
|
23 | 24 |
|
24 | 25 | use build_helper::output;
|
| 26 | +use filetime::FileTime; |
25 | 27 |
|
26 | 28 | use util::{exe, staticlib, libdir, mtime, is_dylib, copy};
|
27 | 29 | use {Build, Compiler, Mode};
|
@@ -66,6 +68,7 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
66 | 68 | }
|
67 | 69 |
|
68 | 70 | build.run(&mut cargo);
|
| 71 | + update_mtime(&libstd_stamp(build, compiler, target)); |
69 | 72 | std_link(build, target, compiler, compiler.host);
|
70 | 73 | }
|
71 | 74 |
|
@@ -141,11 +144,12 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
141 | 144 | println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
|
142 | 145 | compiler.host, target);
|
143 | 146 | 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)); |
145 | 148 | let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build");
|
146 | 149 | cargo.arg("--manifest-path")
|
147 | 150 | .arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
|
148 | 151 | build.run(&mut cargo);
|
| 152 | + update_mtime(&libtest_stamp(build, compiler, target)); |
149 | 153 | test_link(build, target, compiler, compiler.host);
|
150 | 154 | }
|
151 | 155 |
|
@@ -173,7 +177,7 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
173 | 177 | compiler.stage, compiler.host, target);
|
174 | 178 |
|
175 | 179 | 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)); |
177 | 181 |
|
178 | 182 | let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build");
|
179 | 183 | cargo.arg("--features").arg(build.rustc_features())
|
@@ -238,14 +242,14 @@ pub fn rustc_link(build: &Build,
|
238 | 242 |
|
239 | 243 | /// Cargo's output path for the standard library in a given stage, compiled
|
240 | 244 | /// 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") |
243 | 247 | }
|
244 | 248 |
|
245 | 249 | /// Cargo's output path for libtest in a given stage, compiled by a particular
|
246 | 250 | /// 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") |
249 | 253 | }
|
250 | 254 |
|
251 | 255 | fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
|
@@ -358,10 +362,35 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
|
358 | 362 | // Maybe when libstd is compiled it should clear out the rustc of the
|
359 | 363 | // corresponding stage?
|
360 | 364 | // 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)); |
362 | 366 |
|
363 | 367 | let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build");
|
364 | 368 | cargo.arg("--manifest-path")
|
365 | 369 | .arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool)));
|
366 | 370 | build.run(&mut cargo);
|
367 | 371 | }
|
| 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 | +} |
0 commit comments