]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
Auto merge of #103284 - compiler-errors:const-sad, r=oli-obk
[rust.git] / compiler / rustc_codegen_cranelift / build_system / build_sysroot.rs
1 use std::fs;
2 use std::path::{Path, PathBuf};
3 use std::process::{self, Command};
4
5 use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
6 use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
7 use super::SysrootKind;
8
9 pub(crate) fn build_sysroot(
10     channel: &str,
11     sysroot_kind: SysrootKind,
12     target_dir: &Path,
13     cg_clif_dylib_src: &Path,
14     host_triple: &str,
15     target_triple: &str,
16 ) {
17     eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
18
19     if target_dir.exists() {
20         fs::remove_dir_all(target_dir).unwrap();
21     }
22     fs::create_dir_all(target_dir.join("bin")).unwrap();
23     fs::create_dir_all(target_dir.join("lib")).unwrap();
24
25     // Copy the backend
26     let cg_clif_dylib_path = target_dir
27         .join(if cfg!(windows) {
28             // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
29             // binaries.
30             "bin"
31         } else {
32             "lib"
33         })
34         .join(get_file_name("rustc_codegen_cranelift", "dylib"));
35     try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
36
37     // Build and copy rustc and cargo wrappers
38     for wrapper in ["rustc-clif", "cargo-clif"] {
39         let wrapper_name = get_wrapper_file_name(wrapper, "bin");
40
41         let mut build_cargo_wrapper_cmd = Command::new("rustc");
42         build_cargo_wrapper_cmd
43             .arg(PathBuf::from("scripts").join(format!("{wrapper}.rs")))
44             .arg("-o")
45             .arg(target_dir.join(wrapper_name))
46             .arg("-g");
47         spawn_and_wait(build_cargo_wrapper_cmd);
48     }
49
50     let default_sysroot = super::rustc_info::get_default_sysroot();
51
52     let rustlib = target_dir.join("lib").join("rustlib");
53     let host_rustlib_lib = rustlib.join(host_triple).join("lib");
54     let target_rustlib_lib = rustlib.join(target_triple).join("lib");
55     fs::create_dir_all(&host_rustlib_lib).unwrap();
56     fs::create_dir_all(&target_rustlib_lib).unwrap();
57
58     if target_triple == "x86_64-pc-windows-gnu" {
59         if !default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib").exists() {
60             eprintln!(
61                 "The x86_64-pc-windows-gnu target needs to be installed first before it is possible \
62                 to compile a sysroot for it.",
63             );
64             process::exit(1);
65         }
66         for file in fs::read_dir(
67             default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"),
68         )
69         .unwrap()
70         {
71             let file = file.unwrap().path();
72             if file.extension().map_or(true, |ext| ext.to_str().unwrap() != "o") {
73                 continue; // only copy object files
74             }
75             try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap()));
76         }
77     }
78
79     match sysroot_kind {
80         SysrootKind::None => {} // Nothing to do
81         SysrootKind::Llvm => {
82             for file in fs::read_dir(
83                 default_sysroot.join("lib").join("rustlib").join(host_triple).join("lib"),
84             )
85             .unwrap()
86             {
87                 let file = file.unwrap().path();
88                 let file_name_str = file.file_name().unwrap().to_str().unwrap();
89                 if (file_name_str.contains("rustc_")
90                     && !file_name_str.contains("rustc_std_workspace_")
91                     && !file_name_str.contains("rustc_demangle"))
92                     || file_name_str.contains("chalk")
93                     || file_name_str.contains("tracing")
94                     || file_name_str.contains("regex")
95                 {
96                     // These are large crates that are part of the rustc-dev component and are not
97                     // necessary to run regular programs.
98                     continue;
99                 }
100                 try_hard_link(&file, host_rustlib_lib.join(file.file_name().unwrap()));
101             }
102
103             if target_triple != host_triple {
104                 for file in fs::read_dir(
105                     default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"),
106                 )
107                 .unwrap()
108                 {
109                     let file = file.unwrap().path();
110                     try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap()));
111                 }
112             }
113         }
114         SysrootKind::Clif => {
115             build_clif_sysroot_for_triple(
116                 channel,
117                 target_dir,
118                 host_triple,
119                 &cg_clif_dylib_path,
120                 None,
121             );
122
123             if host_triple != target_triple {
124                 // When cross-compiling it is often necessary to manually pick the right linker
125                 let linker = if target_triple == "aarch64-unknown-linux-gnu" {
126                     Some("aarch64-linux-gnu-gcc")
127                 } else {
128                     None
129                 };
130                 build_clif_sysroot_for_triple(
131                     channel,
132                     target_dir,
133                     target_triple,
134                     &cg_clif_dylib_path,
135                     linker,
136                 );
137             }
138
139             // Copy std for the host to the lib dir. This is necessary for the jit mode to find
140             // libstd.
141             for file in fs::read_dir(host_rustlib_lib).unwrap() {
142                 let file = file.unwrap().path();
143                 let filename = file.file_name().unwrap().to_str().unwrap();
144                 if filename.contains("std-") && !filename.contains(".rlib") {
145                     try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap()));
146                 }
147             }
148         }
149     }
150 }
151
152 fn build_clif_sysroot_for_triple(
153     channel: &str,
154     target_dir: &Path,
155     triple: &str,
156     cg_clif_dylib_path: &Path,
157     linker: Option<&str>,
158 ) {
159     match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) {
160         Err(e) => {
161             eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
162             eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source");
163             process::exit(1);
164         }
165         Ok(source_version) => {
166             let rustc_version = get_rustc_version();
167             if source_version != rustc_version {
168                 eprintln!("The patched sysroot source is outdated");
169                 eprintln!("Source version: {}", source_version.trim());
170                 eprintln!("Rustc version:  {}", rustc_version.trim());
171                 eprintln!("Hint: Try `./y.rs prepare` to update the patched sysroot source");
172                 process::exit(1);
173             }
174         }
175     }
176
177     let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel);
178
179     if !super::config::get_bool("keep_sysroot") {
180         // Cleanup the deps dir, but keep build scripts and the incremental cache for faster
181         // recompilation as they are not affected by changes in cg_clif.
182         if build_dir.join("deps").exists() {
183             fs::remove_dir_all(build_dir.join("deps")).unwrap();
184         }
185     }
186
187     // Build sysroot
188     let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot"));
189     let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
190     rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
191     rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap()));
192     if channel == "release" {
193         build_cmd.arg("--release");
194         rustflags.push_str(" -Zmir-opt-level=3");
195     }
196     if let Some(linker) = linker {
197         use std::fmt::Write;
198         write!(rustflags, " -Clinker={}", linker).unwrap();
199     }
200     build_cmd.env("RUSTFLAGS", rustflags);
201     build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
202     spawn_and_wait(build_cmd);
203
204     // Copy all relevant files to the sysroot
205     for entry in
206         fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps"))
207             .unwrap()
208     {
209         let entry = entry.unwrap();
210         if let Some(ext) = entry.path().extension() {
211             if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" {
212                 continue;
213             }
214         } else {
215             continue;
216         };
217         try_hard_link(
218             entry.path(),
219             target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()),
220         );
221     }
222 }