Skip to content

Commit 2d21df8

Browse files
Workaround presence of LLVM library in stage0/lib
This commit works around the newly-introduced LLVM shared library. This is needed such that llvm-config run from librustc_llvm's build script can correctly locate it's own LLVM, not the one in stage0/lib. The LLVM build system uses the DT_RUNPATH/RUNPATH header within the llvm-config binary, which we want to use, but because Cargo always adds the host compiler's "libdir" (stage0/lib in our case) to the dynamic linker's search path, we weren't properly finding the freshly-built LLVM in llvm/lib. By restoring the environment variable setting the search path to what bootstrap sees, the problem is resolved and librustc_llvm correctly links and finds the appropriate LLVM. Several run-make-fulldeps tests are also updated with similar handling.
1 parent b7f030e commit 2d21df8

File tree

11 files changed

+55
-13
lines changed

11 files changed

+55
-13
lines changed

src/bootstrap/builder.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::install;
2121
use crate::native;
2222
use crate::test;
2323
use crate::tool;
24-
use crate::util::{add_lib_path, exe, libdir};
24+
use crate::util::{self, add_lib_path, exe, libdir};
2525
use crate::{Build, DocTests, Mode, GitRepo};
2626

2727
pub use crate::Compiler;
@@ -791,6 +791,13 @@ impl<'a> Builder<'a> {
791791
.env("CARGO_TARGET_DIR", out_dir)
792792
.arg(cmd);
793793

794+
// See comment in librustc_llvm/build.rs for why this is necessary, largely llvm-config
795+
// needs to not accidentally link to libLLVM in stage0/lib.
796+
cargo.env("REAL_LIBRARY_PATH_VAR", &util::dylib_path_var());
797+
if let Some(e) = env::var_os(util::dylib_path_var()) {
798+
cargo.env("REAL_LIBRARY_PATH", e);
799+
}
800+
794801
if cmd != "install" {
795802
cargo.arg("--target")
796803
.arg(target);

src/bootstrap/compile.rs

+1
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@ pub fn build_codegen_backend(builder: &Builder,
712712
if builder.is_rust_llvm(target) && backend != "emscripten" {
713713
cargo.env("LLVM_RUSTLLVM", "1");
714714
}
715+
715716
cargo.env("LLVM_CONFIG", &llvm_config);
716717
if backend != "emscripten" {
717718
let target_config = builder.config.target_config.get(&target);

src/bootstrap/util.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ pub fn dylib_path_var() -> &'static str {
7070
/// Parses the `dylib_path_var()` environment variable, returning a list of
7171
/// paths that are members of this lookup path.
7272
pub fn dylib_path() -> Vec<PathBuf> {
73-
env::split_paths(&env::var_os(dylib_path_var()).unwrap_or_default()).collect()
73+
let var = match env::var_os(dylib_path_var()) {
74+
Some(v) => v,
75+
None => return vec![],
76+
};
77+
env::split_paths(&var).collect()
7478
}
7579

7680
/// `push` all components to `buf`. On windows, append `.exe` to the last component.

src/build_helper/lib.rs

+19
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@ macro_rules! t {
2323
};
2424
}
2525

26+
// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
27+
// break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM
28+
// shared library, which means that when our freshly built llvm-config goes to load it's
29+
// associated LLVM, it actually loads the compiler's LLVM. In particular when building the first
30+
// compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from
31+
// the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't
32+
// perfect -- we might actually want to see something from Cargo's added library paths -- but
33+
// for now it works.
34+
pub fn restore_library_path() {
35+
println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH_VAR");
36+
println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH");
37+
let key = env::var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR");
38+
if let Some(env) = env::var_os("REAL_LIBRARY_PATH") {
39+
env::set_var(&key, &env);
40+
} else {
41+
env::remove_var(&key);
42+
}
43+
}
44+
2645
pub fn run(cmd: &mut Command) {
2746
println!("running: {:?}", cmd);
2847
run_silent(cmd);

src/librustc_asan/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use cmake::Config;
88

99
fn main() {
1010
if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
11+
build_helper::restore_library_path();
12+
1113
let (native, target) = match sanitizer_lib_boilerplate("asan") {
1214
Ok(native) => native,
1315
_ => return,

src/librustc_llvm/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ fn main() {
2424
return;
2525
}
2626

27+
build_helper::restore_library_path();
28+
2729
let target = env::var("TARGET").expect("TARGET was not set");
2830
let llvm_config = env::var_os("LLVM_CONFIG")
2931
.map(PathBuf::from)

src/librustc_lsan/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use cmake::Config;
88

99
fn main() {
1010
if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
11+
build_helper::restore_library_path();
12+
1113
let (native, target) = match sanitizer_lib_boilerplate("lsan") {
1214
Ok(native) => native,
1315
_ => return,

src/librustc_msan/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use cmake::Config;
88

99
fn main() {
1010
if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
11+
build_helper::restore_library_path();
12+
1113
let (native, target) = match sanitizer_lib_boilerplate("msan") {
1214
Ok(native) => native,
1315
_ => return,

src/librustc_tsan/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use cmake::Config;
88

99
fn main() {
1010
if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
11+
build_helper::restore_library_path();
12+
1113
let (native, target) = match sanitizer_lib_boilerplate("tsan") {
1214
Ok(native) => native,
1315
_ => return,

src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ all: staticlib.rs upstream.rs
99

1010
# Check No LTO
1111
$(RUSTC) staticlib.rs -Z cross-lang-lto -Ccodegen-units=1 -L. -o $(TMPDIR)/staticlib.a
12-
(cd $(TMPDIR); llvm-ar x ./staticlib.a)
12+
(cd $(TMPDIR); $(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) llvm-ar x ./staticlib.a)
1313
# Make sure the upstream object file was included
1414
ls $(TMPDIR)/upstream.*.rcgu.o
1515

@@ -19,5 +19,5 @@ all: staticlib.rs upstream.rs
1919
# Check ThinLTO
2020
$(RUSTC) upstream.rs -Z cross-lang-lto -Ccodegen-units=1 -Clto=thin
2121
$(RUSTC) staticlib.rs -Z cross-lang-lto -Ccodegen-units=1 -Clto=thin -L. -o $(TMPDIR)/staticlib.a
22-
(cd $(TMPDIR); llvm-ar x ./staticlib.a)
22+
(cd $(TMPDIR); $(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) llvm-ar x ./staticlib.a)
2323
ls $(TMPDIR)/upstream.*.rcgu.o

src/test/run-make-fulldeps/cross-lang-lto/Makefile

+10-9
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
# LLVM bitcode files (as used by linker LTO plugins) when compiling with
66
# -Z cross-lang-lto.
77

8-
ASSERT_IS_BITCODE_OBJ=llvm-bcanalyzer # this only succeeds for bitcode files
9-
EXTRACT_OBJS=(cd $(TMPDIR); rm -f ./*.o; llvm-ar x $(1))
8+
# this only succeeds for bitcode files
9+
ASSERT_IS_BITCODE_OBJ=($(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) llvm-bcanalyzer $(1))
10+
EXTRACT_OBJS=(cd $(TMPDIR); rm -f ./*.o; $(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) llvm-ar x $(1))
1011

1112
BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Z cross-lang-lto=on -Ccodegen-units=1
1213
BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Z cross-lang-lto=on -Ccodegen-units=1 --emit=obj
@@ -16,31 +17,31 @@ all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib
1617
staticlib: lib.rs
1718
$(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a
1819
$(call EXTRACT_OBJS, liblib.a)
19-
for file in $(TMPDIR)/liblib.*.rcgu.o; do $(ASSERT_IS_BITCODE_OBJ) $$file; done
20+
for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
2021

2122
staticlib-fat-lto: lib.rs
2223
$(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat
2324
$(call EXTRACT_OBJS, liblib-fat-lto.a)
24-
for file in $(TMPDIR)/liblib-fat-lto.*.rcgu.o; do $(ASSERT_IS_BITCODE_OBJ) $$file; done
25+
for file in $(TMPDIR)/liblib-fat-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
2526

2627
staticlib-thin-lto: lib.rs
2728
$(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin
2829
$(call EXTRACT_OBJS, liblib-thin-lto.a)
29-
for file in $(TMPDIR)/liblib-thin-lto.*.rcgu.o; do $(ASSERT_IS_BITCODE_OBJ) $$file; done
30+
for file in $(TMPDIR)/liblib-thin-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
3031

3132
rlib: lib.rs
3233
$(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib
3334
$(call EXTRACT_OBJS, liblib.rlib)
34-
for file in $(TMPDIR)/liblib.*.rcgu.o; do $(ASSERT_IS_BITCODE_OBJ) $$file; done
35+
for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
3536

3637
cdylib: lib.rs
3738
$(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o
38-
$(ASSERT_IS_BITCODE_OBJ) $(TMPDIR)/cdylib.o
39+
$(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/cdylib.o)
3940

4041
rdylib: lib.rs
4142
$(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o
42-
$(ASSERT_IS_BITCODE_OBJ) $(TMPDIR)/rdylib.o
43+
$(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/rdylib.o)
4344

4445
exe: lib.rs
4546
$(BUILD_EXE) -o $(TMPDIR)/exe.o
46-
$(ASSERT_IS_BITCODE_OBJ) $(TMPDIR)/exe.o
47+
$(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/exe.o)

0 commit comments

Comments
 (0)