diff --git a/src/Cargo.lock b/src/Cargo.lock
index c463f2bb747cc..f4174693a5771 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -80,7 +80,7 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -202,7 +202,7 @@ dependencies = [
 
 [[package]]
 name = "cmake"
-version = "0.1.20"
+version = "0.1.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -221,6 +221,7 @@ dependencies = [
 name = "compiler_builtins"
 version = "0.0.0"
 dependencies = [
+ "build_helper 0.1.0",
  "core 0.0.0",
  "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -486,7 +487,7 @@ name = "libgit2-sys"
 version = "0.6.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -501,7 +502,7 @@ name = "libssh2-sys"
 version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -893,7 +894,7 @@ version = "0.0.0"
 dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1036,7 +1037,7 @@ version = "0.0.0"
 dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1080,7 +1081,7 @@ version = "0.0.0"
 dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1172,7 +1173,7 @@ version = "0.0.0"
 dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1572,7 +1573,7 @@ dependencies = [
 "checksum bufstream 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b48dbe2ff0e98fa2f03377d204a9637d3c9816cd431bfe05a8abbd0ea11d074"
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758"
-"checksum cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a3a6805df695087e7c1bcd9a82e03ad6fb864c8e67ac41b1348229ce5b7f0407"
+"checksum cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "e1acc68a3f714627af38f9f5d09706a28584ba60dfe2cca68f40bf779f941b25"
 "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
 "checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b"
 "checksum curl-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d909dc402ae80b6f7b0118c039203436061b9d9a3ca5d2c2546d93e0a61aaa"
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index c1ee0c29ac981..7dd53f41a214a 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -8,6 +8,7 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
+from __future__ import print_function
 import argparse
 import contextlib
 import datetime
@@ -501,7 +502,7 @@ def build_triple(self):
 
         return "{}-{}".format(cputype, ostype)
 
-def main():
+def bootstrap():
     parser = argparse.ArgumentParser(description='Build rust')
     parser.add_argument('--config')
     parser.add_argument('--clean', action='store_true')
@@ -564,8 +565,6 @@ def main():
     rb._rustc_channel, rb._rustc_date = data['rustc'].split('-', 1)
     rb._cargo_rev = data['cargo']
 
-    start_time = time()
-
     # Fetch/build the bootstrap
     rb.build = rb.build_triple()
     rb.download_stage0()
@@ -582,9 +581,19 @@ def main():
     env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
     rb.run(args, env)
 
-    end_time = time()
-
-    print("Build completed in %s" % format_build_time(end_time - start_time))
+def main():
+    start_time = time()
+    try:
+        bootstrap()
+        print("Build completed successfully in %s" % format_build_time(time() - start_time))
+    except (SystemExit, KeyboardInterrupt) as e:
+        if hasattr(e, 'code') and isinstance(e.code, int):
+            exit_code = e.code
+        else:
+            exit_code = 1
+            print(e)
+        print("Build completed unsuccessfully in %s" % format_build_time(time() - start_time))
+        sys.exit(exit_code)
 
 if __name__ == '__main__':
     main()
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 5215b281fac0b..98b68d870d375 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -740,7 +740,7 @@ impl Build {
         } else {
             let base = self.llvm_out(&self.config.build).join("build");
             let exe = exe("FileCheck", target);
-            if self.config.build.contains("msvc") {
+            if !self.config.ninja && self.config.build.contains("msvc") {
                 base.join("Release/bin").join(exe)
             } else {
                 base.join("bin").join(exe)
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 90e1530308f4a..483f45fdd6218 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -41,28 +41,32 @@ pub fn llvm(build: &Build, target: &str) {
         }
     }
 
-    // If the cleaning trigger is newer than our built artifacts (or if the
-    // artifacts are missing) then we keep going, otherwise we bail out.
-    let dst = build.llvm_out(target);
-    let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
-    let mut stamp_contents = String::new();
-    t!(t!(File::open(&stamp)).read_to_string(&mut stamp_contents));
-    let done_stamp = dst.join("llvm-finished-building");
+    let clean_trigger = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
+    let mut clean_trigger_contents = String::new();
+    t!(t!(File::open(&clean_trigger)).read_to_string(&mut clean_trigger_contents));
+
+    let out_dir = build.llvm_out(target);
+    let done_stamp = out_dir.join("llvm-finished-building");
     if done_stamp.exists() {
         let mut done_contents = String::new();
         t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents));
-        if done_contents == stamp_contents {
+
+        // LLVM was already built previously.
+        // We don't track changes in LLVM sources, so we need to choose between reusing
+        // what was built previously, or cleaning the directory and doing a fresh build.
+        // The choice depends on contents of the clean-trigger file.
+        // If the contents are the same as during the previous build, then no action is required.
+        // If the contents differ from the previous build, then cleaning is triggered.
+        if done_contents == clean_trigger_contents {
             return
+        } else {
+            t!(fs::remove_dir_all(&out_dir));
         }
     }
-    drop(fs::remove_dir_all(&dst));
 
     println!("Building LLVM for {}", target);
-
     let _time = util::timeit();
-    let _ = fs::remove_dir_all(&dst.join("build"));
-    t!(fs::create_dir_all(&dst.join("build")));
-    let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
+    t!(fs::create_dir_all(&out_dir));
 
     // http://llvm.org/docs/CMake.html
     let mut cfg = cmake::Config::new(build.src.join("src/llvm"));
@@ -82,9 +86,11 @@ pub fn llvm(build: &Build, target: &str) {
         None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX",
     };
 
+    let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
+
     cfg.target(target)
        .host(&build.config.build)
-       .out_dir(&dst)
+       .out_dir(&out_dir)
        .profile(profile)
        .define("LLVM_ENABLE_ASSERTIONS", assertions)
        .define("LLVM_TARGETS_TO_BUILD", llvm_targets)
@@ -142,7 +148,7 @@ pub fn llvm(build: &Build, target: &str) {
     //        tools and libs on all platforms.
     cfg.build();
 
-    t!(t!(File::create(&done_stamp)).write_all(stamp_contents.as_bytes()));
+    t!(t!(File::create(&done_stamp)).write_all(clean_trigger_contents.as_bytes()));
 }
 
 fn check_llvm_version(build: &Build, llvm_config: &Path) {
diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs
index 7e4771dd7dc2f..a5c0d11d21985 100644
--- a/src/bootstrap/step.rs
+++ b/src/bootstrap/step.rs
@@ -312,6 +312,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
                  });
         };
 
+        suite("check-ui", "src/test/ui", "ui", "ui");
         suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass");
         suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail");
         suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail");
@@ -372,7 +373,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
                  });
         };
 
