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