Skip to content

Commit e5e4eef

Browse files
committed
Auto merge of #106000 - nikic:lld-build, r=Mark-Simulacrum
Make LLD build forward-compatible with LLVM 16 Switch to using the cmake module instead of llvm-config. I believe this also removes the need for llvm-config-wrapper.
2 parents 2d8651a + 59b3157 commit e5e4eef

File tree

7 files changed

+58
-99
lines changed

7 files changed

+58
-99
lines changed

src/bootstrap/Cargo.toml

-5
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ name = "sccache-plus-cl"
2929
path = "bin/sccache-plus-cl.rs"
3030
test = false
3131

32-
[[bin]]
33-
name = "llvm-config-wrapper"
34-
path = "bin/llvm-config-wrapper.rs"
35-
test = false
36-
3732
[dependencies]
3833
cmake = "0.1.38"
3934
fd-lock = "3.0.8"

src/bootstrap/bin/llvm-config-wrapper.rs

-24
This file was deleted.

src/bootstrap/builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ impl<'a> Builder<'a> {
10681068
/// check build or dry-run, where there's no need to build all of LLVM.
10691069
fn llvm_config(&self, target: TargetSelection) -> Option<PathBuf> {
10701070
if self.config.llvm_enabled() && self.kind != Kind::Check && !self.config.dry_run() {
1071-
let llvm_config = self.ensure(native::Llvm { target });
1071+
let native::LlvmResult { llvm_config, .. } = self.ensure(native::Llvm { target });
10721072
if llvm_config.is_file() {
10731073
return Some(llvm_config);
10741074
}

src/bootstrap/compile.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
805805
if builder.is_rust_llvm(target) {
806806
cargo.env("LLVM_RUSTLLVM", "1");
807807
}
808-
let llvm_config = builder.ensure(native::Llvm { target });
808+
let native::LlvmResult { llvm_config, .. } = builder.ensure(native::Llvm { target });
809809
cargo.env("LLVM_CONFIG", &llvm_config);
810810
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
811811
cargo.env("CFG_LLVM_ROOT", s);
@@ -1341,9 +1341,10 @@ impl Step for Assemble {
13411341
}
13421342

13431343
if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
1344-
let llvm_config_bin = builder.ensure(native::Llvm { target: target_compiler.host });
1344+
let native::LlvmResult { llvm_config, .. } =
1345+
builder.ensure(native::Llvm { target: target_compiler.host });
13451346
if !builder.config.dry_run() {
1346-
let llvm_bin_dir = output(Command::new(llvm_config_bin).arg("--bindir"));
1347+
let llvm_bin_dir = output(Command::new(llvm_config).arg("--bindir"));
13471348
let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
13481349

13491350
// Since we've already built the LLVM tools, install them to the sysroot.

src/bootstrap/dist.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use crate::channel;
2424
use crate::compile;
2525
use crate::config::TargetSelection;
2626
use crate::doc::DocumentationFormat;
27+
use crate::native;
2728
use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
2829
use crate::tool::{self, Tool};
2930
use crate::util::{exe, is_dylib, output, t, timeit};
@@ -1927,7 +1928,9 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
19271928
builder.install(&llvm_dylib_path, dst_libdir, 0o644);
19281929
}
19291930
!builder.config.dry_run()
1930-
} else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
1931+
} else if let Ok(native::LlvmResult { llvm_config, .. }) =
1932+
native::prebuilt_llvm_config(builder, target)
1933+
{
19311934
let mut cmd = Command::new(llvm_config);
19321935
cmd.arg("--libfiles");
19331936
builder.verbose(&format!("running {:?}", cmd));
@@ -2137,7 +2140,7 @@ impl Step for Bootstrap {
21372140
let tarball = Tarball::new(builder, "bootstrap", &target.triple);
21382141

21392142
let bootstrap_outdir = &builder.bootstrap_out;
2140-
for file in &["bootstrap", "llvm-config-wrapper", "rustc", "rustdoc", "sccache-plus-cl"] {
2143+
for file in &["bootstrap", "rustc", "rustdoc", "sccache-plus-cl"] {
21412144
tarball.add_file(bootstrap_outdir.join(exe(file, target)), "bootstrap/bin", 0o755);
21422145
}
21432146

src/bootstrap/native.rs

+46-63
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,18 @@ use crate::util::get_clang_cl_resource_dir;
2424
use crate::util::{self, exe, output, t, up_to_date};
2525
use crate::{CLang, GitRepo};
2626

27+
#[derive(Clone)]
28+
pub struct LlvmResult {
29+
/// Path to llvm-config binary.
30+
/// NB: This is always the host llvm-config!
31+
pub llvm_config: PathBuf,
32+
/// Path to LLVM cmake directory for the target.
33+
pub llvm_cmake_dir: PathBuf,
34+
}
35+
2736
pub struct Meta {
2837
stamp: HashStamp,
29-
build_llvm_config: PathBuf,
38+
res: LlvmResult,
3039
out_dir: PathBuf,
3140
root: String,
3241
}
@@ -64,15 +73,22 @@ impl LdFlags {
6473
pub fn prebuilt_llvm_config(
6574
builder: &Builder<'_>,
6675
target: TargetSelection,
67-
) -> Result<PathBuf, Meta> {
76+
) -> Result<LlvmResult, Meta> {
6877
builder.config.maybe_download_ci_llvm();
6978

7079
// If we're using a custom LLVM bail out here, but we can only use a
7180
// custom LLVM for the build triple.
7281
if let Some(config) = builder.config.target_config.get(&target) {
7382
if let Some(ref s) = config.llvm_config {
7483
check_llvm_version(builder, s);
75-
return Ok(s.to_path_buf());
84+
let llvm_config = s.to_path_buf();
85+
let mut llvm_cmake_dir = llvm_config.clone();
86+
llvm_cmake_dir.pop();
87+
llvm_cmake_dir.pop();
88+
llvm_cmake_dir.push("lib");
89+
llvm_cmake_dir.push("cmake");
90+
llvm_cmake_dir.push("llvm");
91+
return Ok(LlvmResult { llvm_config, llvm_cmake_dir });
7692
}
7793
}
7894

@@ -84,8 +100,9 @@ pub fn prebuilt_llvm_config(
84100
llvm_config_ret_dir.push("build");
85101
}
86102
llvm_config_ret_dir.push("bin");
87-
88103
let build_llvm_config = llvm_config_ret_dir.join(exe("llvm-config", builder.config.build));
104+
let llvm_cmake_dir = out_dir.join("lib/cmake/llvm");
105+
let res = LlvmResult { llvm_config: build_llvm_config, llvm_cmake_dir };
89106

90107
let stamp = out_dir.join("llvm-finished-building");
91108
let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
@@ -96,7 +113,7 @@ pub fn prebuilt_llvm_config(
96113
Using a potentially stale build of LLVM; \
97114
This may not behave well.",
98115
);
99-
return Ok(build_llvm_config);
116+
return Ok(res);
100117
}
101118

102119
if stamp.is_done() {
@@ -110,10 +127,10 @@ pub fn prebuilt_llvm_config(
110127
stamp.path.display()
111128
));
112129
}
113-
return Ok(build_llvm_config);
130+
return Ok(res);
114131
}
115132

116-
Err(Meta { stamp, build_llvm_config, out_dir, root: root.into() })
133+
Err(Meta { stamp, res, out_dir, root: root.into() })
117134
}
118135

119136
/// This retrieves the LLVM sha we *want* to use, according to git history.
@@ -223,7 +240,7 @@ pub struct Llvm {
223240
}
224241

225242
impl Step for Llvm {
226-
type Output = PathBuf; // path to llvm-config
243+
type Output = LlvmResult;
227244

228245
const ONLY_HOSTS: bool = true;
229246

@@ -236,7 +253,7 @@ impl Step for Llvm {
236253
}
237254

238255
/// Compile LLVM for `target`.
239-
fn run(self, builder: &Builder<'_>) -> PathBuf {
256+
fn run(self, builder: &Builder<'_>) -> LlvmResult {
240257
let target = self.target;
241258
let target_native = if self.target.starts_with("riscv") {
242259
// RISC-V target triples in Rust is not named the same as C compiler target triples.
@@ -252,11 +269,10 @@ impl Step for Llvm {
252269
target.to_string()
253270
};
254271

255-
let Meta { stamp, build_llvm_config, out_dir, root } =
256-
match prebuilt_llvm_config(builder, target) {
257-
Ok(p) => return p,
258-
Err(m) => m,
259-
};
272+
let Meta { stamp, res, out_dir, root } = match prebuilt_llvm_config(builder, target) {
273+
Ok(p) => return p,
274+
Err(m) => m,
275+
};
260276

261277
builder.update_submodule(&Path::new("src").join("llvm-project"));
262278
if builder.llvm_link_shared() && target.contains("windows") {
@@ -430,7 +446,8 @@ impl Step for Llvm {
430446

431447
// https://llvm.org/docs/HowToCrossCompileLLVM.html
432448
if target != builder.config.build {
433-
let llvm_config = builder.ensure(Llvm { target: builder.config.build });
449+
let LlvmResult { llvm_config, .. } =
450+
builder.ensure(Llvm { target: builder.config.build });
434451
if !builder.config.dry_run() {
435452
let llvm_bindir = output(Command::new(&llvm_config).arg("--bindir"));
436453
let host_bin = Path::new(llvm_bindir.trim());
@@ -480,7 +497,7 @@ impl Step for Llvm {
480497
// tools and libs on all platforms.
481498

482499
if builder.config.dry_run() {
483-
return build_llvm_config;
500+
return res;
484501
}
485502

486503
cfg.build();
@@ -490,7 +507,7 @@ impl Step for Llvm {
490507
// for a versioned path like libLLVM-14.dylib. Manually create a symbolic
491508
// link to make llvm-config happy.
492509
if builder.llvm_link_shared() && target.contains("apple-darwin") {
493-
let mut cmd = Command::new(&build_llvm_config);
510+
let mut cmd = Command::new(&res.llvm_config);
494511
let version = output(cmd.arg("--version"));
495512
let major = version.split('.').next().unwrap();
496513
let lib_name = match llvm_version_suffix {
@@ -509,18 +526,18 @@ impl Step for Llvm {
509526
// LLVM after a configuration change, so to rebuild it the build files have to be removed,
510527
// which will also remove these modified files.
511528
if builder.config.llvm_bolt_profile_generate {
512-
instrument_with_bolt_inplace(&get_built_llvm_lib_path(&build_llvm_config));
529+
instrument_with_bolt_inplace(&get_built_llvm_lib_path(&res.llvm_config));
513530
}
514531
if let Some(path) = &builder.config.llvm_bolt_profile_use {
515532
optimize_library_with_bolt_inplace(
516-
&get_built_llvm_lib_path(&build_llvm_config),
533+
&get_built_llvm_lib_path(&res.llvm_config),
517534
&Path::new(path),
518535
);
519536
}
520537

521538
t!(stamp.write());
522539

523-
build_llvm_config
540+
res
524541
}
525542
}
526543

@@ -806,7 +823,8 @@ impl Step for Lld {
806823
}
807824
let target = self.target;
808825

809-
let llvm_config = builder.ensure(Llvm { target: self.target });
826+
let LlvmResult { llvm_config, llvm_cmake_dir } =
827+
builder.ensure(Llvm { target: self.target });
810828

811829
let out_dir = builder.lld_out(target);
812830
let done_stamp = out_dir.join("lld-finished-building");
@@ -837,22 +855,6 @@ impl Step for Lld {
837855
configure_cmake(builder, target, &mut cfg, true, ldflags);
838856
configure_llvm(builder, target, &mut cfg);
839857

840-
// This is an awful, awful hack. Discovered when we migrated to using
841-
// clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
842-
// tree, will execute `llvm-config --cmakedir` and then tell CMake about
843-
// that directory for later processing. Unfortunately if this path has
844-
// forward slashes in it (which it basically always does on Windows)
845-
// then CMake will hit a syntax error later on as... something isn't
846-
// escaped it seems?
847-
//
848-
// Instead of attempting to fix this problem in upstream CMake and/or
849-
// LLVM/LLD we just hack around it here. This thin wrapper will take the
850-
// output from llvm-config and replace all instances of `\` with `/` to
851-
// ensure we don't hit the same bugs with escaping. It means that you
852-
// can't build on a system where your paths require `\` on Windows, but
853-
// there's probably a lot of reasons you can't do that other than this.
854-
let llvm_config_shim = env::current_exe().unwrap().with_file_name("llvm-config-wrapper");
855-
856858
// Re-use the same flags as llvm to control the level of debug information
857859
// generated for lld.
858860
let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
@@ -863,36 +865,17 @@ impl Step for Lld {
863865

864866
cfg.out_dir(&out_dir)
865867
.profile(profile)
866-
.env("LLVM_CONFIG_REAL", &llvm_config)
867-
.define("LLVM_CONFIG_PATH", llvm_config_shim)
868+
.define("LLVM_CMAKE_DIR", llvm_cmake_dir)
868869
.define("LLVM_INCLUDE_TESTS", "OFF");
869870

870-
// While we're using this horrible workaround to shim the execution of
871-
// llvm-config, let's just pile on more. I can't seem to figure out how
872-
// to build LLD as a standalone project and also cross-compile it at the
873-
// same time. It wants a natively executable `llvm-config` to learn
874-
// about LLVM, but then it learns about all the host configuration of
875-
// LLVM and tries to link to host LLVM libraries.
876-
//
877-
// To work around that we tell our shim to replace anything with the
878-
// build target with the actual target instead. This'll break parts of
879-
// LLD though which try to execute host tools, such as llvm-tblgen, so
880-
// we specifically tell it where to find those. This is likely super
881-
// brittle and will break over time. If anyone knows better how to
882-
// cross-compile LLD it would be much appreciated to fix this!
883871
if target != builder.config.build {
884-
cfg.env("LLVM_CONFIG_SHIM_REPLACE", &builder.config.build.triple)
885-
.env("LLVM_CONFIG_SHIM_REPLACE_WITH", &target.triple)
886-
.define(
887-
"LLVM_TABLEGEN_EXE",
888-
llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION),
889-
);
872+
// Use the host llvm-tblgen binary.
873+
cfg.define(
874+
"LLVM_TABLEGEN_EXE",
875+
llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION),
876+
);
890877
}
891878

892-
// Explicitly set C++ standard, because upstream doesn't do so
893-
// for standalone builds.
894-
cfg.define("CMAKE_CXX_STANDARD", "14");
895-
896879
cfg.build();
897880

898881
t!(File::create(&done_stamp));
@@ -994,7 +977,7 @@ impl Step for Sanitizers {
994977
return runtimes;
995978
}
996979

997-
let llvm_config = builder.ensure(Llvm { target: builder.config.build });
980+
let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: builder.config.build });
998981
if builder.config.dry_run() {
999982
return runtimes;
1000983
}

src/bootstrap/test.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1575,7 +1575,8 @@ note: if you're sure you want to do this, please open an issue as to why. In the
15751575
let mut llvm_components_passed = false;
15761576
let mut copts_passed = false;
15771577
if builder.config.llvm_enabled() {
1578-
let llvm_config = builder.ensure(native::Llvm { target: builder.config.build });
1578+
let native::LlvmResult { llvm_config, .. } =
1579+
builder.ensure(native::Llvm { target: builder.config.build });
15791580
if !builder.config.dry_run() {
15801581
let llvm_version = output(Command::new(&llvm_config).arg("--version"));
15811582
let llvm_components = output(Command::new(&llvm_config).arg("--components"));

0 commit comments

Comments
 (0)