|
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};
|
@@ -76,6 +78,7 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
76 | 78 | }
|
77 | 79 |
|
78 | 80 | build.run(&mut cargo);
|
| 81 | + update_mtime(&libstd_stamp(build, compiler, target)); |
79 | 82 | std_link(build, target, compiler, compiler.host);
|
80 | 83 | }
|
81 | 84 |
|
@@ -149,11 +152,12 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
149 | 152 | println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
|
150 | 153 | compiler.host, target);
|
151 | 154 | 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)); |
153 | 156 | let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build");
|
154 | 157 | cargo.arg("--manifest-path")
|
155 | 158 | .arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
|
156 | 159 | build.run(&mut cargo);
|
| 160 | + update_mtime(&libtest_stamp(build, compiler, target)); |
157 | 161 | test_link(build, target, compiler, compiler.host);
|
158 | 162 | }
|
159 | 163 |
|
@@ -181,7 +185,7 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
181 | 185 | compiler.stage, compiler.host, target);
|
182 | 186 |
|
183 | 187 | 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)); |
185 | 189 |
|
186 | 190 | let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build");
|
187 | 191 | cargo.arg("--features").arg(build.rustc_features())
|
@@ -246,14 +250,14 @@ pub fn rustc_link(build: &Build,
|
246 | 250 |
|
247 | 251 | /// Cargo's output path for the standard library in a given stage, compiled
|
248 | 252 | /// 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") |
251 | 255 | }
|
252 | 256 |
|
253 | 257 | /// Cargo's output path for libtest in a given stage, compiled by a particular
|
254 | 258 | /// 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") |
257 | 261 | }
|
258 | 262 |
|
259 | 263 | fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
|
@@ -366,10 +370,35 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
|
366 | 370 | // Maybe when libstd is compiled it should clear out the rustc of the
|
367 | 371 | // corresponding stage?
|
368 | 372 | // 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)); |
370 | 374 |
|
371 | 375 | let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build");
|
372 | 376 | cargo.arg("--manifest-path")
|
373 | 377 | .arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool)));
|
374 | 378 | build.run(&mut cargo);
|
375 | 379 | }
|
| 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 | +} |
0 commit comments