Skip to content

rustbuild: allow dynamically linking LLVM #37822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
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"
opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
opt llvm-link-shared 0 "prefer shared linking to LLVM (llvm-config --link-shared)"
opt rpath 1 "build rpaths into rustc itself"
opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0"
# This is used by the automation to produce single-target nightlies
Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
cargo.env("LLVM_STATIC_STDCPP",
compiler_file(build.cxx(target), "libstdc++.a"));
}
if build.config.llvm_link_shared {
cargo.env("LLVM_LINK_SHARED", "1");
}
if let Some(ref s) = build.config.rustc_default_linker {
cargo.env("CFG_DEFAULT_LINKER", s);
}
Expand Down
2 changes: 2 additions & 0 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub struct Config {
pub llvm_release_debuginfo: bool,
pub llvm_version_check: bool,
pub llvm_static_stdcpp: bool,
pub llvm_link_shared: bool,

// rust codegen options
pub rust_optimize: bool,
Expand Down Expand Up @@ -343,6 +344,7 @@ impl Config {
("OPTIMIZE_LLVM", self.llvm_optimize),
("LLVM_VERSION_CHECK", self.llvm_version_check),
("LLVM_STATIC_STDCPP", self.llvm_static_stdcpp),
("LLVM_LINK_SHARED", self.llvm_link_shared),
("OPTIMIZE", self.rust_optimize),
("DEBUG_ASSERTIONS", self.rust_debug_assertions),
("DEBUGINFO", self.rust_debuginfo),
Expand Down
45 changes: 34 additions & 11 deletions src/librustc_llvm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -174,7 +197,7 @@ fn main() {
}

let kind = if name.starts_with("LLVM") {
"static"
llvm_kind
} else {
"dylib"
};
Expand Down