-        suite("check-ui", "src/test/ui", "ui", "ui");
+        suite("check-ui-full", "src/test/ui-fulldeps", "ui", "ui-fulldeps");
         suite("check-rpass-full", "src/test/run-pass-fulldeps",
               "run-pass", "run-pass-fulldeps");
         suite("check-rfail-full", "src/test/run-fail-fulldeps",
@@ -1530,7 +1531,8 @@ mod tests {
         assert!(plan.iter().all(|s| s.host == "A"));
         assert!(plan.iter().all(|s| s.target == "C"));
 
-        assert!(!plan.iter().any(|s| s.name.contains("-ui")));
+        assert!(plan.iter().any(|s| s.name.contains("-ui")));
+        assert!(!plan.iter().any(|s| s.name.contains("ui-full")));
         assert!(plan.iter().any(|s| s.name.contains("cfail")));
         assert!(!plan.iter().any(|s| s.name.contains("cfail-full")));
         assert!(plan.iter().any(|s| s.name.contains("codegen-units")));
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
index 08f1f31c2d74b..dffaebbd92914 100644
--- a/src/build_helper/lib.rs
+++ b/src/build_helper/lib.rs
@@ -12,7 +12,8 @@
 
 extern crate filetime;
 
-use std::fs;
+use std::{fs, env};
+use std::fs::File;
 use std::process::{Command, Stdio};
 use std::path::{Path, PathBuf};
 
@@ -166,6 +167,47 @@ pub fn up_to_date(src: &Path, dst: &Path) -> bool {
     }
 }
 
+#[must_use]
+pub struct NativeLibBoilerplate {
+    pub src_dir: PathBuf,
+    pub out_dir: PathBuf,
+}
+
+impl Drop for NativeLibBoilerplate {
+    fn drop(&mut self) {
+        t!(File::create(self.out_dir.join("rustbuild.timestamp")));
+    }
+}
+
+// Perform standard preparations for native libraries that are build only once for all stages.
+// Emit rerun-if-changed and linking attributes for Cargo, check if any source files are
+// updated, calculate paths used later in actual build with CMake/make or C/C++ compiler.
+// If Err is returned, then everything is up-to-date and further build actions can be skipped.
+// Timestamps are created automatically when the result of `native_lib_boilerplate` goes out
+// of scope, so all the build actions should be completed until then.
+pub fn native_lib_boilerplate(src_name: &str,
+                              out_name: &str,
+                              link_name: &str,
+                              search_subdir: &str)
+                              -> Result<NativeLibBoilerplate, ()> {
+    let current_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
+    let src_dir = current_dir.join("..").join(src_name);
+    rerun_if_changed_anything_in_dir(&src_dir);
+
+    let out_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or(env::var_os("OUT_DIR").unwrap());
+    let out_dir = PathBuf::from(out_dir).join(out_name);
+    let _ = fs::create_dir_all(&out_dir);
+    println!("cargo:rustc-link-lib=static={}", link_name);
+    println!("cargo:rustc-link-search=native={}", out_dir.join(search_subdir).display());
+
+    let timestamp = out_dir.join("rustbuild.timestamp");
+    if !up_to_date(Path::new("build.rs"), &timestamp) || !up_to_date(&src_dir, &timestamp) {
+        Ok(NativeLibBoilerplate { src_dir: src_dir, out_dir: out_dir })
+    } else {
+        Err(())
+    }
+}
+
 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());
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index a3402bf399427..ae040a2390659 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -10,19 +10,15 @@
 
 #![deny(warnings)]
 
