From 07dae5a97b64100f5abd511f1e2d5a6263a54006 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Fri, 11 Feb 2022 11:44:44 -0800 Subject: [PATCH] bootstrap: make LLVM build respect *FLAGS envvars This tidies up the logic in `src/bootstrap/native.rs` such that: - `CMAKE_*_LINKER_FLAGS` is not overridden if we add to it twice. - `CMAKE_*_FLAGS` also include the standard `*FLAGS` environment variables, which CMake respects when we _don't_ set `CMAKE_*_FLAGS`. - `llvm.ldflags` from `config.toml` appends to the ldflags Rust's bootstrap logic adds, rather than replacing them. Fixes #93880. --- src/bootstrap/native.rs | 85 ++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 14de1531f73..4af9edbae40 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -31,6 +31,29 @@ pub struct Meta { root: String, } +// Linker flags to pass to LLVM's CMake invocation. +#[derive(Debug, Clone, Default)] +struct LdFlags { + // CMAKE_EXE_LINKER_FLAGS + exe: OsString, + // CMAKE_SHARED_LINKER_FLAGS + shared: OsString, + // CMAKE_MODULE_LINKER_FLAGS + module: OsString, +} + +impl LdFlags { + fn push_all(&mut self, s: impl AsRef) { + let s = s.as_ref(); + self.exe.push(" "); + self.exe.push(s); + self.shared.push(" "); + self.shared.push(s); + self.module.push(" "); + self.module.push(s); + } +} + // This returns whether we've already previously built LLVM. // // It's used to avoid busting caches during x.py check -- if we've already built @@ -146,6 +169,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { // https://llvm.org/docs/CMake.html let mut cfg = cmake::Config::new(builder.src.join(root)); + let mut ldflags = LdFlags::default(); let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) { (false, _) => "Debug", @@ -242,9 +266,9 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { if builder.config.llvm_tools_enabled { if !target.contains("msvc") { if target.contains("apple") { - cfg.define("CMAKE_EXE_LINKER_FLAGS", "-static-libstdc++"); + ldflags.exe.push(" -static-libstdc++"); } else { - cfg.define("CMAKE_EXE_LINKER_FLAGS", "-Wl,-Bsymbolic -static-libstdc++"); + ldflags.exe.push(" -Wl,-Bsymbolic -static-libstdc++"); } } } @@ -258,11 +282,11 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { // provides no libatomic in its base system so does // not want this. if !builder.config.llvm_tools_enabled { - cfg.define("CMAKE_EXE_LINKER_FLAGS", "-latomic"); + ldflags.exe.push(" -latomic"); } else { - cfg.define("CMAKE_EXE_LINKER_FLAGS", "-latomic -static-libstdc++"); + ldflags.exe.push(" -latomic -static-libstdc++"); } - cfg.define("CMAKE_SHARED_LINKER_FLAGS", "-latomic"); + ldflags.shared.push(" -latomic"); } if target.contains("msvc") { @@ -309,7 +333,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { // Workaround for ppc32 lld limitation if target == "powerpc-unknown-freebsd" { - cfg.define("CMAKE_EXE_LINKER_FLAGS", "-fuse-ld=bfd"); + ldflags.exe.push(" -fuse-ld=bfd"); } // https://llvm.org/docs/HowToCrossCompileLLVM.html @@ -351,7 +375,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { cfg.define("LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN", "YES"); } - configure_cmake(builder, target, &mut cfg, true); + configure_cmake(builder, target, &mut cfg, true, ldflags); for (key, val) in &builder.config.llvm_build_config { cfg.define(key, val); @@ -399,6 +423,7 @@ fn configure_cmake( target: TargetSelection, cfg: &mut cmake::Config, use_compiler_launcher: bool, + mut ldflags: LdFlags, ) { // Do not print installation messages for up-to-date files. // LLVM and LLD builds can produce a lot of those and hit CI limits on log size. @@ -507,31 +532,41 @@ fn configure_cmake( } cfg.build_arg("-j").build_arg(builder.jobs().to_string()); - let mut cflags = builder.cflags(target, GitRepo::Llvm).join(" "); + let mut cflags: OsString = builder.cflags(target, GitRepo::Llvm).join(" ").into(); if let Some(ref s) = builder.config.llvm_cflags { - cflags.push_str(&format!(" {}", s)); + cflags.push(" "); + cflags.push(s); } // Some compiler features used by LLVM (such as thread locals) will not work on a min version below iOS 10. if target.contains("apple-ios") { if target.contains("86-") { - cflags.push_str(" -miphonesimulator-version-min=10.0"); + cflags.push(" -miphonesimulator-version-min=10.0"); } else { - cflags.push_str(" -miphoneos-version-min=10.0"); + cflags.push(" -miphoneos-version-min=10.0"); } } if builder.config.llvm_clang_cl.is_some() { - cflags.push_str(&format!(" --target={}", target)) + cflags.push(&format!(" --target={}", target)); + } + if let Some(flags) = env::var_os("CFLAGS") { + cflags.push(" "); + cflags.push(flags); } cfg.define("CMAKE_C_FLAGS", cflags); - let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" "); + let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm).join(" ").into(); if builder.config.llvm_static_stdcpp && !target.contains("msvc") && !target.contains("netbsd") { - cxxflags.push_str(" -static-libstdc++"); + cxxflags.push(" -static-libstdc++"); } if let Some(ref s) = builder.config.llvm_cxxflags { - cxxflags.push_str(&format!(" {}", s)); + cxxflags.push(" "); + cxxflags.push(s); } if builder.config.llvm_clang_cl.is_some() { - cxxflags.push_str(&format!(" --target={}", target)) + cxxflags.push(&format!(" --target={}", target)); + } + if let Some(flags) = env::var_os("CXXFLAGS") { + cxxflags.push(" "); + cxxflags.push(flags); } cfg.define("CMAKE_CXX_FLAGS", cxxflags); if let Some(ar) = builder.ar(target) { @@ -550,12 +585,18 @@ fn configure_cmake( } } - if let Some(ref s) = builder.config.llvm_ldflags { - cfg.define("CMAKE_SHARED_LINKER_FLAGS", s); - cfg.define("CMAKE_MODULE_LINKER_FLAGS", s); - cfg.define("CMAKE_EXE_LINKER_FLAGS", s); + if let Some(ref flags) = builder.config.llvm_ldflags { + ldflags.push_all(flags); } + if let Some(flags) = env::var_os("LDFLAGS") { + ldflags.push_all(&flags); + } + + cfg.define("CMAKE_SHARED_LINKER_FLAGS", &ldflags.shared); + cfg.define("CMAKE_MODULE_LINKER_FLAGS", &ldflags.module); + cfg.define("CMAKE_EXE_LINKER_FLAGS", &ldflags.exe); + if env::var_os("SCCACHE_ERROR_LOG").is_some() { cfg.env("RUSTC_LOG", "sccache=warn"); } @@ -598,7 +639,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { t!(fs::create_dir_all(&out_dir)); let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/lld")); - configure_cmake(builder, target, &mut cfg, true); + configure_cmake(builder, target, &mut cfg, true, LdFlags::default()); // 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 @@ -788,7 +829,7 @@ fn run(self, builder: &Builder<'_>) -> Self::Output { // Unfortunately sccache currently lacks support to build them successfully. // Disable compiler launcher on Darwin targets to avoid potential issues. let use_compiler_launcher = !self.target.contains("apple-darwin"); - configure_cmake(builder, self.target, &mut cfg, use_compiler_launcher); + configure_cmake(builder, self.target, &mut cfg, use_compiler_launcher, LdFlags::default()); t!(fs::create_dir_all(&out_dir)); cfg.out_dir(out_dir);