Skip to content

Commit b1da18f

Browse files
authored
Auto merge of #37822 - cuviper:llvm-link-shared, r=alexcrichton
rustbuild: allow dynamically linking LLVM The makefiles and `mklldeps.py` called `llvm-config --shared-mode` to find out if LLVM defaulted to shared or static libraries, and just went with that. But under rustbuild, `librustc_llvm/build.rs` was assuming that LLVM should be static, and even forcing `--link-static` for 3.9+. Now that build script also uses `--shared-mode` to learn the default, which should work better for pre-3.9 configured for dynamic linking, as it wasn't possible back then to choose differently via `llvm-config`. Further, the configure script now has a new `--enable-llvm-link-shared` option, which allows one to manually override `--link-shared` on 3.9+ instead of forcing static. Update: There are now four static/shared scenarios that can happen for the supported LLVM versions: - 3.9+: By default use `llvm-config --link-static` - 3.9+ and `--enable-llvm-link-shared`: Use `--link-shared` instead. - 3.8: Use `llvm-config --shared-mode` and go with its answer. - 3.7: Just assume static, maintaining the status quo.
2 parents fb025b4 + f324037 commit b1da18f

File tree

4 files changed

+40
-11
lines changed

4 files changed

+40
-11
lines changed

configure

+1
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
624624
opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
625625
opt local-rebuild 0 "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version"
626626
opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
627+
opt llvm-link-shared 0 "prefer shared linking to LLVM (llvm-config --link-shared)"
627628
opt rpath 1 "build rpaths into rustc itself"
628629
opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0"
629630
# This is used by the automation to produce single-target nightlies

src/bootstrap/compile.rs

+3
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
212212
cargo.env("LLVM_STATIC_STDCPP",
213213
compiler_file(build.cxx(target), "libstdc++.a"));
214214
}
215+
if build.config.llvm_link_shared {
216+
cargo.env("LLVM_LINK_SHARED", "1");
217+
}
215218
if let Some(ref s) = build.config.rustc_default_linker {
216219
cargo.env("CFG_DEFAULT_LINKER", s);
217220
}

src/bootstrap/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub struct Config {
5353
pub llvm_release_debuginfo: bool,
5454
pub llvm_version_check: bool,
5555
pub llvm_static_stdcpp: bool,
56+
pub llvm_link_shared: bool,
5657

5758
// rust codegen options
5859
pub rust_optimize: bool,
@@ -346,6 +347,7 @@ impl Config {
346347
("OPTIMIZE_LLVM", self.llvm_optimize),
347348
("LLVM_VERSION_CHECK", self.llvm_version_check),
348349
("LLVM_STATIC_STDCPP", self.llvm_static_stdcpp),
350+
("LLVM_LINK_SHARED", self.llvm_link_shared),
349351
("OPTIMIZE", self.rust_optimize),
350352
("DEBUG_ASSERTIONS", self.rust_debug_assertions),
351353
("DEBUGINFO", self.rust_debuginfo),

src/librustc_llvm/build.rs

+34-11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,35 @@ use std::path::{PathBuf, Path};
1717

1818
use build_helper::output;
1919

20+
fn detect_llvm_link(llvm_config: &Path) -> (&'static str, Option<&'static str>) {
21+
let mut version_cmd = Command::new(llvm_config);
22+
version_cmd.arg("--version");
23+
let version_output = output(&mut version_cmd);
24+
let mut parts = version_output.split('.').take(2)
25+
.filter_map(|s| s.parse::<u32>().ok());
26+
if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
27+
if major > 3 || (major == 3 && minor >= 9) {
28+
// Force the link mode we want, preferring static by default, but
29+
// possibly overridden by `configure --enable-llvm-link-shared`.
30+
if env::var_os("LLVM_LINK_SHARED").is_some() {
31+
return ("dylib", Some("--link-shared"));
32+
} else {
33+
return ("static", Some("--link-static"));
34+
}
35+
} else if major == 3 && minor == 8 {
36+
// Find out LLVM's default linking mode.
37+
let mut mode_cmd = Command::new(llvm_config);
38+
mode_cmd.arg("--shared-mode");
39+
if output(&mut mode_cmd).trim() == "shared" {
40+
return ("dylib", None);
41+
} else {
42+
return ("static", None);
43+
}
44+
}
45+
}
46+
("static", None)
47+
}
48+
2049
fn main() {
2150
println!("cargo:rustc-cfg=cargobuild");
2251

@@ -123,22 +152,16 @@ fn main() {
123152
.cpp_link_stdlib(None) // we handle this below
124153
.compile("librustllvm.a");
125154

155+
let (llvm_kind, llvm_link_arg) = detect_llvm_link(&llvm_config);
156+
126157
// Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then
127158
// we don't pick up system libs because unfortunately they're for the host
128159
// of llvm-config, not the target that we're attempting to link.
129160
let mut cmd = Command::new(&llvm_config);
130161
cmd.arg("--libs");
131162

132-
// Force static linking with "--link-static" if available.
133-
let mut version_cmd = Command::new(&llvm_config);
134-
version_cmd.arg("--version");
135-
let version_output = output(&mut version_cmd);
136-
let mut parts = version_output.split('.');
137-
if let (Some(major), Some(minor)) = (parts.next().and_then(|s| s.parse::<u32>().ok()),
138-
parts.next().and_then(|s| s.parse::<u32>().ok())) {
139-
if major > 3 || (major == 3 && minor >= 9) {
140-
cmd.arg("--link-static");
141-
}
163+
if let Some(link_arg) = llvm_link_arg {
164+
cmd.arg(link_arg);
142165
}
143166

144167
if !is_crossed {
@@ -174,7 +197,7 @@ fn main() {
174197
}
175198

176199
let kind = if name.starts_with("LLVM") {
177-
"static"
200+
llvm_kind
178201
} else {
179202
"dylib"
180203
};

0 commit comments

Comments
 (0)