mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 21:16:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			322 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			322 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use std::fs;
 | |
| use std::path::{Path, PathBuf};
 | |
| use std::process::Command;
 | |
| 
 | |
| use crate::path::{Dirs, RelPath};
 | |
| use crate::rustc_info::get_file_name;
 | |
| use crate::utils::{
 | |
|     maybe_incremental, remove_dir_if_exists, spawn_and_wait, try_hard_link, CargoProject, Compiler,
 | |
|     LogGroup,
 | |
| };
 | |
| use crate::{config, CodegenBackend, SysrootKind};
 | |
| 
 | |
| static DIST_DIR: RelPath = RelPath::DIST;
 | |
| static BIN_DIR: RelPath = RelPath::DIST.join("bin");
 | |
| static LIB_DIR: RelPath = RelPath::DIST.join("lib");
 | |
| 
 | |
| pub(crate) fn build_sysroot(
 | |
|     dirs: &Dirs,
 | |
|     channel: &str,
 | |
|     sysroot_kind: SysrootKind,
 | |
|     cg_clif_dylib_src: &CodegenBackend,
 | |
|     bootstrap_host_compiler: &Compiler,
 | |
|     rustup_toolchain_name: Option<&str>,
 | |
|     target_triple: String,
 | |
| ) -> Compiler {
 | |
|     let _guard = LogGroup::guard("Build sysroot");
 | |
| 
 | |
|     eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
 | |
| 
 | |
|     DIST_DIR.ensure_fresh(dirs);
 | |
|     BIN_DIR.ensure_exists(dirs);
 | |
|     LIB_DIR.ensure_exists(dirs);
 | |
| 
 | |
|     let is_native = bootstrap_host_compiler.triple == target_triple;
 | |
| 
 | |
|     let cg_clif_dylib_path = match cg_clif_dylib_src {
 | |
|         CodegenBackend::Local(src_path) => {
 | |
|             // Copy the backend
 | |
|             let cg_clif_dylib_path = if cfg!(windows) {
 | |
|                 // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
 | |
|                 // binaries.
 | |
|                 BIN_DIR
 | |
|             } else {
 | |
|                 LIB_DIR
 | |
|             }
 | |
|             .to_path(dirs)
 | |
|             .join(src_path.file_name().unwrap());
 | |
|             try_hard_link(src_path, &cg_clif_dylib_path);
 | |
|             CodegenBackend::Local(cg_clif_dylib_path)
 | |
|         }
 | |
|         CodegenBackend::Builtin(name) => CodegenBackend::Builtin(name.clone()),
 | |
|     };
 | |
| 
 | |
|     // Build and copy rustc and cargo wrappers
 | |
|     let wrapper_base_name = get_file_name(&bootstrap_host_compiler.rustc, "____", "bin");
 | |
|     for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] {
 | |
|         let wrapper_name = wrapper_base_name.replace("____", wrapper);
 | |
| 
 | |
|         let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc);
 | |
|         let wrapper_path = DIST_DIR.to_path(dirs).join(&wrapper_name);
 | |
|         build_cargo_wrapper_cmd
 | |
|             .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
 | |
|             .arg("-o")
 | |
|             .arg(&wrapper_path)
 | |
|             .arg("-Cstrip=debuginfo");
 | |
|         if let Some(rustup_toolchain_name) = &rustup_toolchain_name {
 | |
|             build_cargo_wrapper_cmd
 | |
|                 .env("TOOLCHAIN_NAME", rustup_toolchain_name)
 | |
|                 .env_remove("CARGO")
 | |
|                 .env_remove("RUSTC")
 | |
|                 .env_remove("RUSTDOC");
 | |
|         } else {
 | |
|             build_cargo_wrapper_cmd
 | |
|                 .env_remove("TOOLCHAIN_NAME")
 | |
|                 .env("CARGO", &bootstrap_host_compiler.cargo)
 | |
|                 .env("RUSTC", &bootstrap_host_compiler.rustc)
 | |
|                 .env("RUSTDOC", &bootstrap_host_compiler.rustdoc);
 | |
|         }
 | |
