rustbuild: Support specifying archiver and linker explicitly
This commit is contained in:
parent
2689fd2402
commit
9e0fc5ccd0
29 changed files with 200 additions and 108 deletions
|
@ -300,7 +300,7 @@
|
|||
# =============================================================================
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
|
||||
# C compiler to be used to compiler C code and link Rust code. Note that the
|
||||
# C compiler to be used to compiler C code. Note that the
|
||||
# default value is platform specific, and if not specified it may also depend on
|
||||
# what platform is crossing to what platform.
|
||||
#cc = "cc"
|
||||
|
@ -309,6 +309,15 @@
|
|||
# This is only used for host targets.
|
||||
#cxx = "c++"
|
||||
|
||||
# Archiver to be used to assemble static libraries compiled from C/C++ code.
|
||||
# Note: an absolute path should be used, otherwise LLVM build will break.
|
||||
#ar = "ar"
|
||||
|
||||
# Linker to be used to link Rust code. Note that the
|
||||
# default value is platform specific, and if not specified it may also depend on
|
||||
# what platform is crossing to what platform.
|
||||
#linker = "cc"
|
||||
|
||||
# Path to the `llvm-config` binary of the installation of a custom LLVM to link
|
||||
# against. Note that if this is specifed we don't compile LLVM at all for this
|
||||
# target.
|
||||
|
|
1
src/Cargo.lock
generated
1
src/Cargo.lock
generated
|
@ -1994,7 +1994,6 @@ dependencies = [
|
|||
"alloc_jemalloc 0.0.0",
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"collections 0.0.0",
|
||||
"compiler_builtins 0.0.0",
|
||||
"core 0.0.0",
|
||||
|
|
|
@ -120,12 +120,6 @@ fn main() {
|
|||
cmd.arg("-L").arg(&root);
|
||||
}
|
||||
|
||||
// Pass down extra flags, commonly used to configure `-Clinker` when
|
||||
// cross compiling.
|
||||
if let Ok(s) = env::var("RUSTC_FLAGS") {
|
||||
cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
// Pass down incremental directory, if any.
|
||||
if let Ok(dir) = env::var("RUSTC_INCREMENTAL") {
|
||||
cmd.arg(format!("-Zincremental={}", dir));
|
||||
|
@ -254,6 +248,13 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
// Pass down extra flags, commonly used to configure `-Clinker`.
|
||||
// Linker options should be set for build scripts as well,
|
||||
// can't link a build script executable without a linker!
|
||||
if let Ok(s) = env::var("RUSTC_FLAGS") {
|
||||
cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
let color = match env::var("RUSTC_COLOR") {
|
||||
Ok(s) => usize::from_str(&s).expect("RUSTC_COLOR should be an integer"),
|
||||
Err(_) => 0,
|
||||
|
|
|
@ -47,6 +47,9 @@ fn main() {
|
|||
if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
|
||||
cmd.arg("-Z").arg("force-unstable-if-unmarked");
|
||||
}
|
||||
if let Some(linker) = env::var_os("RUSTDOC_LINKER") {
|
||||
cmd.arg("--linker").arg(linker).arg("-Z").arg("unstable-options");
|
||||
}
|
||||
|
||||
// Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick
|
||||
// it up so we can make rustdoc print this into the docs
|
||||
|
|
|
@ -413,13 +413,15 @@ impl<'a> Builder<'a> {
|
|||
pub fn rustdoc_cmd(&self, host: Interned<String>) -> Command {
|
||||
let mut cmd = Command::new(&self.out.join("bootstrap/debug/rustdoc"));
|
||||
let compiler = self.compiler(self.top_stage, host);
|
||||
cmd
|
||||
.env("RUSTC_STAGE", compiler.stage.to_string())
|
||||
.env("RUSTC_SYSROOT", self.sysroot(compiler))
|
||||
.env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
|
||||
.env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
|
||||
.env("RUSTDOC_REAL", self.rustdoc(host))
|
||||
.env("RUSTDOC_CRATE_VERSION", self.build.rust_version());
|
||||
cmd.env("RUSTC_STAGE", compiler.stage.to_string())
|
||||
.env("RUSTC_SYSROOT", self.sysroot(compiler))
|
||||
.env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
|
||||
.env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
|
||||
.env("RUSTDOC_REAL", self.rustdoc(host))
|
||||
.env("RUSTDOC_CRATE_VERSION", self.build.rust_version());
|
||||
if let Some(linker) = self.build.linker(host) {
|
||||
cmd.env("RUSTDOC_LINKER", linker);
|
||||
}
|
||||
cmd
|
||||
}
|
||||
|
||||
|
@ -485,6 +487,10 @@ impl<'a> Builder<'a> {
|
|||
.env("TEST_MIRI", self.config.test_miri.to_string())
|
||||
.env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));
|
||||
|
||||
if let Some(linker) = self.build.linker(target) {
|
||||
cargo.env("RUSTDOC_LINKER", linker);
|
||||
}
|
||||
|
||||
if mode != Mode::Tool {
|
||||
// Tools don't get debuginfo right now, e.g. cargo and rls don't
|
||||
// get compiled with debuginfo.
|
||||
|
@ -557,17 +563,35 @@ impl<'a> Builder<'a> {
|
|||
|
||||
cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
|
||||
|
||||
// Specify some various options for build scripts used throughout
|
||||
// the build.
|
||||
// Throughout the build Cargo can execute a number of build scripts
|
||||
// compiling C/C++ code and we need to pass compilers, archivers, flags, etc
|
||||
// obtained previously to those build scripts.
|
||||
// Build scripts use either the `cc` crate or `configure/make` so we pass
|
||||
// the options through environment variables that are fetched and understood by both.
|
||||
//
|
||||
// FIXME: the guard against msvc shouldn't need to be here
|
||||
if !target.contains("msvc") {
|
||||
cargo.env(format!("CC_{}", target), self.cc(target))
|
||||
.env(format!("AR_{}", target), self.ar(target).unwrap()) // only msvc is None
|
||||
.env(format!("CFLAGS_{}", target), self.cflags(target).join(" "));
|
||||
let cc = self.cc(target);
|
||||
cargo.env(format!("CC_{}", target), cc)
|
||||
.env("CC", cc);
|
||||
|
||||
let cflags = self.cflags(target).join(" ");
|
||||
cargo.env(format!("CFLAGS_{}", target), cflags.clone())
|
||||
.env("CFLAGS", cflags.clone());
|
||||
|
||||
if let Some(ar) = self.ar(target) {
|
||||
let ranlib = format!("{} s", ar.display());
|
||||
cargo.env(format!("AR_{}", target), ar)
|
||||
.env("AR", ar)
|
||||
.env(format!("RANLIB_{}", target), ranlib.clone())
|
||||
.env("RANLIB", ranlib);
|
||||
}
|
||||
|
||||
if let Ok(cxx) = self.cxx(target) {
|
||||
cargo.env(format!("CXX_{}", target), cxx);
|
||||
cargo.env(format!("CXX_{}", target), cxx)
|
||||
.env("CXX", cxx)
|
||||
.env(format!("CXXFLAGS_{}", target), cflags.clone())
|
||||
.env("CXXFLAGS", cflags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,20 +31,51 @@
|
|||
//! ever be probed for. Instead the compilers found here will be used for
|
||||
//! everything.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::{env, iter};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::iter;
|
||||
|
||||
use build_helper::{cc2ar, output};
|
||||
use build_helper::output;
|
||||
use cc;
|
||||
|
||||
use Build;
|
||||
use config::Target;
|
||||
use cache::Interned;
|
||||
|
||||
// The `cc` crate doesn't provide a way to obtain a path to the detected archiver,
|
||||
// so use some simplified logic here. First we respect the environment variable `AR`, then
|
||||
// try to infer the archiver path from the C compiler path.
|
||||
// In the future this logic should be replaced by calling into the `cc` crate.
|
||||
fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
|
||||
if let Some(ar) = env::var_os("AR") {
|
||||
Some(PathBuf::from(ar))
|
||||
} else if target.contains("msvc") {
|
||||
None
|
||||
} else if target.contains("musl") {
|
||||
Some(PathBuf::from("ar"))
|
||||
} else if target.contains("openbsd") {
|
||||
Some(PathBuf::from("ar"))
|
||||
} else {
|
||||
let parent = cc.parent().unwrap();
|
||||
let file = cc.file_name().unwrap().to_str().unwrap();
|
||||
for suffix in &["gcc", "cc", "clang"] {
|
||||
if let Some(idx) = file.rfind(suffix) {
|
||||
let mut file = file[..idx].to_owned();
|
||||
file.push_str("ar");
|
||||
return Some(parent.join(&file));
|
||||
}
|
||||
}
|
||||
Some(parent.join(file))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find(build: &mut Build) {
|
||||
// For all targets we're going to need a C compiler for building some shims
|
||||
// and such as well as for being a linker for Rust code.
|
||||
for target in build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build)) {
|
||||
let targets = build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build))
|
||||
.collect::<HashSet<_>>();
|
||||
for target in targets.into_iter() {
|
||||
let mut cfg = cc::Build::new();
|
||||
cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false)
|
||||
.target(&target).host(&build.build);
|
||||
|
@ -57,16 +88,23 @@ pub fn find(build: &mut Build) {
|
|||
}
|
||||
|
||||
let compiler = cfg.get_compiler();
|
||||
let ar = cc2ar(compiler.path(), &target);
|
||||
let ar = if let ar @ Some(..) = config.and_then(|c| c.ar.clone()) {
|
||||
ar
|
||||
} else {
|
||||
cc2ar(compiler.path(), &target)
|
||||
};
|
||||
|
||||
build.verbose(&format!("CC_{} = {:?}", &target, compiler.path()));
|
||||
if let Some(ref ar) = ar {
|
||||
build.cc.insert(target, compiler);
|
||||
if let Some(ar) = ar {
|
||||
build.verbose(&format!("AR_{} = {:?}", &target, ar));
|
||||
build.ar.insert(target, ar);
|
||||
}
|
||||
build.cc.insert(target, (compiler, ar));
|
||||
}
|
||||
|
||||
// For all host triples we need to find a C++ compiler as well
|
||||
for host in build.hosts.iter().cloned().chain(iter::once(build.build)) {
|
||||
let hosts = build.hosts.iter().cloned().chain(iter::once(build.build)).collect::<HashSet<_>>();
|
||||
for host in hosts.into_iter() {
|
||||
let mut cfg = cc::Build::new();
|
||||
cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false).cpp(true)
|
||||
.target(&host).host(&build.build);
|
||||
|
|
|
@ -725,6 +725,9 @@ impl Step for Compiletest {
|
|||
// Avoid depending on rustdoc when we don't need it.
|
||||
if mode == "rustdoc" || mode == "run-make" {
|
||||
cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host));
|
||||
if let Some(linker) = build.linker(target) {
|
||||
cmd.arg("--linker").arg(linker);
|
||||
}
|
||||
}
|
||||
|
||||
cmd.arg("--src-base").arg(build.src.join("src/test").join(suite));
|
||||
|
@ -806,6 +809,9 @@ impl Step for Compiletest {
|
|||
.arg("--cflags").arg(build.cflags(target).join(" "))
|
||||
.arg("--llvm-components").arg(llvm_components.trim())
|
||||
.arg("--llvm-cxxflags").arg(llvm_cxxflags.trim());
|
||||
if let Some(ar) = build.ar(target) {
|
||||
cmd.arg("--ar").arg(ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
if suite == "run-make" && !build.config.llvm_enabled {
|
||||
|
@ -831,7 +837,7 @@ impl Step for Compiletest {
|
|||
// Note that if we encounter `PATH` we make sure to append to our own `PATH`
|
||||
// rather than stomp over it.
|
||||
if target.contains("msvc") {
|
||||
for &(ref k, ref v) in build.cc[&target].0.env() {
|
||||
for &(ref k, ref v) in build.cc[&target].env() {
|
||||
if k != "PATH" {
|
||||
cmd.env(k, v);
|
||||
}
|
||||
|
|
|
@ -143,6 +143,8 @@ pub struct Target {
|
|||
pub jemalloc: Option<PathBuf>,
|
||||
pub cc: Option<PathBuf>,
|
||||
pub cxx: Option<PathBuf>,
|
||||
pub ar: Option<PathBuf>,
|
||||
pub linker: Option<PathBuf>,
|
||||
pub ndk: Option<PathBuf>,
|
||||
pub crt_static: Option<bool>,
|
||||
pub musl_root: Option<PathBuf>,
|
||||
|
@ -282,6 +284,8 @@ struct TomlTarget {
|
|||
jemalloc: Option<String>,
|
||||
cc: Option<String>,
|
||||
cxx: Option<String>,
|
||||
ar: Option<String>,
|
||||
linker: Option<String>,
|
||||
android_ndk: Option<String>,
|
||||
crt_static: Option<bool>,
|
||||
musl_root: Option<String>,
|
||||
|
@ -484,8 +488,10 @@ impl Config {
|
|||
if let Some(ref s) = cfg.android_ndk {
|
||||
target.ndk = Some(env::current_dir().unwrap().join(s));
|
||||
}
|
||||
target.cxx = cfg.cxx.clone().map(PathBuf::from);
|
||||
target.cc = cfg.cc.clone().map(PathBuf::from);
|
||||
target.cxx = cfg.cxx.clone().map(PathBuf::from);
|
||||
target.ar = cfg.ar.clone().map(PathBuf::from);
|
||||
target.linker = cfg.linker.clone().map(PathBuf::from);
|
||||
target.crt_static = cfg.crt_static.clone();
|
||||
target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
|
||||
target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
|
||||
|
|
|
@ -240,10 +240,11 @@ pub struct Build {
|
|||
lldb_python_dir: Option<String>,
|
||||
|
||||
// Runtime state filled in later on
|
||||
// target -> (cc, ar)
|
||||
cc: HashMap<Interned<String>, (cc::Tool, Option<PathBuf>)>,
|
||||
// host -> (cc, ar)
|
||||
// C/C++ compilers and archiver for all targets
|
||||
cc: HashMap<Interned<String>, cc::Tool>,
|
||||
cxx: HashMap<Interned<String>, cc::Tool>,
|
||||
ar: HashMap<Interned<String>, PathBuf>,
|
||||
// Misc
|
||||
crates: HashMap<Interned<String>, Crate>,
|
||||
is_sudo: bool,
|
||||
ci_env: CiEnv,
|
||||
|
@ -324,6 +325,7 @@ impl Build {
|
|||
rls_info,
|
||||
cc: HashMap::new(),
|
||||
cxx: HashMap::new(),
|
||||
ar: HashMap::new(),
|
||||
crates: HashMap::new(),
|
||||
lldb_version: None,
|
||||
lldb_python_dir: None,
|
||||
|
@ -612,7 +614,7 @@ impl Build {
|
|||
|
||||
/// Returns the path to the C compiler for the target specified.
|
||||
fn cc(&self, target: Interned<String>) -> &Path {
|
||||
self.cc[&target].0.path()
|
||||
self.cc[&target].path()
|
||||
}
|
||||
|
||||
/// Returns a list of flags to pass to the C compiler for the target
|
||||
|
@ -620,7 +622,7 @@ impl Build {
|
|||
fn cflags(&self, target: Interned<String>) -> Vec<String> {
|
||||
// Filter out -O and /O (the optimization flags) that we picked up from
|
||||
// cc-rs because the build scripts will determine that for themselves.
|
||||
let mut base = self.cc[&target].0.args().iter()
|
||||
let mut base = self.cc[&target].args().iter()
|
||||
.map(|s| s.to_string_lossy().into_owned())
|
||||
.filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -644,7 +646,11 @@ impl Build {
|
|||
|
||||
/// Returns the path to the `ar` archive utility for the target specified.
|
||||
fn ar(&self, target: Interned<String>) -> Option<&Path> {
|
||||
self.cc[&target].1.as_ref().map(|p| &**p)
|
||||
self.ar.get(&target).map(|p| &**p)
|
||||
}
|
||||
|
||||
fn linker(&self, target: Interned<String>) -> Option<&Path> {
|
||||
self.config.target_config.get(&target).and_then(|c| c.linker.as_ref().map(|p| &**p))
|
||||
}
|
||||
|
||||
/// Returns the path to the C++ compiler for the target specified.
|
||||
|
@ -667,7 +673,10 @@ impl Build {
|
|||
// than an entry here.
|
||||
|
||||
let mut base = Vec::new();
|
||||
if target != self.config.build && !target.contains("msvc") &&
|
||||
if let Some(linker) = self.linker(target) {
|
||||
// If linker was explictly provided, force it on all the compiled Rust code.
|
||||
base.push(format!("-Clinker={}", linker.display()));
|
||||
} else if target != self.config.build && !target.contains("msvc") &&
|
||||
!target.contains("emscripten") {
|
||||
base.push(format!("-Clinker={}", self.cc(target).display()));
|
||||
}
|
||||
|
|
|
@ -227,6 +227,13 @@ impl Step for Llvm {
|
|||
cfg.build_arg("-j").build_arg(build.jobs().to_string());
|
||||
cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" "));
|
||||
cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" "));
|
||||
if let Some(ar) = build.ar(target) {
|
||||
if ar.is_absolute() {
|
||||
// LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it
|
||||
// tries to resolve this path in the LLVM build directory.
|
||||
cfg.define("CMAKE_AR", sanitize_cc(ar));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
configure_compilers(&mut cfg);
|
||||
|
|
|
@ -561,7 +561,7 @@ impl<'a> Builder<'a> {
|
|||
if compiler.host.contains("msvc") {
|
||||
let curpaths = env::var_os("PATH").unwrap_or_default();
|
||||
let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
|
||||
for &(ref k, ref v) in self.cc[&compiler.host].0.env() {
|
||||
for &(ref k, ref v) in self.cc[&compiler.host].env() {
|
||||
if k != "PATH" {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -138,27 +138,6 @@ pub fn gnu_target(target: &str) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
|
||||
if target.contains("msvc") {
|
||||
None
|
||||
} else if target.contains("musl") {
|
||||
Some(PathBuf::from("ar"))
|
||||
} else if target.contains("openbsd") {
|
||||
Some(PathBuf::from("ar"))
|
||||
} else {
|
||||
let parent = cc.parent().unwrap();
|
||||
let file = cc.file_name().unwrap().to_str().unwrap();
|
||||
for suffix in &["gcc", "cc", "clang"] {
|
||||
if let Some(idx) = file.rfind(suffix) {
|
||||
let mut file = file[..idx].to_owned();
|
||||
file.push_str("ar");
|
||||
return Some(parent.join(&file));
|
||||
}
|
||||
}
|
||||
Some(parent.join(file))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make(host: &str) -> PathBuf {
|
||||
if host.contains("bitrig") || host.contains("dragonfly") ||
|
||||
host.contains("freebsd") || host.contains("netbsd") ||
|
||||
|
|
|
@ -63,15 +63,6 @@ fn main() {
|
|||
_ => return,
|
||||
};
|
||||
|
||||
let compiler = cc::Build::new().get_compiler();
|
||||
// only msvc returns None for ar so unwrap is okay
|
||||
let ar = build_helper::cc2ar(compiler.path(), &target).unwrap();
|
||||
let cflags = compiler.args()
|
||||
.iter()
|
||||
.map(|s| s.to_str().unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
|
||||
let mut cmd = Command::new("sh");
|
||||
cmd.arg(native.src_dir.join("configure")
|
||||
.to_str()
|
||||
|
@ -79,8 +70,6 @@ fn main() {
|
|||
.replace("C:\\", "/c/")
|
||||
.replace("\\", "/"))
|
||||
.current_dir(&native.out_dir)
|
||||
.env("CC", compiler.path())
|
||||
.env("EXTRA_CFLAGS", cflags.clone())
|
||||
// jemalloc generates Makefile deps using GCC's "-MM" flag. This means
|
||||
// that GCC will run the preprocessor, and only the preprocessor, over
|
||||
// jemalloc's source files. If we don't specify CPPFLAGS, then at least
|
||||
|
@ -89,9 +78,7 @@ fn main() {
|
|||
// passed to GCC, and then GCC won't define the
|
||||
// "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
|
||||
// select an atomic operation implementation.
|
||||
.env("CPPFLAGS", cflags.clone())
|
||||
.env("AR", &ar)
|
||||
.env("RANLIB", format!("{} s", ar.display()));
|
||||
.env("CPPFLAGS", env::var_os("CFLAGS").unwrap_or_default());
|
||||
|
||||
if target.contains("ios") {
|
||||
cmd.arg("--disable-tls");
|
||||
|
|
|
@ -246,6 +246,9 @@ pub fn opts() -> Vec<RustcOptGroup> {
|
|||
unstable("crate-version", |o| {
|
||||
o.optopt("", "crate-version", "crate version to print into documentation", "VERSION")
|
||||
}),
|
||||
unstable("linker", |o| {
|
||||
o.optopt("", "linker", "linker used for building executable test code", "PATH")
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -357,15 +360,16 @@ pub fn main_args(args: &[String]) -> isize {
|
|||
let playground_url = matches.opt_str("playground-url");
|
||||
let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
|
||||
let display_warnings = matches.opt_present("display-warnings");
|
||||
let linker = matches.opt_str("linker");
|
||||
|
||||
match (should_test, markdown_input) {
|
||||
(true, true) => {
|
||||
return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot, render_type,
|
||||
display_warnings)
|
||||
display_warnings, linker)
|
||||
}
|
||||
(true, false) => {
|
||||
return test::run(input, cfgs, libs, externs, test_args, crate_name, maybe_sysroot,
|
||||
render_type, display_warnings)
|
||||
render_type, display_warnings, linker)
|
||||
}
|
||||
(false, true) => return markdown::render(input,
|
||||
output.unwrap_or(PathBuf::from("doc")),
|
||||
|
|
|
@ -142,7 +142,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
|
|||
/// Run any tests/code examples in the markdown file `input`.
|
||||
pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
|
||||
mut test_args: Vec<String>, maybe_sysroot: Option<PathBuf>,
|
||||
render_type: RenderType, display_warnings: bool) -> isize {
|
||||
render_type: RenderType, display_warnings: bool, linker: Option<String>) -> isize {
|
||||
let input_str = match load_string(input) {
|
||||
Ok(s) => s,
|
||||
Err(LoadStringError::ReadFail) => return 1,
|
||||
|
@ -154,7 +154,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
|
|||
let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
|
||||
true, opts, maybe_sysroot, None,
|
||||
Some(input.to_owned()),
|
||||
render_type);
|
||||
render_type, linker);
|
||||
if render_type == RenderType::Pulldown {
|
||||
old_find_testable_code(&input_str, &mut collector, DUMMY_SP);
|
||||
find_testable_code(&input_str, &mut collector, DUMMY_SP);
|
||||
|
|
|
@ -61,7 +61,8 @@ pub fn run(input: &str,
|
|||
crate_name: Option<String>,
|
||||
maybe_sysroot: Option<PathBuf>,
|
||||
render_type: RenderType,
|
||||
display_warnings: bool)
|
||||
display_warnings: bool,
|
||||
linker: Option<String>)
|
||||
-> isize {
|
||||
let input_path = PathBuf::from(input);
|
||||
let input = config::Input::File(input_path.clone());
|
||||
|
@ -121,7 +122,8 @@ pub fn run(input: &str,
|
|||
maybe_sysroot,
|
||||
Some(codemap),
|
||||
None,
|
||||
render_type);
|
||||
render_type,
|
||||
linker);
|
||||
|
||||
{
|
||||
let map = hir::map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
|
||||
|
@ -180,7 +182,8 @@ fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec<String>, libs
|
|||
externs: Externs,
|
||||
should_panic: bool, no_run: bool, as_test_harness: bool,
|
||||
compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
|
||||
maybe_sysroot: Option<PathBuf>) {
|
||||
maybe_sysroot: Option<PathBuf>,
|
||||
linker: Option<String>) {
|
||||
// the test harness wants its own `main` & top level functions, so
|
||||
// never wrap the test in `fn main() { ... }`
|
||||
let test = make_test(test, Some(cratename), as_test_harness, opts);
|
||||
|
@ -201,6 +204,7 @@ fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec<String>, libs
|
|||
externs,
|
||||
cg: config::CodegenOptions {
|
||||
prefer_dynamic: true,
|
||||
linker,
|
||||
.. config::basic_codegen_options()
|
||||
},
|
||||
test: as_test_harness,
|
||||
|
@ -442,13 +446,14 @@ pub struct Collector {
|
|||
filename: Option<String>,
|
||||
// to be removed when hoedown will be removed as well
|
||||
pub render_type: RenderType,
|
||||
linker: Option<String>,
|
||||
}
|
||||
|
||||
impl Collector {
|
||||
pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
|
||||
use_headers: bool, opts: TestOptions, maybe_sysroot: Option<PathBuf>,
|
||||
codemap: Option<Rc<CodeMap>>, filename: Option<String>,
|
||||
render_type: RenderType) -> Collector {
|
||||
render_type: RenderType, linker: Option<String>) -> Collector {
|
||||
Collector {
|
||||
tests: Vec::new(),
|
||||
old_tests: HashMap::new(),
|
||||
|
@ -464,6 +469,7 @@ impl Collector {
|
|||
codemap,
|
||||
filename,
|
||||
render_type,
|
||||
linker,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,6 +516,7 @@ impl Collector {
|
|||
let cratename = self.cratename.to_string();
|
||||
let opts = self.opts.clone();
|
||||
let maybe_sysroot = self.maybe_sysroot.clone();
|
||||
let linker = self.linker.clone();
|
||||
debug!("Creating test {}: {}", name, test);
|
||||
self.tests.push(testing::TestDescAndFn {
|
||||
desc: testing::TestDesc {
|
||||
|
@ -538,7 +545,8 @@ impl Collector {
|
|||
compile_fail,
|
||||
error_codes,
|
||||
&opts,
|
||||
maybe_sysroot)
|
||||
maybe_sysroot,
|
||||
linker)
|
||||
})
|
||||
} {
|
||||
Ok(()) => (),
|
||||
|
|
|
@ -36,7 +36,6 @@ rustc_tsan = { path = "../librustc_tsan" }
|
|||
|
||||
[build-dependencies]
|
||||
build_helper = { path = "../build_helper" }
|
||||
cc = "1.0.1"
|
||||
|
||||
[features]
|
||||
backtrace = []
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
extern crate build_helper;
|
||||
extern crate cc;
|
||||
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
|
@ -77,12 +76,6 @@ fn main() {
|
|||
fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
|
||||
let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
|
||||
|
||||
let compiler = cc::Build::new().get_compiler();
|
||||
// only msvc returns None for ar so unwrap is okay
|
||||
let ar = build_helper::cc2ar(compiler.path(), target).unwrap();
|
||||
let mut cflags = compiler.args().iter().map(|s| s.to_str().unwrap())
|
||||
.collect::<Vec<_>>().join(" ");
|
||||
cflags.push_str(" -fvisibility=hidden");
|
||||
run(Command::new("sh")
|
||||
.current_dir(&native.out_dir)
|
||||
.arg(native.src_dir.join("configure").to_str().unwrap()
|
||||
|
@ -94,10 +87,7 @@ fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
|
|||
.arg("--disable-host-shared")
|
||||
.arg(format!("--host={}", build_helper::gnu_target(target)))
|
||||
.arg(format!("--build={}", build_helper::gnu_target(host)))
|
||||
.env("CC", compiler.path())
|
||||
.env("AR", &ar)
|
||||
.env("RANLIB", format!("{} s", ar.display()))
|
||||
.env("CFLAGS", cflags),
|
||||
.env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"),
|
||||
BuildExpectation::None);
|
||||
|
||||
run(Command::new(build_helper::make(host))
|
||||
|
|
|
@ -5,7 +5,7 @@ all:
|
|||
mkdir $(TMPDIR)/b
|
||||
$(call COMPILE_OBJ,$(TMPDIR)/a/foo.o,foo.c)
|
||||
$(call COMPILE_OBJ,$(TMPDIR)/b/foo.o,bar.c)
|
||||
ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o
|
||||
$(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o
|
||||
$(RUSTC) foo.rs
|
||||
$(RUSTC) bar.rs
|
||||
$(call RUN,bar)
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
ifneq (,$(findstring MINGW,$(UNAME)))
|
||||
ifndef IS_MSVC
|
||||
all:
|
||||
g++ foo.cpp -c -o $(TMPDIR)/foo.o
|
||||
ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o
|
||||
$(CXX) foo.cpp -c -o $(TMPDIR)/foo.o
|
||||
$(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o
|
||||
$(RUSTC) foo.rs -lfoo -lstdc++
|
||||
$(call RUN,foo)
|
||||
else
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
|
||||
all:
|
||||
touch $(TMPDIR)/rust.metadata.bin
|
||||
ar crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/rust.metadata.bin
|
||||
$(AR) crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/rust.metadata.bin
|
||||
$(RUSTC) foo.rs 2>&1 | grep "can't find crate for"
|
||||
|
|
|
@ -18,7 +18,6 @@ extern crate rustc_errors;
|
|||
extern crate rustc_trans;
|
||||
extern crate syntax;
|
||||
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::session::{build_session, Session};
|
||||
use rustc::session::config::{basic_options, build_configuration, Input,
|
||||
OutputType, OutputTypes};
|
||||
|
@ -56,6 +55,9 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
|
|||
let mut opts = basic_options();
|
||||
opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
|
||||
opts.maybe_sysroot = Some(sysroot);
|
||||
if let Ok(linker) = std::env::var("RUSTC_LINKER") {
|
||||
opts.cg.linker = Some(linker);
|
||||
}
|
||||
|
||||
let descriptions = Registry::new(&rustc::DIAGNOSTICS);
|
||||
let cstore = Rc::new(CStore::new(Box::new(rustc_trans::LlvmMetadataLoader)));
|
||||
|
@ -67,8 +69,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
|
|||
|
||||
fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
|
||||
let (sess, cstore) = basic_sess(sysroot);
|
||||
let cfg = build_configuration(&sess, HashSet::new());
|
||||
let control = CompileController::basic();
|
||||
let input = Input::Str { name: anon_src(), input: code };
|
||||
compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control);
|
||||
let _ = compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
all: foo.rs
|
||||
$(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs
|
||||
$(HOST_RPATH_ENV) '$(RUSTDOC)' --test --cfg 'feature="bar"' \
|
||||
$(RUSTDOC) --test --cfg 'feature="bar"' \
|
||||
-L $(TMPDIR) foo.rs |\
|
||||
grep -q 'foo.rs - foo (line 11) ... ok'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(HOST_RPATH_ENV) '$(RUSTDOC)' -o "$(TMPDIR)/foo/bar/doc" foo.rs
|
||||
$(RUSTDOC) -o "$(TMPDIR)/foo/bar/doc" foo.rs
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
ar crus $(TMPDIR)/libfoo.a foo.rs
|
||||
ar d $(TMPDIR)/libfoo.a foo.rs
|
||||
$(AR) crus $(TMPDIR)/libfoo.a foo.rs
|
||||
$(AR) d $(TMPDIR)/libfoo.a foo.rs
|
||||
$(RUSTC) foo.rs
|
||||
|
|
|
@ -7,7 +7,13 @@ TARGET_RPATH_ENV = \
|
|||
|
||||
RUSTC_ORIGINAL := $(RUSTC)
|
||||
BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)'
|
||||
BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)'
|
||||
RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS)
|
||||
RUSTDOC := $(BARE_RUSTDOC)
|
||||
ifdef RUSTC_LINKER
|
||||
RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER)
|
||||
RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options
|
||||
endif
|
||||
#CC := $(CC) -L $(TMPDIR)
|
||||
HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py
|
||||
|
||||
|
@ -102,13 +108,13 @@ REMOVE_DYLIBS = rm $(TMPDIR)/$(call DYLIB_GLOB,$(1))
|
|||
REMOVE_RLIBS = rm $(TMPDIR)/$(call RLIB_GLOB,$(1))
|
||||
|
||||
%.a: %.o
|
||||
ar crus $@ $<
|
||||
$(AR) crus $@ $<
|
||||
ifdef IS_MSVC
|
||||
%.lib: lib%.o
|
||||
$(MSVC_LIB) -out:`cygpath -w $@` $<
|
||||
else
|
||||
%.lib: lib%.o
|
||||
ar crus $@ $<
|
||||
$(AR) crus $@ $<
|
||||
endif
|
||||
%.dylib: %.o
|
||||
$(CC) -dynamiclib -Wl,-dylib -o $@ $<
|
||||
|
|
|
@ -201,6 +201,8 @@ pub struct Config {
|
|||
pub cc: String,
|
||||
pub cxx: String,
|
||||
pub cflags: String,
|
||||
pub ar: String,
|
||||
pub linker: Option<String>,
|
||||
pub llvm_components: String,
|
||||
pub llvm_cxxflags: String,
|
||||
pub nodejs: Option<String>,
|
||||
|
|
|
@ -102,6 +102,8 @@ pub fn parse_config(args: Vec<String> ) -> Config {
|
|||
.reqopt("", "cc", "path to a C compiler", "PATH")
|
||||
.reqopt("", "cxx", "path to a C++ compiler", "PATH")
|
||||
.reqopt("", "cflags", "flags for the C compiler", "FLAGS")
|
||||
.optopt("", "ar", "path to an archiver", "PATH")
|
||||
.optopt("", "linker", "path to a linker", "PATH")
|
||||
.reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
|
||||
.reqopt("", "llvm-cxxflags", "C++ flags for LLVM", "FLAGS")
|
||||
.optopt("", "nodejs", "the name of nodejs", "PATH")
|
||||
|
@ -198,6 +200,8 @@ pub fn parse_config(args: Vec<String> ) -> Config {
|
|||
cc: matches.opt_str("cc").unwrap(),
|
||||
cxx: matches.opt_str("cxx").unwrap(),
|
||||
cflags: matches.opt_str("cflags").unwrap(),
|
||||
ar: matches.opt_str("ar").unwrap_or("ar".into()),
|
||||
linker: matches.opt_str("linker"),
|
||||
llvm_components: matches.opt_str("llvm-components").unwrap(),
|
||||
llvm_cxxflags: matches.opt_str("llvm-cxxflags").unwrap(),
|
||||
nodejs: matches.opt_str("nodejs"),
|
||||
|
@ -234,6 +238,8 @@ pub fn log_config(config: &Config) {
|
|||
logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
|
||||
logv(c, format!("adb_device_status: {}",
|
||||
config.adb_device_status));
|
||||
logv(c, format!("ar: {}", config.ar));
|
||||
logv(c, format!("linker: {:?}", config.linker));
|
||||
logv(c, format!("verbose: {}", config.verbose));
|
||||
logv(c, format!("quiet: {}", config.quiet));
|
||||
logv(c, "\n".to_string());
|
||||
|
|
|
@ -1155,6 +1155,9 @@ actual:\n\
|
|||
.arg("-o").arg(out_dir)
|
||||
.arg(&self.testpaths.file)
|
||||
.args(&self.props.compile_flags);
|
||||
if let Some(ref linker) = self.config.linker {
|
||||
rustdoc.arg("--linker").arg(linker).arg("-Z").arg("unstable-options");
|
||||
}
|
||||
|
||||
self.compose_and_run_compiler(rustdoc, None)
|
||||
}
|
||||
|
@ -2101,6 +2104,10 @@ actual:\n\
|
|||
.env("LLVM_COMPONENTS", &self.config.llvm_components)
|
||||
.env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags);
|
||||
|
||||
if let Some(ref linker) = self.config.linker {
|
||||
cmd.env("RUSTC_LINKER", linker);
|
||||
}
|
||||
|
||||
// We don't want RUSTFLAGS set from the outside to interfere with
|
||||
// compiler flags set in the test cases:
|
||||
cmd.env_remove("RUSTFLAGS");
|
||||
|
@ -2123,7 +2130,8 @@ actual:\n\
|
|||
.env("CXX", &self.config.cxx);
|
||||
} else {
|
||||
cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
|
||||
.env("CXX", format!("{} {}", self.config.cxx, self.config.cflags));
|
||||
.env("CXX", format!("{} {}", self.config.cxx, self.config.cflags))
|
||||
.env("AR", &self.config.ar);
|
||||
|
||||
if self.config.target.contains("windows") {
|
||||
cmd.env("IS_WINDOWS", "1");
|
||||
|
|
Loading…
Add table
Reference in a new issue