-#[macro_use]
 extern crate build_helper;
 extern crate gcc;
 
 use std::env;
-use std::fs::{self, File};
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
 use std::process::Command;
-use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date};
+use build_helper::{run, native_lib_boilerplate};
 
 fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-
     // FIXME: This is a hack to support building targets that don't
     // support jemalloc alongside hosts that do. The jemalloc build is
     // controlled by a feature of the std crate, and if that feature
@@ -61,22 +57,11 @@ fn main() {
         return;
     }
 
-    let build_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or(env::var_os("OUT_DIR").unwrap());
-    let build_dir = PathBuf::from(build_dir).join("jemalloc");
-    let _ = fs::create_dir_all(&build_dir);
-
-    if target.contains("windows") {
-        println!("cargo:rustc-link-lib=static=jemalloc");
-    } else {
-        println!("cargo:rustc-link-lib=static=jemalloc_pic");
-    }
-    println!("cargo:rustc-link-search=native={}/lib", build_dir.display());
-    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
-    }
+    let link_name = if target.contains("windows") { "jemalloc" } else { "jemalloc_pic" };
+    let native = match native_lib_boilerplate("jemalloc", "jemalloc", link_name, "lib") {
+        Ok(native) => native,
+        _ => return,
+    };
 
     let compiler = gcc::Config::new().get_compiler();
     // only msvc returns None for ar so unwrap is okay
