diff options
| author | bors <bors@rust-lang.org> | 2018-05-10 10:30:02 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-05-10 10:30:02 +0000 |
| commit | 57dc98434eb818733dbc941405fdee59e5c3a023 (patch) | |
| tree | 4b76049ca5ef8fb2e8f600599f407121e49676d0 /src/bootstrap | |
| parent | c8a3ec1ce6dc12f86de39bf5ac55fc2fa38358f8 (diff) | |
| parent | 7e5b9ac41e36b29d5208f4e5455aade07d4d107d (diff) | |
| download | rust-57dc98434eb818733dbc941405fdee59e5c3a023.tar.gz rust-57dc98434eb818733dbc941405fdee59e5c3a023.zip | |
Auto merge of #50200 - alexcrichton:compile-with-clang, r=kennytm
Compile LLVM with Clang on release builders Attempting to cache in on some rustc compile time wins mentioned in https://github.com/rust-lang/rust/issues/49879#issuecomment-383602941
Diffstat (limited to 'src/bootstrap')
| -rw-r--r-- | src/bootstrap/Cargo.toml | 5 | ||||
| -rw-r--r-- | src/bootstrap/bin/llvm-config-wrapper.rs | 27 | ||||
| -rw-r--r-- | src/bootstrap/bin/sccache-plus-cl.rs | 10 | ||||
| -rw-r--r-- | src/bootstrap/builder.rs | 6 | ||||
| -rw-r--r-- | src/bootstrap/config.rs | 3 | ||||
| -rw-r--r-- | src/bootstrap/native.rs | 68 |
6 files changed, 107 insertions, 12 deletions
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 2f9c4e148a6..af33ebf3c42 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -28,6 +28,11 @@ name = "sccache-plus-cl" path = "bin/sccache-plus-cl.rs" test = false +[[bin]] +name = "llvm-config-wrapper" +path = "bin/llvm-config-wrapper.rs" +test = false + [dependencies] build_helper = { path = "../build_helper" } cmake = "0.1.23" diff --git a/src/bootstrap/bin/llvm-config-wrapper.rs b/src/bootstrap/bin/llvm-config-wrapper.rs new file mode 100644 index 00000000000..b1703f8c728 --- /dev/null +++ b/src/bootstrap/bin/llvm-config-wrapper.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// The sheer existence of this file is an awful hack. See the comments in +// `src/bootstrap/native.rs` for why this is needed when compiling LLD. + +use std::env; +use std::process::{self, Stdio, Command}; +use std::io::{self, Write}; + +fn main() { + let real_llvm_config = env::var_os("LLVM_CONFIG_REAL").unwrap(); + let mut cmd = Command::new(real_llvm_config); + cmd.args(env::args().skip(1)).stderr(Stdio::piped()); + let output = cmd.output().expect("failed to spawn llvm-config"); + let stdout = String::from_utf8_lossy(&output.stdout); + print!("{}", stdout.replace("\\", "/")); + io::stdout().flush().unwrap(); + process::exit(output.status.code().unwrap_or(1)); +} diff --git a/src/bootstrap/bin/sccache-plus-cl.rs b/src/bootstrap/bin/sccache-plus-cl.rs index 8584014d48d..0a20ac7e492 100644 --- a/src/bootstrap/bin/sccache-plus-cl.rs +++ b/src/bootstrap/bin/sccache-plus-cl.rs @@ -16,8 +16,8 @@ use std::process::{self, Command}; fn main() { let target = env::var("SCCACHE_TARGET").unwrap(); // Locate the actual compiler that we're invoking - env::remove_var("CC"); - env::remove_var("CXX"); + env::set_var("CC", env::var_os("SCCACHE_CC").unwrap()); + env::set_var("CXX", env::var_os("SCCACHE_CXX").unwrap()); let mut cfg = cc::Build::new(); cfg.cargo_metadata(false) .out_dir("/") @@ -39,6 +39,12 @@ fn main() { cmd.arg(arg); } + if let Ok(s) = env::var("SCCACHE_EXTRA_ARGS") { + for s in s.split_whitespace() { + cmd.arg(s); + } + } + let status = cmd.status().expect("failed to spawn"); process::exit(status.code().unwrap_or(2)) } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 701313d8082..f87436504c6 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -751,7 +751,11 @@ impl<'a> Builder<'a> { // the options through environment variables that are fetched and understood by both. // // FIXME: the guard against msvc shouldn't need to be here - if !target.contains("msvc") { + if target.contains("msvc") { + if let Some(ref cl) = self.config.llvm_clang_cl { + cargo.env("CC", cl).env("CXX", cl); + } + } else { let ccache = self.config.ccache.as_ref(); let ccacheify = |s: &Path| { let ccache = match ccache { diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 6dd6291be23..9840682d137 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -82,6 +82,7 @@ pub struct Config { pub llvm_version_check: bool, pub llvm_static_stdcpp: bool, pub llvm_link_shared: bool, + pub llvm_clang_cl: Option<String>, pub llvm_targets: Option<String>, pub llvm_experimental_targets: String, pub llvm_link_jobs: Option<u32>, @@ -250,6 +251,7 @@ struct Llvm { experimental_targets: Option<String>, link_jobs: Option<u32>, link_shared: Option<bool>, + clang_cl: Option<String> } #[derive(Deserialize, Default, Clone)] @@ -504,6 +506,7 @@ impl Config { config.llvm_experimental_targets = llvm.experimental_targets.clone() .unwrap_or("WebAssembly".to_string()); config.llvm_link_jobs = llvm.link_jobs; + config.llvm_clang_cl = llvm.clang_cl.clone(); } if let Some(ref rust) = toml.rust { diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index d952cb5bfc4..002044050f3 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -275,21 +275,53 @@ fn configure_cmake(builder: &Builder, return } - let cc = builder.cc(target); - let cxx = builder.cxx(target).unwrap(); + let (cc, cxx) = match builder.config.llvm_clang_cl { + Some(ref cl) => (cl.as_ref(), cl.as_ref()), + None => (builder.cc(target), builder.cxx(target).unwrap()), + }; // Handle msvc + ninja + ccache specially (this is what the bots use) if target.contains("msvc") && builder.config.ninja && - builder.config.ccache.is_some() { - let mut cc = env::current_exe().expect("failed to get cwd"); - cc.set_file_name("sccache-plus-cl.exe"); + builder.config.ccache.is_some() + { + let mut wrap_cc = env::current_exe().expect("failed to get cwd"); + wrap_cc.set_file_name("sccache-plus-cl.exe"); - cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc)) - .define("CMAKE_CXX_COMPILER", sanitize_cc(&cc)); + cfg.define("CMAKE_C_COMPILER", sanitize_cc(&wrap_cc)) + .define("CMAKE_CXX_COMPILER", sanitize_cc(&wrap_cc)); cfg.env("SCCACHE_PATH", builder.config.ccache.as_ref().unwrap()) - .env("SCCACHE_TARGET", target); + .env("SCCACHE_TARGET", target) + .env("SCCACHE_CC", &cc) + .env("SCCACHE_CXX", &cxx); + + // Building LLVM on MSVC can be a little ludicrous at times. We're so far + // off the beaten path here that I'm not really sure this is even half + // supported any more. Here we're trying to: + // + // * Build LLVM on MSVC + // * Build LLVM with `clang-cl` instead of `cl.exe` + // * Build a project with `sccache` + // * Build for 32-bit as well + // * Build with Ninja + // + // For `cl.exe` there are different binaries to compile 32/64 bit which + // we use but for `clang-cl` there's only one which internally + // multiplexes via flags. As a result it appears that CMake's detection + // of a compiler's architecture and such on MSVC **doesn't** pass any + // custom flags we pass in CMAKE_CXX_FLAGS below. This means that if we + // use `clang-cl.exe` it's always diagnosed as a 64-bit compiler which + // definitely causes problems since all the env vars are pointing to + // 32-bit libraries. + // + // To hack aroudn this... again... we pass an argument that's + // unconditionally passed in the sccache shim. This'll get CMake to + // correctly diagnose it's doing a 32-bit compilation and LLVM will + // internally configure itself appropriately. + if builder.config.llvm_clang_cl.is_some() && target.contains("i686") { + cfg.env("SCCACHE_EXTRA_ARGS", "-m32"); + } // If ccache is configured we inform the build a little differently hwo // to invoke ccache while also invoking our compilers. @@ -368,9 +400,27 @@ impl Step for Lld { let mut cfg = cmake::Config::new(builder.src.join("src/tools/lld")); configure_cmake(builder, target, &mut cfg, true); + // This is an awful, awful hack. Discovered when we migrated to using + // clang-cl to compile LLVM/LLD it turns out that LLD, when built out of + // tree, will execute `llvm-config --cmakedir` and then tell CMake about + // that directory for later processing. Unfortunately if this path has + // forward slashes in it (which it basically always does on Windows) + // then CMake will hit a syntax error later on as... something isn't + // escaped it seems? + // + // Instead of attempting to fix this problem in upstream CMake and/or + // LLVM/LLD we just hack around it here. This thin wrapper will take the + // output from llvm-config and replace all instances of `\` with `/` to + // ensure we don't hit the same bugs with escaping. It means that you + // can't build on a system where your paths require `\` on Windows, but + // there's probably a lot of reasons you can't do that other than this. + let llvm_config_shim = env::current_exe() + .unwrap() + .with_file_name("llvm-config-wrapper"); cfg.out_dir(&out_dir) .profile("Release") - .define("LLVM_CONFIG_PATH", llvm_config) + .env("LLVM_CONFIG_REAL", llvm_config) + .define("LLVM_CONFIG_PATH", llvm_config_shim) .define("LLVM_INCLUDE_TESTS", "OFF"); cfg.build(); |
