]> git.lizzy.rs Git - rust.git/blobdiff - src/bootstrap/native.rs
Rollup merge of #106100 - scottmcm:derived-less-than-test, r=compiler-errors
[rust.git] / src / bootstrap / native.rs
index 8052bde6024eeb7a7527accf887e7c558aaf198c..4e503dfe864e2937eca0461125effb8147739ff1 100644 (file)
 use crate::util::{self, exe, output, t, up_to_date};
 use crate::{CLang, GitRepo};
 
+#[derive(Clone)]
+pub struct LlvmResult {
+    /// Path to llvm-config binary.
+    /// NB: This is always the host llvm-config!
+    pub llvm_config: PathBuf,
+    /// Path to LLVM cmake directory for the target.
+    pub llvm_cmake_dir: PathBuf,
+}
+
 pub struct Meta {
     stamp: HashStamp,
-    build_llvm_config: PathBuf,
+    res: LlvmResult,
     out_dir: PathBuf,
     root: String,
 }
@@ -64,7 +73,7 @@ fn push_all(&mut self, s: impl AsRef<OsStr>) {
 pub fn prebuilt_llvm_config(
     builder: &Builder<'_>,
     target: TargetSelection,
-) -> Result<PathBuf, Meta> {
+) -> Result<LlvmResult, Meta> {
     builder.config.maybe_download_ci_llvm();
 
     // If we're using a custom LLVM bail out here, but we can only use a
@@ -72,7 +81,14 @@ pub fn prebuilt_llvm_config(
     if let Some(config) = builder.config.target_config.get(&target) {
         if let Some(ref s) = config.llvm_config {
             check_llvm_version(builder, s);
-            return Ok(s.to_path_buf());
+            let llvm_config = s.to_path_buf();
+            let mut llvm_cmake_dir = llvm_config.clone();
+            llvm_cmake_dir.pop();
+            llvm_cmake_dir.pop();
+            llvm_cmake_dir.push("lib");
+            llvm_cmake_dir.push("cmake");
+            llvm_cmake_dir.push("llvm");
+            return Ok(LlvmResult { llvm_config, llvm_cmake_dir });
         }
     }
 
@@ -84,8 +100,9 @@ pub fn prebuilt_llvm_config(
         llvm_config_ret_dir.push("build");
     }
     llvm_config_ret_dir.push("bin");
-
     let build_llvm_config = llvm_config_ret_dir.join(exe("llvm-config", builder.config.build));
+    let llvm_cmake_dir = out_dir.join("lib/cmake/llvm");
+    let res = LlvmResult { llvm_config: build_llvm_config, llvm_cmake_dir };
 
     let stamp = out_dir.join("llvm-finished-building");
     let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
@@ -96,7 +113,7 @@ pub fn prebuilt_llvm_config(
                 Using a potentially stale build of LLVM; \
                 This may not behave well.",
         );
-        return Ok(build_llvm_config);
+        return Ok(res);
     }
 
     if stamp.is_done() {
@@ -110,10 +127,10 @@ pub fn prebuilt_llvm_config(
                 stamp.path.display()
             ));
         }
-        return Ok(build_llvm_config);
+        return Ok(res);
     }
 
-    Err(Meta { stamp, build_llvm_config, out_dir, root: root.into() })
+    Err(Meta { stamp, res, out_dir, root: root.into() })
 }
 
 /// This retrieves the LLVM sha we *want* to use, according to git history.