@@ -88,12 +73,12 @@ fn main() {
         .join(" ");
 
     let mut cmd = Command::new("sh");
-    cmd.arg(src_dir.join("configure")
-                   .to_str()
-                   .unwrap()
-                   .replace("C:\\", "/c/")
-                   .replace("\\", "/"))
-       .current_dir(&build_dir)
+    cmd.arg(native.src_dir.join("configure")
+                          .to_str()
+                          .unwrap()
+                          .replace("C:\\", "/c/")
+                          .replace("\\", "/"))
+       .current_dir(&native.out_dir)
        .env("CC", compiler.path())
        .env("EXTRA_CFLAGS", cflags.clone())
        // jemalloc generates Makefile deps using GCC's "-MM" flag. This means
@@ -166,7 +151,7 @@ fn main() {
     run(&mut cmd);
 
     let mut make = Command::new(build_helper::make(&host));
-    make.current_dir(&build_dir)
+    make.current_dir(&native.out_dir)
         .arg("build_lib_static");
 
     // mingw make seems... buggy? unclear...
@@ -187,6 +172,4 @@ fn main() {
             .file("pthread_atfork_dummy.c")
             .compile("libpthread_atfork_dummy.a");
     }
-
-    t!(File::create(&timestamp));
 }
diff --git a/src/libcompiler_builtins/Cargo.toml b/src/libcompiler_builtins/Cargo.toml
index 1a549ae823ac5..3f844b3f09e3a 100644
--- a/src/libcompiler_builtins/Cargo.toml
+++ b/src/libcompiler_builtins/Cargo.toml
@@ -15,4 +15,5 @@ doc = false
 core = { path = "../libcore" }
 
 [build-dependencies]
+build_helper = { path = "../build_helper" }
 gcc = "0.3.27"
diff --git a/src/libcompiler_builtins/build.rs b/src/libcompiler_builtins/build.rs
index 16ecf88256670..bcd3a92dd4305 100644
--- a/src/libcompiler_builtins/build.rs
+++ b/src/libcompiler_builtins/build.rs
@@ -33,11 +33,13 @@
 //! error (if any) and then we just add it to the list. Overall, that cost is
 //! far far less than working with compiler-rt's build system over time.
 
+extern crate build_helper;
 extern crate gcc;
 
 use std::collections::BTreeMap;
 use std::env;
 use std::path::Path;
+use build_helper::native_lib_boilerplate;
 
 struct Sources {
     // SYMBOL -> PATH TO SOURCE
@@ -79,7 +81,14 @@ fn main() {
         return;
     }
 
+    // Can't reuse `sources` list for the freshness check becuse it doesn't contain header files.
+    let native = match native_lib_boilerplate("compiler-rt", "compiler-rt", "compiler-rt", ".") {
+        Ok(native) => native,
+        _ => return,
+    };
+
     let cfg = &mut gcc::Config::new();
+    cfg.out_dir(&native.out_dir);
 
     if target.contains("msvc") {
         // Don't pull in extra libraries on MSVC
diff --git a/src/libflate/build.rs b/src/libflate/build.rs
index 12016980a2c65..78d2ef1e37d2a 100644
--- a/src/libflate/build.rs
+++ b/src/libflate/build.rs
@@ -11,6 +11,7 @@
 extern crate gcc;
 
 fn main() {
+    println!("cargo:rerun-if-changed=../rt/miniz.c");
     gcc::Config::new()
         .file("../rt/miniz.c")
         .compile("libminiz.a");
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
index 015be14bd495a..2df2e001e6ff2 100644
--- a/src/librustc_asan/build.rs
+++ b/src/librustc_asan/build.rs
@@ -11,29 +11,26 @@
 extern crate build_helper;
 extern crate cmake;
 
-use std::path::PathBuf;
 use std::env;
+use build_helper::native_lib_boilerplate;
 
 use cmake::Config;
 
 fn main() {
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        let dst = Config::new("../compiler-rt")
+        let native = match native_lib_boilerplate("compiler-rt", "asan", "clang_rt.asan-x86_64",
+                                                  "build/lib/linux") {
+            Ok(native) => native,
+            _ => return,
+        };
+
+        Config::new(&native.src_dir)
             .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
             .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
             .define("COMPILER_RT_BUILD_XRAY", "OFF")
             .define("LLVM_CONFIG_PATH", llvm_config)
+            .out_dir(&native.out_dir)
             .build_target("asan")
             .build();
-
-        println!("cargo:rustc-link-search=native={}",
-                 dst.join("build/lib/linux").display());
-        println!("cargo:rustc-link-lib=static=clang_rt.asan-x86_64");
-
-        build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
-                .unwrap())
-            .join("../compiler-rt"));
     }
-
-    println!("cargo:rerun-if-changed=build.rs");
 }
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index c74a9308e4eba..b74bccb70593f 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -144,9 +144,7 @@ fn main() {
         cfg.flag("-DLLVM_RUSTLLVM");
     }
 
-    println!("cargo:rerun-if-changed=../rustllvm/PassWrapper.cpp");
-    println!("cargo:rerun-if-changed=../rustllvm/RustWrapper.cpp");
-    println!("cargo:rerun-if-changed=../rustllvm/ArchiveWrapper.cpp");
+    build_helper::rerun_if_changed_anything_in_dir(Path::new("../rustllvm"));
     cfg.file("../rustllvm/PassWrapper.cpp")
        .file("../rustllvm/RustWrapper.cpp")
        .file("../rustllvm/ArchiveWrapper.cpp")
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
index 5773777d1f81b..005163f41026c 100644
--- a/src/librustc_lsan/build.rs
+++ b/src/librustc_lsan/build.rs
@@ -11,29 +11,26 @@
 extern crate build_helper;
 extern crate cmake;
 
-use std::path::PathBuf;
 use std::env;
+use build_helper::native_lib_boilerplate;
 
 use cmake::Config;
 
 fn main() {
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        let dst = Config::new("../compiler-rt")
+        let native = match native_lib_boilerplate("compiler-rt", "lsan", "clang_rt.lsan-x86_64",
+                                                  "build/lib/linux") {
+            Ok(native) => native,
+            _ => return,
+        };
+
+        Config::new(&native.src_dir)
             .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
             .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
             .define("COMPILER_RT_BUILD_XRAY", "OFF")
             .define("LLVM_CONFIG_PATH", llvm_config)
+            .out_dir(&native.out_dir)
             .build_target("lsan")
             .build();
-
-        println!("cargo:rustc-link-search=native={}",
-                 dst.join("build/lib/linux").display());
-        println!("cargo:rustc-link-lib=static=clang_rt.lsan-x86_64");
-
-        build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
-                .unwrap())
-            .join("../compiler-rt"));
     }