|         if let CodegenBackend::Builtin(name) = cg_clif_dylib_src {
 | |
|             build_cargo_wrapper_cmd.env("BUILTIN_BACKEND", name);
 | |
|         }
 | |
|         spawn_and_wait(build_cargo_wrapper_cmd);
 | |
|         try_hard_link(wrapper_path, BIN_DIR.to_path(dirs).join(wrapper_name));
 | |
|     }
 | |
| 
 | |
|     let host = build_sysroot_for_triple(
 | |
|         dirs,
 | |
|         channel,
 | |
|         bootstrap_host_compiler.clone(),
 | |
|         &cg_clif_dylib_path,
 | |
|         sysroot_kind,
 | |
|     );
 | |
|     host.install_into_sysroot(&DIST_DIR.to_path(dirs));
 | |
| 
 | |
|     if !is_native {
 | |
|         build_sysroot_for_triple(
 | |
|             dirs,
 | |
|             channel,
 | |
|             {
 | |
|                 let mut bootstrap_target_compiler = bootstrap_host_compiler.clone();
 | |
|                 bootstrap_target_compiler.triple = target_triple.clone();
 | |
|                 bootstrap_target_compiler.set_cross_linker_and_runner();
 | |
|                 bootstrap_target_compiler
 | |
|             },
 | |
|             &cg_clif_dylib_path,
 | |
|             sysroot_kind,
 | |
|         )
 | |
|         .install_into_sysroot(&DIST_DIR.to_path(dirs));
 | |
|     }
 | |
| 
 | |
|     // Copy std for the host to the lib dir. This is necessary for the jit mode to find
 | |
|     // libstd.
 | |
