]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_llvm/build.rs
New upstream version 1.58.1+dfsg1
[rustc.git] / compiler / rustc_llvm / build.rs
CommitLineData
7453a54e 1use std::env;
dfeec247
XL
2use std::path::{Path, PathBuf};
3use std::process::Command;
7453a54e 4
3dfed10e 5use build_helper::{output, tracked_env_var_os};
7453a54e 6
ff7c6d11
XL
7fn detect_llvm_link() -> (&'static str, &'static str) {
8 // Force the link mode we want, preferring static by default, but
9 // possibly overridden by `configure --enable-llvm-link-shared`.
3dfed10e 10 if tracked_env_var_os("LLVM_LINK_SHARED").is_some() {
ff7c6d11
XL
11 ("dylib", "--link-shared")
12 } else {
13 ("static", "--link-static")
476ff2be 14 }
476ff2be
SL
15}
16
7453a54e 17fn main() {
3dfed10e 18 if tracked_env_var_os("RUST_CHECK").is_some() {
83c7162d 19 // If we're just running `check`, there's no need for LLVM to be built.
83c7162d
XL
20 return;
21 }
22
9fa01778
XL
23 build_helper::restore_library_path();
24
9e0c209e 25 let target = env::var("TARGET").expect("TARGET was not set");
ba9703b0 26 let llvm_config =
3dfed10e
XL
27 tracked_env_var_os("LLVM_CONFIG").map(|x| Some(PathBuf::from(x))).unwrap_or_else(|| {
28 if let Some(dir) = tracked_env_var_os("CARGO_TARGET_DIR").map(PathBuf::from) {
ba9703b0
XL
29 let to_test = dir
30 .parent()
31 .unwrap()
32 .parent()
33 .unwrap()
34 .join(&target)
35 .join("llvm/bin/llvm-config");
36 if Command::new(&to_test).output().is_ok() {
37 return Some(to_test);
38 }
c30ab7b3 39 }
ba9703b0
XL
40 None
41 });
42
43 if let Some(llvm_config) = &llvm_config {
44 println!("cargo:rerun-if-changed={}", llvm_config.display());
45 }
46 let llvm_config = llvm_config.unwrap_or_else(|| PathBuf::from("llvm-config"));
7453a54e 47
7453a54e
SL
48 // Test whether we're cross-compiling LLVM. This is a pretty rare case
49 // currently where we're producing an LLVM for a different platform than
50 // what this build script is currently running on.
51 //
52 // In that case, there's no guarantee that we can actually run the target,
53 // so the build system works around this by giving us the LLVM_CONFIG for
54 // the host platform. This only really works if the host LLVM and target
55 // LLVM are compiled the same way, but for us that's typically the case.
56 //
54a0048b 57 // We *want* detect this cross compiling situation by asking llvm-config
e1599b0c 58 // what its host-target is. If that's not the TARGET, then we're cross
54a0048b
SL
59 // compiling. Unfortunately `llvm-config` seems either be buggy, or we're
60 // misconfiguring it, because the `i686-pc-windows-gnu` build of LLVM will
61 // report itself with a `--host-target` of `x86_64-pc-windows-gnu`. This
62 // tricks us into thinking we're doing a cross build when we aren't, so
63 // havoc ensues.
64 //
65 // In any case, if we're cross compiling, this generally just means that we
e1599b0c 66 // can't trust all the output of llvm-config because it might be targeted
54a0048b
SL
67 // for the host rather than the target. As a result a bunch of blocks below
68 // are gated on `if !is_crossed`
9e0c209e
SL
69 let target = env::var("TARGET").expect("TARGET was not set");
70 let host = env::var("HOST").expect("HOST was not set");
7453a54e
SL
71 let is_crossed = target != host;
72
29967ef6 73 let optional_components = &[
dfeec247
XL
74 "x86",
75 "arm",
76 "aarch64",
77 "amdgpu",
f035d41b 78 "avr",
c295e0f8 79 "m68k",
dfeec247
XL
80 "mips",
81 "powerpc",
82 "systemz",
83 "jsbackend",
84 "webassembly",
85 "msp430",
86 "sparc",
87 "nvptx",
88 "hexagon",
29967ef6 89 "riscv",
17df50a5 90 "bpf",
dfeec247 91 ];
7cac9316 92
3dfed10e
XL
93 let required_components = &[
94 "ipo",
95 "bitreader",
96 "bitwriter",
97 "linker",
98 "asmparser",
99 "lto",
100 "coverage",
101 "instrumentation",
102 ];
7453a54e
SL
103
104 let components = output(Command::new(&llvm_config).arg("--components"));
105 let mut components = components.split_whitespace().collect::<Vec<_>>();
3157f602 106 components.retain(|c| optional_components.contains(c) || required_components.contains(c));
7453a54e
SL
107
108 for component in required_components {
109 if !components.contains(component) {
110 panic!("require llvm component {} but wasn't found", component);
111 }
112 }
113
114 for component in components.iter() {
115 println!("cargo:rustc-cfg=llvm_component=\"{}\"", component);
116 }
117
118 // Link in our own LLVM shims, compiled with the same flags as LLVM
119 let mut cmd = Command::new(&llvm_config);
120 cmd.arg("--cxxflags");
121 let cxxflags = output(&mut cmd);
ea8adc8c
XL
122 let mut cfg = cc::Build::new();
123 cfg.warnings(false);
7453a54e
SL
124 for flag in cxxflags.split_whitespace() {
125 // Ignore flags like `-m64` when we're doing a cross build
126 if is_crossed && flag.starts_with("-m") {
3157f602 127 continue;
7453a54e 128 }
cc61c64b 129
0731742a
XL
130 if flag.starts_with("-flto") {
131 continue;
132 }
133
cc61c64b
XL
134 // -Wdate-time is not supported by the netbsd cross compiler
135 if is_crossed && target.contains("netbsd") && flag.contains("date-time") {
136 continue;
137 }
138
3dfed10e
XL
139 // Include path contains host directory, replace it with target
140 if is_crossed && flag.starts_with("-I") {
141 cfg.flag(&flag.replace(&host, &target));
142 continue;
143 }
144
7453a54e
SL
145 cfg.flag(flag);
146 }
a7813a04 147
cc61c64b 148 for component in &components {
ff7c6d11 149 let mut flag = String::from("LLVM_COMPONENT_");
a7813a04 150 flag.push_str(&component.to_uppercase());
ff7c6d11 151 cfg.define(&flag, None);
a7813a04
XL
152 }
153
3dfed10e 154 if tracked_env_var_os("LLVM_RUSTLLVM").is_some() {
ff7c6d11 155 cfg.define("LLVM_RUSTLLVM", None);
5bcae85e
SL
156 }
157
3dfed10e 158 if tracked_env_var_os("LLVM_NDEBUG").is_some() {
e1599b0c 159 cfg.define("NDEBUG", None);
ba9703b0 160 cfg.debug(false);
e1599b0c
XL
161 }
162
1b1a35ee
XL
163 build_helper::rerun_if_changed_anything_in_dir(Path::new("llvm-wrapper"));
164 cfg.file("llvm-wrapper/PassWrapper.cpp")
165 .file("llvm-wrapper/RustWrapper.cpp")
166 .file("llvm-wrapper/ArchiveWrapper.cpp")
167 .file("llvm-wrapper/CoverageMappingWrapper.cpp")
168 .file("llvm-wrapper/Linker.cpp")
dfeec247
XL
169 .cpp(true)
170 .cpp_link_stdlib(None) // we handle this below
1b1a35ee 171 .compile("llvm-wrapper");
7453a54e 172
ff7c6d11 173 let (llvm_kind, llvm_link_arg) = detect_llvm_link();
476ff2be 174
e1599b0c 175 // Link in all LLVM libraries, if we're using the "wrong" llvm-config then
7453a54e
SL
176 // we don't pick up system libs because unfortunately they're for the host
177 // of llvm-config, not the target that we're attempting to link.
178 let mut cmd = Command::new(&llvm_config);
ff7c6d11 179 cmd.arg(llvm_link_arg).arg("--libs");
c30ab7b3 180
7453a54e
SL
181 if !is_crossed {
182 cmd.arg("--system-libs");
3dfed10e
XL
183 } else if target.contains("windows-gnu") {
184 println!("cargo:rustc-link-lib=shell32");
185 println!("cargo:rustc-link-lib=uuid");
94222f64 186 } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") {
1b1a35ee 187 println!("cargo:rustc-link-lib=z");
7453a54e 188 }
cc61c64b 189 cmd.args(&components);
7453a54e
SL
190
191 for lib in output(&mut cmd).split_whitespace() {
fc512014
XL
192 let name = if let Some(stripped) = lib.strip_prefix("-l") {
193 stripped
194 } else if let Some(stripped) = lib.strip_prefix('-') {
195 stripped
5bcae85e
SL
196 } else if Path::new(lib).exists() {
197 // On MSVC llvm-config will print the full name to libraries, but
198 // we're only interested in the name part
199 let name = Path::new(lib).file_name().unwrap().to_str().unwrap();
0731742a 200 name.trim_end_matches(".lib")
5bcae85e
SL
201 } else if lib.ends_with(".lib") {
202 // Some MSVC libraries just come up with `.lib` tacked on, so chop
203 // that off
0731742a 204 lib.trim_end_matches(".lib")
7453a54e 205 } else {
c30ab7b3 206 continue;
7453a54e
SL
207 };
208
209 // Don't need or want this library, but LLVM's CMake build system
210 // doesn't provide a way to disable it, so filter it here even though we
211 // may or may not have built it. We don't reference anything from this
212 // library and it otherwise may just pull in extra dependencies on
213 // libedit which we don't want
214 if name == "LLVMLineEditor" {
c30ab7b3 215 continue;
7453a54e
SL
216 }
217
dfeec247 218 let kind = if name.starts_with("LLVM") { llvm_kind } else { "dylib" };
7453a54e
SL
219 println!("cargo:rustc-link-lib={}={}", kind, name);
220 }
221
222 // LLVM ldflags
223 //
224 // If we're a cross-compile of LLVM then unfortunately we can't trust these
225 // ldflags (largely where all the LLVM libs are located). Currently just
226 // hack around this by replacing the host triple with the target and pray
227 // that those -L directories are the same!
228 let mut cmd = Command::new(&llvm_config);
ff7c6d11 229 cmd.arg(llvm_link_arg).arg("--ldflags");
7453a54e 230 for lib in output(&mut cmd).split_whitespace() {
dfeec247 231 if is_crossed {
fc512014
XL
232 if let Some(stripped) = lib.strip_prefix("-LIBPATH:") {
233 println!("cargo:rustc-link-search=native={}", stripped.replace(&host, &target));
234 } else if let Some(stripped) = lib.strip_prefix("-L") {
235 println!("cargo:rustc-link-search=native={}", stripped.replace(&host, &target));
7453a54e 236 }
fc512014
XL
237 } else if let Some(stripped) = lib.strip_prefix("-LIBPATH:") {
238 println!("cargo:rustc-link-search=native={}", stripped);
239 } else if let Some(stripped) = lib.strip_prefix("-l") {
240 println!("cargo:rustc-link-lib={}", stripped);
241 } else if let Some(stripped) = lib.strip_prefix("-L") {
242 println!("cargo:rustc-link-search=native={}", stripped);
7453a54e
SL
243 }
244 }
245
dc9dc135 246 // Some LLVM linker flags (-L and -l) may be needed even when linking
1b1a35ee 247 // rustc_llvm, for example when using static libc++, we may need to
dc9dc135
XL
248 // manually specify the library search path and -ldl -lpthread as link
249 // dependencies.
3dfed10e 250 let llvm_linker_flags = tracked_env_var_os("LLVM_LINKER_FLAGS");
dc9dc135
XL
251 if let Some(s) = llvm_linker_flags {
252 for lib in s.into_string().unwrap().split_whitespace() {
fc512014
XL
253 if let Some(stripped) = lib.strip_prefix("-l") {
254 println!("cargo:rustc-link-lib={}", stripped);
255 } else if let Some(stripped) = lib.strip_prefix("-L") {
256 println!("cargo:rustc-link-search=native={}", stripped);
dc9dc135
XL
257 }
258 }
259 }
260
3dfed10e
XL
261 let llvm_static_stdcpp = tracked_env_var_os("LLVM_STATIC_STDCPP");
262 let llvm_use_libcxx = tracked_env_var_os("LLVM_USE_LIBCXX");
cc61c64b 263
476ff2be 264 let stdcppname = if target.contains("openbsd") {
dfeec247 265 if target.contains("sparc64") { "estdc++" } else { "c++" }
ff7c6d11
XL
266 } else if target.contains("freebsd") {
267 "c++"
9fa01778
XL
268 } else if target.contains("darwin") {
269 "c++"
cc61c64b
XL
270 } else if target.contains("netbsd") && llvm_static_stdcpp.is_some() {
271 // NetBSD uses a separate library when relocation is required
272 "stdc++_pic"
0731742a
XL
273 } else if llvm_use_libcxx.is_some() {
274 "c++"
476ff2be
SL
275 } else {
276 "stdc++"
277 };
278
3dfed10e
XL
279 // RISC-V requires libatomic for sub-word atomic operations
280 if target.starts_with("riscv") {
281 println!("cargo:rustc-link-lib=atomic");
282 }
283
7453a54e
SL
284 // C++ runtime library
285 if !target.contains("msvc") {
cc61c64b 286 if let Some(s) = llvm_static_stdcpp {
7453a54e
SL
287 assert!(!cxxflags.contains("stdlib=libc++"));
288 let path = PathBuf::from(s);
dfeec247 289 println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display());
e74abb32 290 if target.contains("windows") {
3c0e092e 291 println!("cargo:rustc-link-lib=static:-bundle={}", stdcppname);
e74abb32
XL
292 } else {
293 println!("cargo:rustc-link-lib=static={}", stdcppname);
294 }
7453a54e
SL
295 } else if cxxflags.contains("stdlib=libc++") {
296 println!("cargo:rustc-link-lib=c++");
297 } else {
476ff2be 298 println!("cargo:rustc-link-lib={}", stdcppname);
7453a54e
SL
299 }
300 }
cc61c64b 301
f035d41b
XL
302 // Libstdc++ depends on pthread which Rust doesn't link on MinGW
303 // since nothing else requires it.
7cac9316 304 if target.contains("windows-gnu") {
3c0e092e 305 println!("cargo:rustc-link-lib=static:-bundle=pthread");
cc61c64b 306 }
7453a54e 307}