-
-    println!("cargo:rerun-if-changed=build.rs");
 }
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
index 7a4c8f7073933..c438b5250463b 100644
--- a/src/librustc_msan/build.rs
+++ b/src/librustc_msan/build.rs
@@ -11,29 +11,26 @@
 extern crate build_helper;
 extern crate cmake;
 
-use std::path::PathBuf;
 use std::env;
+use build_helper::native_lib_boilerplate;
 
 use cmake::Config;
 
 fn main() {
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        let dst = Config::new("../compiler-rt")
+        let native = match native_lib_boilerplate("compiler-rt", "msan", "clang_rt.msan-x86_64",
+                                                  "build/lib/linux") {
+            Ok(native) => native,
+            _ => return,
+        };
+
+        Config::new(&native.src_dir)
             .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
             .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
             .define("COMPILER_RT_BUILD_XRAY", "OFF")
             .define("LLVM_CONFIG_PATH", llvm_config)
+            .out_dir(&native.out_dir)
             .build_target("msan")
             .build();
-
-        println!("cargo:rustc-link-search=native={}",
-                 dst.join("build/lib/linux").display());
-        println!("cargo:rustc-link-lib=static=clang_rt.msan-x86_64");
-
-        build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
-                .unwrap())
-            .join("../compiler-rt"));
     }