|     for lib in host.libs {
 | |
|         let filename = lib.file_name().unwrap().to_str().unwrap();
 | |
|         if filename.contains("std-") && !filename.contains(".rlib") {
 | |
|             try_hard_link(&lib, LIB_DIR.to_path(dirs).join(lib.file_name().unwrap()));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     let mut target_compiler = {
 | |
|         let dirs: &Dirs = &dirs;
 | |
|         let rustc_clif =
 | |
|             RelPath::DIST.to_path(&dirs).join(wrapper_base_name.replace("____", "rustc-clif"));
 | |
|         let rustdoc_clif =
 | |
|             RelPath::DIST.to_path(&dirs).join(wrapper_base_name.replace("____", "rustdoc-clif"));
 | |
| 
 | |
|         Compiler {
 | |
|             cargo: bootstrap_host_compiler.cargo.clone(),
 | |
|             rustc: rustc_clif.clone(),
 | |
|             rustdoc: rustdoc_clif.clone(),
 | |
|             rustflags: vec![],
 | |
|             rustdocflags: vec![],
 | |
|             triple: target_triple,
 | |
|             runner: vec![],
 | |
|         }
 | |
|     };
 | |
|     if !is_native {
 | |
|         target_compiler.set_cross_linker_and_runner();
 | |
|     }
 | |
|     target_compiler
 | |
| }
 | |
| 
 | |
| struct SysrootTarget {
 | |
|     triple: String,
 | |
|     libs: Vec<PathBuf>,
 | |
| }
 | |
| 
 | |
| impl SysrootTarget {
 | |
|     fn install_into_sysroot(&self, sysroot: &Path) {
 | |
|         if self.libs.is_empty() {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         let target_rustlib_lib = sysroot.join("lib").join("rustlib").join(&self.triple).join("lib");
 | |
|         fs::create_dir_all(&target_rustlib_lib).unwrap();
 | |
| 
 | |
|         for lib in &self.libs {
 | |
|             try_hard_link(lib, target_rustlib_lib.join(lib.file_name().unwrap()));
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| pub(crate) static STDLIB_SRC: RelPath = RelPath::BUILD.join("stdlib");
 | |
| pub(crate) static STANDARD_LIBRARY: CargoProject =
 | |
|     CargoProject::new(&STDLIB_SRC.join("library/sysroot"), "stdlib_target");
 | |
| pub(crate) static RTSTARTUP_SYSROOT: RelPath = RelPath::BUILD.join("rtstartup");
 | |
| 
 | |
| #[must_use]
 | |
| fn build_sysroot_for_triple(
 | |
|     dirs: &Dirs,
 | |
|     channel: &str,
 | |
|     compiler: Compiler,
 | |
|     cg_clif_dylib_path: &CodegenBackend,
 | |
|     sysroot_kind: SysrootKind,
 | |
| ) -> SysrootTarget {
 | |
|     match sysroot_kind {
 | |
|         SysrootKind::None => build_rtstartup(dirs, &compiler)
 | |
|             .unwrap_or(SysrootTarget { triple: compiler.triple, libs: vec![] }),
 | |
|         SysrootKind::Llvm => build_llvm_sysroot_for_triple(compiler),
 | |
|         SysrootKind::Clif => {
 | |
|             build_clif_sysroot_for_triple(dirs, channel, compiler, cg_clif_dylib_path)
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[must_use]
 | |
| fn build_llvm_sysroot_for_triple(compiler: Compiler) -> SysrootTarget {
 | |
|     let default_sysroot = crate::rustc_info::get_default_sysroot(&compiler.rustc);
 | |
| 
 | |
|     let mut target_libs = SysrootTarget { triple: compiler.triple, libs: vec![] };
 | |
| 
 | |
|     for entry in fs::read_dir(
 | |
|         default_sysroot.join("lib").join("rustlib").join(&target_libs.triple).join("lib"),
 | |
|     )
 | |
|     .unwrap()
 | |
|     {
 | |
|         let entry = entry.unwrap();
 | |
|         if entry.file_type().unwrap().is_dir() {
 | |
|             continue;
 | |
|         }
 | |
|         let file = entry.path();
 | |
|         let file_name_str = file.file_name().unwrap().to_str().unwrap();
 | |
|         if (file_name_str.contains("rustc_")
 | |
|             && !file_name_str.contains("rustc_std_workspace_")
 | |
|             && !file_name_str.contains("rustc_demangle"))
 | |
|             || file_name_str.contains("chalk")
 | |
|             || file_name_str.contains("tracing")
 | |
|             || file_name_str.contains("regex")
 | |
|         {
 | |
|             // These are large crates that are part of the rustc-dev component and are not
 | |
|             // necessary to run regular programs.
 | |
|             continue;
 | |
|         }
 | |
|         target_libs.libs.push(file);
 | |
|     }
 | |
| 
 | |
|     target_libs
 | |
| }
 | |
| 
 | |
| #[must_use]
 | |
| fn build_clif_sysroot_for_triple(
 | |
|     dirs: &Dirs,
 | |
|     channel: &str,
 | |
|     mut compiler: Compiler,
 | |
|     cg_clif_dylib_path: &CodegenBackend,
 | |
| ) -> SysrootTarget {
 | |
|     let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
 | |
| 
 | |
|     if let Some(rtstartup_target_libs) = build_rtstartup(dirs, &compiler) {
 | |
|         rtstartup_target_libs.install_into_sysroot(&RTSTARTUP_SYSROOT.to_path(dirs));
 | |
| 
 | |
|         target_libs.libs.extend(rtstartup_target_libs.libs);
 | |
|     }
 | |
| 
 | |
|     let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(&compiler.triple).join(channel);
 | |
| 
 | |
|     if !config::get_bool("keep_sysroot") {
 | |
|         // Cleanup the deps dir, but keep build scripts and the incremental cache for faster
 | |
|         // recompilation as they are not affected by changes in cg_clif.
 | |
|         remove_dir_if_exists(&build_dir.join("deps"));
 | |
|     }
 | |
| 
 | |
|     // Build sysroot
 | |
|     let mut rustflags = vec!["-Zforce-unstable-if-unmarked".to_owned(), "-Cpanic=abort".to_owned()];
 | |
|     match cg_clif_dylib_path {
 | |
|         CodegenBackend::Local(path) => {
 | |
|             rustflags.push(format!("-Zcodegen-backend={}", path.to_str().unwrap()));
 | |
|         }
 | |
|         CodegenBackend::Builtin(name) => {
 | |
|             rustflags.push(format!("-Zcodegen-backend={name}"));
 | |
|         }
 | |
|     };
 | |
|     // Necessary for MinGW to find rsbegin.o and rsend.o
 | |
|     rustflags.push("--sysroot".to_owned());
 | |
|     rustflags.push(RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap().to_owned());
 | |
|     if channel == "release" {
 | |
|         // Incremental compilation by default disables mir inlining. This leads to both a decent
 | |
|         // compile perf and a significant runtime perf regression. As such forcefully enable mir
 | |
|         // inlining.
 | |
|         rustflags.push("-Zinline-mir".to_owned());
 | |
|     }
 | |
|     compiler.rustflags.extend(rustflags);
 | |
|     let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
 | |
|     maybe_incremental(&mut build_cmd);
 | |
|     if channel == "release" {
 | |
|         build_cmd.arg("--release");
 | |
|     }
 | |
|     build_cmd.arg("--features").arg("compiler-builtins-no-asm backtrace panic-unwind");
 | |
|     build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
 | |
|     build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
 | |
|     if compiler.triple.contains("apple") {
 | |
|         build_cmd.env("CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO", "packed");
 | |
|     }
 | |
|     spawn_and_wait(build_cmd);
 | |
| 
 | |
|     for entry in fs::read_dir(build_dir.join("deps")).unwrap() {
 | |
|         let entry = entry.unwrap();
 | |
|         if let Some(ext) = entry.path().extension() {
 | |
|             if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" {
 | |
|                 continue;
 | |
|             }
 | |
|         } else {
 | |
|             continue;
 | |
|         };
 | |
|         target_libs.libs.push(entry.path());
 | |
|     }
 | |
| 
 | |
|     target_libs
 | |
| }
 | |
| 
 | |
| fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
 | |
|     if !config::get_bool("keep_sysroot") {
 | |
|         crate::prepare::prepare_stdlib(dirs, &compiler.rustc);
 | |
|     }
 | |
| 
 | |
|     if !compiler.triple.ends_with("windows-gnu") {
 | |
|         return None;
 | |
|     }
 | |
| 
 | |
|     RTSTARTUP_SYSROOT.ensure_fresh(dirs);
 | |
| 
 | |
|     let rtstartup_src = STDLIB_SRC.to_path(dirs).join("library").join("rtstartup");
 | |
|     let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
 | |
| 
 | |
|     for file in ["rsbegin", "rsend"] {
 | |
|         let obj = RTSTARTUP_SYSROOT.to_path(dirs).join(format!("{file}.o"));
 | |
|         let mut build_rtstartup_cmd = Command::new(&compiler.rustc);
 | |
|         build_rtstartup_cmd
 | |
|             .arg("-Ainternal_features") // Missing #[allow(internal_features)]
 | |
|             .arg("--target")
 | |
|             .arg(&compiler.triple)
 | |
|             .arg("--emit=obj")
 | |
|             .arg("-o")
 | |
|             .arg(&obj)
 | |
|             .arg(rtstartup_src.join(format!("{file}.rs")));
 | |
|         spawn_and_wait(build_rtstartup_cmd);
 | |
|         target_libs.libs.push(obj.clone());
 | |
|     }
 | |
| 
 | |
|     Some(target_libs)
 | |
| }
 | 
