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.
This commit is contained in:
bors 2016-11-19 08:08:26 -08:00 committed by GitHub
commit b1da18fe9b
4 changed files with 40 additions and 11 deletions

View file

@ -17,6 +17,35 @@ use std::path::{PathBuf, Path};
use build_helper::output;
fn detect_llvm_link(llvm_config: &Path) -> (&'static str, Option<&'static str>) {
let mut version_cmd = Command::new(llvm_config);
version_cmd.arg("--version");
let version_output = output(&mut version_cmd);
let mut parts = version_output.split('.').take(2)
.filter_map(|s| s.parse::<u32>().ok());
if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
if major > 3 || (major == 3 && minor >= 9) {
// Force the link mode we want, preferring static by default, but
// possibly overridden by `configure --enable-llvm-link-shared`.
if env::var_os("LLVM_LINK_SHARED").is_some() {
return ("dylib", Some("--link-shared"));
} else {
return ("static", Some("--link-static"));
}
} else if major == 3 && minor == 8 {
// Find out LLVM's default linking mode.
let mut mode_cmd = Command::new(llvm_config);
mode_cmd.arg("--shared-mode");
if output(&mut mode_cmd).trim() == "shared" {
return ("dylib", None);
} else {
return ("static", None);
}
}
}
("static", None)
}
fn main() {
println!("cargo:rustc-cfg=cargobuild");
@ -123,22 +152,16 @@ fn main() {
.cpp_link_stdlib(None) // we handle this below
.compile("librustllvm.a");
let (llvm_kind, llvm_link_arg) = detect_llvm_link(&llvm_config);
// Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then
// we don't pick up system libs because unfortunately they're for the host
// of llvm-config, not the target that we're attempting to link.
let mut cmd = Command::new(&llvm_config);
cmd.arg("--libs");
// Force static linking with "--link-static" if available.
let mut version_cmd = Command::new(&llvm_config);
version_cmd.arg("--version");
let version_output = output(&mut version_cmd);
let mut parts = version_output.split('.');
if let (Some(major), Some(minor)) = (parts.next().and_then(|s| s.parse::<u32>().ok()),
parts.next().and_then(|s| s.parse::<u32>().ok())) {
if major > 3 || (major == 3 && minor >= 9) {
cmd.arg("--link-static");
}
if let Some(link_arg) = llvm_link_arg {
cmd.arg(link_arg);
}
if !is_crossed {
@ -174,7 +197,7 @@ fn main() {
}
let kind = if name.starts_with("LLVM") {
"static"
llvm_kind
} else {
"dylib"
};