-
-    println!("cargo:rerun-if-changed=build.rs");
 }
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
index 84326ae8a7106..055b344d2e947 100644
--- a/src/librustc_tsan/build.rs
+++ b/src/librustc_tsan/build.rs
@@ -11,29 +11,26 @@
 extern crate build_helper;
 extern crate cmake;
 
-use std::path::PathBuf;
 use std::env;
+use build_helper::native_lib_boilerplate;
 
 use cmake::Config;
 
 fn main() {
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        let dst = Config::new("../compiler-rt")
+        let native = match native_lib_boilerplate("compiler-rt", "tsan", "clang_rt.tsan-x86_64",
+                                                  "build/lib/linux") {
+            Ok(native) => native,
+            _ => return,
+        };
+
+        Config::new(&native.src_dir)
             .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
             .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
             .define("COMPILER_RT_BUILD_XRAY", "OFF")
             .define("LLVM_CONFIG_PATH", llvm_config)
+            .out_dir(&native.out_dir)
             .build_target("tsan")
             .build();
-
-        println!("cargo:rustc-link-search=native={}",
-                 dst.join("build/lib/linux").display());
-        println!("cargo:rustc-link-lib=static=clang_rt.tsan-x86_64");
-
-        build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
-                .unwrap())
-            .join("../compiler-rt"));
     }
-
-    println!("cargo:rerun-if-changed=build.rs");
 }
diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs
index fcb7af11dce2f..9fa6406c1d8b6 100644
--- a/src/librustdoc/build.rs
+++ b/src/librustdoc/build.rs
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+extern crate build_helper;
 extern crate gcc;
 
 fn main() {
+    let src_dir = std::path::Path::new("../rt/hoedown/src");
+    build_helper::rerun_if_changed_anything_in_dir(src_dir);
     let mut cfg = gcc::Config::new();
     cfg.file("../rt/hoedown/src/autolink.c")
        .file("../rt/hoedown/src/buffer.c")
@@ -21,6 +24,6 @@ fn main() {
        .file("../rt/hoedown/src/html_smartypants.c")
        .file("../rt/hoedown/src/stack.c")
        .file("../rt/hoedown/src/version.c")
-       .include("../rt/hoedown/src")
+       .include(src_dir)
        .compile("libhoedown.a");
 }
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 038dea77f3ead..9fb83ad75980a 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -10,24 +10,19 @@
 
 #![deny(warnings)]
 
-#[macro_use]
 extern crate build_helper;
 extern crate gcc;
 
 use std::env;
-use std::fs::{self, File};
-use std::path::{Path, PathBuf};
 use std::process::Command;
-use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date};
+use build_helper::{run, native_lib_boilerplate};
 
 fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-
     let target = env::var("TARGET").expect("TARGET was not set");
     let host = env::var("HOST").expect("HOST was not set");
     if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
         !target.contains("emscripten") && !target.contains("fuchsia") && !target.contains("redox") {
-        build_libbacktrace(&host, &target);
+        let _ = build_libbacktrace(&host, &target);
     }
 
     if target.contains("linux") {
@@ -69,19 +64,8 @@ fn main() {
     }
 }
 
-fn build_libbacktrace(host: &str, target: &str) {
-    let build_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or(env::var_os("OUT_DIR").unwrap());
-    let build_dir = PathBuf::from(build_dir).join("libbacktrace");
-    let _ = fs::create_dir_all(&build_dir);
-
-    println!("cargo:rustc-link-lib=static=backtrace");
-    println!("cargo:rustc-link-search=native={}/.libs", build_dir.display());
-    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
-    }
+fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
+    let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
 
     let compiler = gcc::Config::new().get_compiler();
     // only msvc returns None for ar so unwrap is okay
