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