From 6e80b94aad125d503ce880fea025336d8c6b0a76 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 24 Dec 2016 01:26:40 +0300 Subject: [PATCH] rustbuild: Build jemalloc and libbacktrace only once --- src/bootstrap/lib.rs | 10 ++- src/liballoc_jemalloc/build.rs | 141 +++++++++++++++++---------------- src/libstd/build.rs | 37 +++++---- 3 files changed, 102 insertions(+), 86 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 665e0c67b7f6c..f8dac87dfb8dd 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -478,7 +478,8 @@ impl Build { // // These variables are primarily all read by // src/bootstrap/bin/{rustc.rs,rustdoc.rs} - cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc")) + cargo.env("RUSTBUILD_NATIVE_DIR", self.native_dir(compiler.host)) + .env("RUSTC", self.out.join("bootstrap/debug/rustc")) .env("RUSTC_REAL", self.compiler_path(compiler)) .env("RUSTC_STAGE", stage.to_string()) .env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()) @@ -736,10 +737,15 @@ impl Build { } } + /// Directory for libraries built from C/C++ code and shared between stages. + fn native_dir(&self, target: &str) -> PathBuf { + self.out.join(target).join("native") + } + /// Root output directory for rust_test_helpers library compiled for /// `target` fn test_helpers_out(&self, target: &str) -> PathBuf { - self.out.join(target).join("rust-test-helpers") + self.native_dir(target).join("rust-test-helpers") } /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 2bbec9e5fc225..57f02162280ce 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -14,6 +14,7 @@ extern crate build_helper; extern crate gcc; use std::env; +use std::fs; use std::path::PathBuf; use std::process::Command; use build_helper::run; @@ -24,8 +25,9 @@ fn main() { let target = env::var("TARGET").expect("TARGET was not set"); let host = env::var("HOST").expect("HOST was not set"); - let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let src_dir = env::current_dir().unwrap(); + let build_dir = PathBuf::from(env::var_os("RUSTBUILD_NATIVE_DIR").unwrap()).join("jemalloc"); + let _ = fs::create_dir_all(&build_dir); // FIXME: This is a hack to support building targets that don't // support jemalloc alongside hosts that do. The jemalloc build is @@ -81,77 +83,80 @@ fn main() { } } - let mut cmd = Command::new("sh"); - cmd.arg(src_dir.join("../jemalloc/configure") - .to_str() - .unwrap() - .replace("C:\\", "/c/") - .replace("\\", "/")) - .current_dir(&build_dir) - .env("CC", compiler.path()) - .env("EXTRA_CFLAGS", cflags.clone()) - // jemalloc generates Makefile deps using GCC's "-MM" flag. This means - // that GCC will run the preprocessor, and only the preprocessor, over - // jemalloc's source files. If we don't specify CPPFLAGS, then at least - // on ARM that step fails with a "Missing implementation for 32-bit - // atomic operations" error. This is because no "-march" flag will be - // passed to GCC, and then GCC won't define the - // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to - // select an atomic operation implementation. - .env("CPPFLAGS", cflags.clone()) - .env("AR", &ar) - .env("RANLIB", format!("{} s", ar.display())); + if !build_dir.join("Makefile").metadata().is_ok() { + let mut cmd = Command::new("sh"); + cmd.arg(src_dir.join("../jemalloc/configure") + .to_str() + .unwrap() + .replace("C:\\", "/c/") + .replace("\\", "/")) + .current_dir(&build_dir) + .env("CC", compiler.path()) + .env("EXTRA_CFLAGS", cflags.clone()) + // jemalloc generates Makefile deps using GCC's "-MM" flag. This means + // that GCC will run the preprocessor, and only the preprocessor, over + // jemalloc's source files. If we don't specify CPPFLAGS, then at least + // on ARM that step fails with a "Missing implementation for 32-bit + // atomic operations" error. This is because no "-march" flag will be + // passed to GCC, and then GCC won't define the + // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to + // select an atomic operation implementation. + .env("CPPFLAGS", cflags.clone()) + .env("AR", &ar) + .env("RANLIB", format!("{} s", ar.display())); + + if target.contains("windows") { + // A bit of history here, this used to be --enable-lazy-lock added in + // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which + // was also reported to MinGW: + // + // http://sourceforge.net/p/mingw-w64/bugs/395/ + // + // When updating jemalloc to 4.0, however, it was found that binaries + // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating + // that a thread was unlocking a mutex it never locked. Disabling this + // "lazy lock" option seems to fix the issue, but it was enabled by + // default for MinGW targets in 13473c7 for jemalloc. + // + // As a result of all that, force disabling lazy lock on Windows, and + // after reading some code it at least *appears* that the initialization + // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems + // hopefully... + // + // tl;dr: make windows behave like other platforms by disabling lazy + // locking, but requires passing an option due to a historical + // default with jemalloc. + cmd.arg("--disable-lazy-lock"); + } else if target.contains("ios") { + cmd.arg("--disable-tls"); + } else if target.contains("android") { + // We force android to have prefixed symbols because apparently + // replacement of the libc allocator doesn't quite work. When this was + // tested (unprefixed symbols), it was found that the `realpath` + // function in libc would allocate with libc malloc (not jemalloc + // malloc), and then the standard library would free with jemalloc free, + // causing a segfault. + // + // If the test suite passes, however, without symbol prefixes then we + // should be good to go! + cmd.arg("--with-jemalloc-prefix=je_"); + cmd.arg("--disable-tls"); + } else if target.contains("dragonfly") { + cmd.arg("--with-jemalloc-prefix=je_"); + } - if target.contains("windows") { - // A bit of history here, this used to be --enable-lazy-lock added in - // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which - // was also reported to MinGW: - // - // http://sourceforge.net/p/mingw-w64/bugs/395/ - // - // When updating jemalloc to 4.0, however, it was found that binaries - // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating - // that a thread was unlocking a mutex it never locked. Disabling this - // "lazy lock" option seems to fix the issue, but it was enabled by - // default for MinGW targets in 13473c7 for jemalloc. - // - // As a result of all that, force disabling lazy lock on Windows, and - // after reading some code it at least *appears* that the initialization - // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems - // hopefully... - // - // tl;dr: make windows behave like other platforms by disabling lazy - // locking, but requires passing an option due to a historical - // default with jemalloc. - cmd.arg("--disable-lazy-lock"); - } else if target.contains("ios") { - cmd.arg("--disable-tls"); - } else if target.contains("android") { - // We force android to have prefixed symbols because apparently - // replacement of the libc allocator doesn't quite work. When this was - // tested (unprefixed symbols), it was found that the `realpath` - // function in libc would allocate with libc malloc (not jemalloc - // malloc), and then the standard library would free with jemalloc free, - // causing a segfault. - // - // If the test suite passes, however, without symbol prefixes then we - // should be good to go! - cmd.arg("--with-jemalloc-prefix=je_"); - cmd.arg("--disable-tls"); - } else if target.contains("dragonfly") { - cmd.arg("--with-jemalloc-prefix=je_"); - } + if cfg!(feature = "debug-jemalloc") { + cmd.arg("--enable-debug"); + } - if cfg!(feature = "debug-jemalloc") { - cmd.arg("--enable-debug"); - } + // Turn off broken quarantine (see jemalloc/jemalloc#161) + cmd.arg("--disable-fill"); + cmd.arg(format!("--host={}", build_helper::gnu_target(&target))); + cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); - // Turn off broken quarantine (see jemalloc/jemalloc#161) - cmd.arg("--disable-fill"); - cmd.arg(format!("--host={}", build_helper::gnu_target(&target))); - cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); + run(&mut cmd); + } - run(&mut cmd); let mut make = Command::new(build_helper::make(&host)); make.current_dir(&build_dir) .arg("build_lib_static"); diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 5e1c3a2851568..87f6f8a960431 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -14,6 +14,7 @@ extern crate gcc; extern crate build_helper; use std::env; +use std::fs; use std::path::PathBuf; use std::process::Command; @@ -67,7 +68,9 @@ fn main() { fn build_libbacktrace(host: &str, target: &str) { let src_dir = env::current_dir().unwrap().join("../libbacktrace"); - let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let build_dir = + PathBuf::from(env::var_os("RUSTBUILD_NATIVE_DIR").unwrap()).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()); @@ -89,21 +92,23 @@ fn build_libbacktrace(host: &str, target: &str) { let ar = build_helper::cc2ar(compiler.path(), target).unwrap(); let cflags = compiler.args().iter().map(|s| s.to_str().unwrap()) .collect::>().join(" "); - run(Command::new("sh") - .current_dir(&build_dir) - .arg(src_dir.join("configure").to_str().unwrap() - .replace("C:\\", "/c/") - .replace("\\", "/")) - .arg("--with-pic") - .arg("--disable-multilib") - .arg("--disable-shared") - .arg("--disable-host-shared") - .arg(format!("--host={}", build_helper::gnu_target(target))) - .arg(format!("--build={}", build_helper::gnu_target(host))) - .env("CC", compiler.path()) - .env("AR", &ar) - .env("RANLIB", format!("{} s", ar.display())) - .env("CFLAGS", cflags)); + if !build_dir.join("Makefile").metadata().is_ok() { + run(Command::new("sh") + .current_dir(&build_dir) + .arg(src_dir.join("configure").to_str().unwrap() + .replace("C:\\", "/c/") + .replace("\\", "/")) + .arg("--with-pic") + .arg("--disable-multilib") + .arg("--disable-shared") + .arg("--disable-host-shared") + .arg(format!("--host={}", build_helper::gnu_target(target))) + .arg(format!("--build={}", build_helper::gnu_target(host))) + .env("CC", compiler.path()) + .env("AR", &ar) + .env("RANLIB", format!("{} s", ar.display())) + .env("CFLAGS", cflags)); + } run(Command::new(build_helper::make(host)) .current_dir(&build_dir) .arg(format!("INCDIR={}", src_dir.display()))