Build libbacktrace/jemalloc only when their timestamps are older than sources

This commit is contained in:
Vadim Petrochenkov 2017-02-01 00:27:51 +03:00
parent c0253304ea
commit a5b603b1bf
10 changed files with 94 additions and 71 deletions

3
src/Cargo.lock generated
View File

@ -61,6 +61,9 @@ dependencies = [
[[package]] [[package]]
name = "build_helper" name = "build_helper"
version = "0.1.0" version = "0.1.0"
dependencies = [
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "cargotest" name = "cargotest"

View File

@ -21,10 +21,10 @@ use std::fs::{self, File};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use build_helper::output; use build_helper::{output, mtime};
use filetime::FileTime; use filetime::FileTime;
use util::{exe, libdir, mtime, is_dylib, copy}; use util::{exe, libdir, is_dylib, copy};
use {Build, Compiler, Mode}; use {Build, Compiler, Mode};
/// Build the standard library. /// Build the standard library.

View File

@ -22,7 +22,8 @@ use std::io::prelude::*;
use std::process::Command; use std::process::Command;
use {Build, Compiler, Mode}; use {Build, Compiler, Mode};
use util::{up_to_date, cp_r}; use util::cp_r;
use build_helper::up_to_date;
/// Invoke `rustbook` as compiled in `stage` for `target` for the doc book /// Invoke `rustbook` as compiled in `stage` for `target` for the doc book
/// `name` into the `out` path. /// `name` into the `out` path.

View File

@ -66,6 +66,7 @@
#![deny(warnings)] #![deny(warnings)]
#[macro_use]
extern crate build_helper; extern crate build_helper;
extern crate cmake; extern crate cmake;
extern crate filetime; extern crate filetime;
@ -83,24 +84,9 @@ use std::fs::{self, File};
use std::path::{Component, PathBuf, Path}; use std::path::{Component, PathBuf, Path};
use std::process::Command; use std::process::Command;
use build_helper::{run_silent, output}; use build_helper::{run_silent, output, mtime};
use util::{exe, mtime, libdir, add_lib_path}; use util::{exe, libdir, add_lib_path};
/// A helper macro to `unwrap` a result except also print out details like:
///
/// * The file/line of the panic
/// * The expression that failed
/// * The error itself
///
/// This is currently used judiciously throughout the build system rather than
/// using a `Result` with `try!`, but this may change one day...
macro_rules! t {
($e:expr) => (match $e {
Ok(e) => e,
Err(e) => panic!("{} failed with {}", stringify!($e), e),
})
}
mod cc; mod cc;
mod channel; mod channel;

View File

@ -28,7 +28,8 @@ use cmake;
use gcc; use gcc;
use Build; use Build;
use util::{self, up_to_date}; use util;
use build_helper::up_to_date;
/// Compile LLVM for `target`. /// Compile LLVM for `target`.
pub fn llvm(build: &Build, target: &str) { pub fn llvm(build: &Build, target: &str) {

View File

@ -20,8 +20,6 @@ use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use std::time::Instant; use std::time::Instant;
use filetime::FileTime;
/// Returns the `name` as the filename of a static library for `target`. /// Returns the `name` as the filename of a static library for `target`.
pub fn staticlib(name: &str, target: &str) -> String { pub fn staticlib(name: &str, target: &str) -> String {
if target.contains("windows") { if target.contains("windows") {
@ -31,13 +29,6 @@ pub fn staticlib(name: &str, target: &str) -> String {
} }
} }
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
pub fn mtime(path: &Path) -> FileTime {
fs::metadata(path).map(|f| {
FileTime::from_last_modification_time(&f)
}).unwrap_or(FileTime::zero())
}
/// Copies a file from `src` to `dst`, attempting to use hard links and then /// Copies a file from `src` to `dst`, attempting to use hard links and then
/// falling back to an actually filesystem copy if necessary. /// falling back to an actually filesystem copy if necessary.
pub fn copy(src: &Path, dst: &Path) { pub fn copy(src: &Path, dst: &Path) {
@ -132,34 +123,6 @@ pub fn add_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
cmd.env(dylib_path_var(), t!(env::join_paths(list))); cmd.env(dylib_path_var(), t!(env::join_paths(list)));
} }
/// Returns whether `dst` is up to date given that the file or files in `src`
/// are used to generate it.
///
/// Uses last-modified time checks to verify this.
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
let threshold = mtime(dst);
let meta = match fs::metadata(src) {
Ok(meta) => meta,
Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
};
if meta.is_dir() {
dir_up_to_date(src, &threshold)
} else {
FileTime::from_last_modification_time(&meta) <= threshold
}
}
fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool {
t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
let meta = t!(e.metadata());
if meta.is_dir() {
dir_up_to_date(&e.path(), threshold)
} else {
FileTime::from_last_modification_time(&meta) < *threshold
}
})
}
/// Returns the environment variable which the dynamic library lookup path /// Returns the environment variable which the dynamic library lookup path
/// resides in for this platform. /// resides in for this platform.
pub fn dylib_path_var() -> &'static str { pub fn dylib_path_var() -> &'static str {

View File

@ -6,3 +6,6 @@ authors = ["The Rust Project Developers"]
[lib] [lib]
name = "build_helper" name = "build_helper"
path = "lib.rs" path = "lib.rs"
[dependencies]
filetime = "0.1"

View File

@ -10,9 +10,30 @@
#![deny(warnings)] #![deny(warnings)]
extern crate filetime;
use std::fs;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use filetime::FileTime;
/// A helper macro to `unwrap` a result except also print out details like:
///
/// * The file/line of the panic
/// * The expression that failed
/// * The error itself
///
/// This is currently used judiciously throughout the build system rather than
/// using a `Result` with `try!`, but this may change one day...
#[macro_export]
macro_rules! t {
($e:expr) => (match $e {
Ok(e) => e,
Err(e) => panic!("{} failed with {}", stringify!($e), e),
})
}
pub fn run(cmd: &mut Command) { pub fn run(cmd: &mut Command) {
println!("running: {:?}", cmd); println!("running: {:?}", cmd);
run_silent(cmd); run_silent(cmd);
@ -103,6 +124,41 @@ pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
} }
} }
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
pub fn mtime(path: &Path) -> FileTime {
fs::metadata(path).map(|f| {
FileTime::from_last_modification_time(&f)
}).unwrap_or(FileTime::zero())
}
/// Returns whether `dst` is up to date given that the file or files in `src`
/// are used to generate it.
///
/// Uses last-modified time checks to verify this.
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
let threshold = mtime(dst);
let meta = match fs::metadata(src) {
Ok(meta) => meta,
Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
};
if meta.is_dir() {
dir_up_to_date(src, &threshold)
} else {
FileTime::from_last_modification_time(&meta) <= threshold
}
}
fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool {
t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
let meta = t!(e.metadata());
if meta.is_dir() {
dir_up_to_date(&e.path(), threshold)
} else {
FileTime::from_last_modification_time(&meta) < *threshold
}
})
}
fn fail(s: &str) -> ! { fn fail(s: &str) -> ! {
println!("\n\n{}\n\n", s); println!("\n\n{}\n\n", s);
std::process::exit(1); std::process::exit(1);

View File

@ -10,13 +10,15 @@
#![deny(warnings)] #![deny(warnings)]
#[macro_use]
extern crate build_helper; extern crate build_helper;
extern crate gcc; extern crate gcc;
use std::{env, fs}; use std::env;
use std::path::PathBuf; use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use build_helper::{run, rerun_if_changed_anything_in_dir}; use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date};
fn main() { fn main() {
println!("cargo:rustc-cfg=cargobuild"); println!("cargo:rustc-cfg=cargobuild");
@ -69,12 +71,13 @@ fn main() {
} else if !target.contains("windows") && !target.contains("musl") { } else if !target.contains("windows") && !target.contains("musl") {
println!("cargo:rustc-link-lib=pthread"); println!("cargo:rustc-link-lib=pthread");
} }
if !cfg!(stage0) && target == host { let src_dir = env::current_dir().unwrap().join("../jemalloc");
rerun_if_changed_anything_in_dir(&src_dir);
let timestamp = build_dir.join("rustbuild.timestamp");
if up_to_date(&Path::new("build.rs"), &timestamp) && up_to_date(&src_dir, &timestamp) {
return return
} }
let src_dir = env::current_dir().unwrap().join("../jemalloc");
rerun_if_changed_anything_in_dir(&src_dir);
let compiler = gcc::Config::new().get_compiler(); let compiler = gcc::Config::new().get_compiler();
// only msvc returns None for ar so unwrap is okay // only msvc returns None for ar so unwrap is okay
let ar = build_helper::cc2ar(compiler.path(), &target).unwrap(); let ar = build_helper::cc2ar(compiler.path(), &target).unwrap();
@ -184,4 +187,6 @@ fn main() {
.file("pthread_atfork_dummy.c") .file("pthread_atfork_dummy.c")
.compile("libpthread_atfork_dummy.a"); .compile("libpthread_atfork_dummy.a");
} }
t!(File::create(&timestamp));
} }