@@ -223,7 +240,7 @@ pub struct Llvm {
 }
 
 impl Step for Llvm {
-    type Output = PathBuf; // path to llvm-config
+    type Output = LlvmResult;
 
     const ONLY_HOSTS: bool = true;
 
@@ -236,7 +253,7 @@ fn make_run(run: RunConfig<'_>) {
     }
 
     /// Compile LLVM for `target`.
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
+    fn run(self, builder: &Builder<'_>) -> LlvmResult {
         let target = self.target;
         let target_native = if self.target.starts_with("riscv") {
             // RISC-V target triples in Rust is not named the same as C compiler target triples.
@@ -252,11 +269,10 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             target.to_string()
         };
 
-        let Meta { stamp, build_llvm_config, out_dir, root } =
-            match prebuilt_llvm_config(builder, target) {
-                Ok(p) => return p,
-                Err(m) => m,
-            };
+        let Meta { stamp, res, out_dir, root } = match prebuilt_llvm_config(builder, target) {
+            Ok(p) => return p,
+            Err(m) => m,
+        };
 
         builder.update_submodule(&Path::new("src").join("llvm-project"));
         if builder.llvm_link_shared() && target.contains("windows") {
@@ -430,7 +446,8 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
 
         // https://llvm.org/docs/HowToCrossCompileLLVM.html
         if target != builder.config.build {
-            let llvm_config = builder.ensure(Llvm { target: builder.config.build });
+            let LlvmResult { llvm_config, .. } =
+                builder.ensure(Llvm { target: builder.config.build });
             if !builder.config.dry_run() {
                 let llvm_bindir = output(Command::new(&llvm_config).arg("--bindir"));
                 let host_bin = Path::new(llvm_bindir.trim());
@@ -480,7 +497,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         //        tools and libs on all platforms.
 
         if builder.config.dry_run() {
-            return build_llvm_config;
+            return res;
         }
 
         cfg.build();
@@ -490,7 +507,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         // for a versioned path like libLLVM-14.dylib. Manually create a symbolic
         // link to make llvm-config happy.
         if builder.llvm_link_shared() && target.contains("apple-darwin") {
-            let mut cmd = Command::new(&build_llvm_config);
+            let mut cmd = Command::new(&res.llvm_config);
             let version = output(cmd.arg("--version"));
             let major = version.split('.').next().unwrap();
             let lib_name = match llvm_version_suffix {
@@ -509,18 +526,18 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         // LLVM after a configuration change, so to rebuild it the build files have to be removed,
         // which will also remove these modified files.
         if builder.config.llvm_bolt_profile_generate {
-            instrument_with_bolt_inplace(&get_built_llvm_lib_path(&build_llvm_config));
+            instrument_with_bolt_inplace(&get_built_llvm_lib_path(&res.llvm_config));
         }
         if let Some(path) = &builder.config.llvm_bolt_profile_use {
             optimize_library_with_bolt_inplace(
-                &get_built_llvm_lib_path(&build_llvm_config),
+                &get_built_llvm_lib_path(&res.llvm_config),
                 &Path::new(path),
             );
         }
 
         t!(stamp.write());
 
-        build_llvm_config
+        res
     }
 }
 
@@ -600,6 +617,9 @@ fn configure_cmake(
             if target.starts_with("aarch64") {
                 // macOS uses a different name for building arm64
                 cfg.define("CMAKE_OSX_ARCHITECTURES", "arm64");
+            } else if target.starts_with("i686") {
+                // macOS uses a different name for building i386
+                cfg.define("CMAKE_OSX_ARCHITECTURES", "i386");
             } else {
                 cfg.define("CMAKE_OSX_ARCHITECTURES", target.triple.split('-').next().unwrap());
             }
@@ -803,7 +823,8 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         }
         let target = self.target;
 
-        let llvm_config = builder.ensure(Llvm { target: self.target });
+        let LlvmResult { llvm_config, llvm_cmake_dir } =
+            builder.ensure(Llvm { target: self.target });
 
         let out_dir = builder.lld_out(target);
         let done_stamp = out_dir.join("lld-finished-building");
@@ -834,22 +855,6 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         configure_cmake(builder, target, &mut cfg, true, ldflags);
         configure_llvm(builder, target, &mut cfg);
 
-        // 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");
-
         // Re-use the same flags as llvm to control the level of debug information
         // generated for lld.
         let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
@@ -860,30 +865,15 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
 
         cfg.out_dir(&out_dir)
             .profile(profile)
-            .env("LLVM_CONFIG_REAL", &llvm_config)
-            .define("LLVM_CONFIG_PATH", llvm_config_shim)
+            .define("LLVM_CMAKE_DIR", llvm_cmake_dir)
             .define("LLVM_INCLUDE_TESTS", "OFF");
 
-        // While we're using this horrible workaround to shim the execution of
-        // llvm-config, let's just pile on more. I can't seem to figure out how
-        // to build LLD as a standalone project and also cross-compile it at the
-        // same time. It wants a natively executable `llvm-config` to learn
-        // about LLVM, but then it learns about all the host configuration of
-        // LLVM and tries to link to host LLVM libraries.
-        //
-        // To work around that we tell our shim to replace anything with the
-        // build target with the actual target instead. This'll break parts of
-        // LLD though which try to execute host tools, such as llvm-tblgen, so
-        // we specifically tell it where to find those. This is likely super
-        // brittle and will break over time. If anyone knows better how to
-        // cross-compile LLD it would be much appreciated to fix this!
         if target != builder.config.build {
-            cfg.env("LLVM_CONFIG_SHIM_REPLACE", &builder.config.build.triple)
-                .env("LLVM_CONFIG_SHIM_REPLACE_WITH", &target.triple)
-                .define(
-                    "LLVM_TABLEGEN_EXE",
-                    llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION),
-                );
+            // Use the host llvm-tblgen binary.
+            cfg.define(
+                "LLVM_TABLEGEN_EXE",
+                llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION),
+            );
         }
 
         cfg.build();
@@ -987,7 +977,7 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
             return runtimes;
         }
 
-        let llvm_config = builder.ensure(Llvm { target: builder.config.build });
+        let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: builder.config.build });
         if builder.config.dry_run() {
             return runtimes;
         }