@@ -90,10 +74,10 @@ fn build_libbacktrace(host: &str, target: &str) {
                              .collect::<Vec<_>>().join(" ");
     cflags.push_str(" -fvisibility=hidden");
     run(Command::new("sh")
-                .current_dir(&build_dir)
-                .arg(src_dir.join("configure").to_str().unwrap()
-                            .replace("C:\\", "/c/")
-                            .replace("\\", "/"))
+                .current_dir(&native.out_dir)
+                .arg(native.src_dir.join("configure").to_str().unwrap()
+                                   .replace("C:\\", "/c/")
+                                   .replace("\\", "/"))
                 .arg("--with-pic")
                 .arg("--disable-multilib")
                 .arg("--disable-shared")
@@ -106,9 +90,8 @@ fn build_libbacktrace(host: &str, target: &str) {
                 .env("CFLAGS", cflags));
 
     run(Command::new(build_helper::make(host))
-                .current_dir(&build_dir)
-                .arg(format!("INCDIR={}", src_dir.display()))
+                .current_dir(&native.out_dir)
+                .arg(format!("INCDIR={}", native.src_dir.display()))
                 .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
-
-    t!(File::create(&timestamp));
+    Ok(())
 }
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index ea0d76978339d..ed3d5212bf256 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -11,6 +11,7 @@
 use std::env;
 
 fn main() {
+    println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
 
     if target.contains("linux") {
diff --git a/src/test/run-make/cdylib/Makefile b/src/test/run-make/cdylib/Makefile
index ae3b82537db52..47ec762b3e94c 100644
--- a/src/test/run-make/cdylib/Makefile
+++ b/src/test/run-make/cdylib/Makefile
@@ -8,7 +8,7 @@ all: $(call RUN_BINFILE,foo)
 
 ifdef IS_MSVC
 $(call RUN_BINFILE,foo): $(call DYLIB,foo)
-	$(CC) $(CFLAGS) foo.c $(TMPDIR)/foo.dll.lib -Fe:`cygpath -w $@`
+	$(CC) $(CFLAGS) foo.c $(TMPDIR)/foo.dll.lib $(call OUT_EXE,foo)
 else
 $(call RUN_BINFILE,foo): $(call DYLIB,foo)
 	$(CC) $(CFLAGS) foo.c -lfoo -o $(call RUN_BINFILE,foo) -L $(TMPDIR)
diff --git a/src/test/ui/custom-derive/auxiliary/plugin.rs b/src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs
similarity index 100%
rename from src/test/ui/custom-derive/auxiliary/plugin.rs
rename to src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs
diff --git a/src/test/ui/custom-derive/issue-36935.rs b/src/test/ui-fulldeps/custom-derive/issue-36935.rs
similarity index 100%
rename from src/test/ui/custom-derive/issue-36935.rs
rename to src/test/ui-fulldeps/custom-derive/issue-36935.rs
diff --git a/src/test/ui/custom-derive/issue-36935.stderr b/src/test/ui-fulldeps/custom-derive/issue-36935.stderr
similarity index 100%
rename from src/test/ui/custom-derive/issue-36935.stderr
rename to src/test/ui-fulldeps/custom-derive/issue-36935.stderr
diff --git a/x.py b/x.py
index d281a6abc93e3..8f528889d6020 100755
--- a/x.py
+++ b/x.py
@@ -9,14 +9,12 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
-import sys
+# This file is only a "symlink" to boostrap.py, all logic should go there.
+
 import os
-dir = os.path.dirname(__file__)
-sys.path.append(os.path.abspath(os.path.join(dir, "src", "bootstrap")))
+import sys
+rust_dir = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(os.path.join(rust_dir, "src", "bootstrap"))
 
 import bootstrap
-
-try:
-    bootstrap.main()
-except KeyboardInterrupt:
-    sys.exit()
+bootstrap.main()