View File

@ -10,13 +10,15 @@
#![deny(warnings)] #![deny(warnings)]
extern crate gcc; #[macro_use]
extern crate build_helper; extern crate build_helper;
extern crate gcc;
use std::{env, fs}; use std::env;
use std::path::PathBuf; use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use build_helper::{run, rerun_if_changed_anything_in_dir}; use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date};
fn main() { fn main() {
println!("cargo:rustc-cfg=cargobuild"); println!("cargo:rustc-cfg=cargobuild");
@ -71,12 +73,13 @@ fn build_libbacktrace(host: &str, target: &str) {
println!("cargo:rustc-link-lib=static=backtrace"); println!("cargo:rustc-link-lib=static=backtrace");
println!("cargo:rustc-link-search=native={}/.libs", build_dir.display()); println!("cargo:rustc-link-search=native={}/.libs", build_dir.display());
if !cfg!(stage0) && target == host { let src_dir = env::current_dir().unwrap().join("../libbacktrace");
rerun_if_changed_anything_in_dir(&src_dir);
let timestamp = build_dir.join("rustbuild.timestamp");
if up_to_date(&Path::new("build.rs"), &timestamp) && up_to_date(&src_dir, &timestamp) {
return return
} }
let src_dir = env::current_dir().unwrap().join("../libbacktrace");
rerun_if_changed_anything_in_dir(&src_dir);
let compiler = gcc::Config::new().get_compiler(); let compiler = gcc::Config::new().get_compiler();
// only msvc returns None for ar so unwrap is okay // only msvc returns None for ar so unwrap is okay
let ar = build_helper::cc2ar(compiler.path(), target).unwrap(); let ar = build_helper::cc2ar(compiler.path(), target).unwrap();
@ -103,4 +106,6 @@ fn build_libbacktrace(host: &str, target: &str) {
.current_dir(&build_dir) .current_dir(&build_dir)
.arg(format!("INCDIR={}", src_dir.display())) .arg(format!("INCDIR={}", src_dir.display()))
.arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set"))); .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
t!(File::create(&timestamp));
} }