From 75d141cf618b648d362fe1131fcf4bf54b848e72 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Fri, 23 Sep 2016 13:05:19 -0400 Subject: [PATCH] Create newtype for platform triple in bootstrap. As I was reading through the bootstrap code, I noticed myself getting lost at times trying to find out what the value of each `&str` is. I also noticed there's quite a few platform-checking conditionals checking the contents of these strings. In an attempt to clarify and cleanup these cases, I created a 'newtype' `Triple` that represents a platform triple and moved the platform-checking logic to methods on the new struct. --- src/bootstrap/cc.rs | 20 +++---- src/bootstrap/check.rs | 32 +++++----- src/bootstrap/compile.rs | 39 ++++++------ src/bootstrap/config.rs | 35 +++++------ src/bootstrap/dist.rs | 21 +++---- src/bootstrap/doc.rs | 15 ++--- src/bootstrap/flags.rs | 22 +++++-- src/bootstrap/lib.rs | 56 ++++++++--------- src/bootstrap/native.rs | 22 +++---- src/bootstrap/sanity.rs | 20 +++---- src/bootstrap/step.rs | 27 ++++----- src/bootstrap/triple.rs | 126 +++++++++++++++++++++++++++++++++++++++ src/bootstrap/util.rs | 13 ++-- 13 files changed, 297 insertions(+), 151 deletions(-) create mode 100644 src/bootstrap/triple.rs diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc.rs index e2bde4a658611..3d725a45a8d20 100644 --- a/src/bootstrap/cc.rs +++ b/src/bootstrap/cc.rs @@ -36,7 +36,7 @@ use std::process::Command; use build_helper::{cc2ar, output}; use gcc; -use Build; +use {Build, Triple}; use config::Target; pub fn find(build: &mut Build) { @@ -45,7 +45,7 @@ pub fn find(build: &mut Build) { for target in build.config.target.iter() { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false) - .target(target).host(&build.config.build); + .target(&target.0).host(&build.config.build.0); let config = build.config.target_config.get(target); if let Some(cc) = config.and_then(|c| c.cc.as_ref()) { @@ -55,19 +55,19 @@ pub fn find(build: &mut Build) { } let compiler = cfg.get_compiler(); - let ar = cc2ar(compiler.path(), target); + let ar = cc2ar(compiler.path(), &target.0); build.verbose(&format!("CC_{} = {:?}", target, compiler.path())); if let Some(ref ar) = ar { build.verbose(&format!("AR_{} = {:?}", target, ar)); } - build.cc.insert(target.to_string(), (compiler, ar)); + build.cc.insert(target.clone(), (compiler, ar)); } // For all host triples we need to find a C++ compiler as well for host in build.config.host.iter() { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false).cpp(true) - .target(host).host(&build.config.build); + .target(&host.0).host(&build.config.build.0); let config = build.config.target_config.get(host); if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { cfg.compiler(cxx); @@ -76,21 +76,21 @@ pub fn find(build: &mut Build) { } let compiler = cfg.get_compiler(); build.verbose(&format!("CXX_{} = {:?}", host, compiler.path())); - build.cxx.insert(host.to_string(), compiler); + build.cxx.insert(host.clone(), compiler); } } fn set_compiler(cfg: &mut gcc::Config, gnu_compiler: &str, - target: &str, + target: &Triple, config: Option<&Target>) { match target { // When compiling for android we may have the NDK configured in the // config.toml in which case we look there. Otherwise the default // compiler already takes into account the triple in question. - t if t.contains("android") => { + t if t.is_android() => { if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) { - let target = target.replace("armv7", "arm"); + let target = target.0.replace("armv7", "arm"); let compiler = format!("{}-{}", target, gnu_compiler); cfg.compiler(ndk.join("bin").join(compiler)); } @@ -98,7 +98,7 @@ fn set_compiler(cfg: &mut gcc::Config, // The default gcc version from OpenBSD may be too old, try using egcc, // which is a gcc version from ports, if this is the case. - t if t.contains("openbsd") => { + t if t.is_openbsd() => { let c = cfg.get_compiler(); if !c.path().ends_with(gnu_compiler) { return diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 2b9d717cbd48d..43c708403a307 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -21,7 +21,7 @@ use std::process::Command; use build_helper::output; -use {Build, Compiler, Mode}; +use {Build, Compiler, Mode, Triple}; use util::{self, dylib_path, dylib_path_var}; const ADB_TEST_DIR: &'static str = "/data/tmp"; @@ -30,7 +30,7 @@ const ADB_TEST_DIR: &'static str = "/data/tmp"; /// /// This tool in `src/tools` will verify the validity of all our links in the /// documentation to ensure we don't have a bunch of dead ones. -pub fn linkcheck(build: &Build, stage: u32, host: &str) { +pub fn linkcheck(build: &Build, stage: u32, host: &Triple) { println!("Linkcheck stage{} ({})", stage, host); let compiler = Compiler::new(stage, host); build.run(build.tool_cmd(&compiler, "linkchecker") @@ -41,7 +41,7 @@ pub fn linkcheck(build: &Build, stage: u32, host: &str) { /// /// This tool in `src/tools` will check out a few Rust projects and run `cargo /// test` to ensure that we don't regress the test suites there. -pub fn cargotest(build: &Build, stage: u32, host: &str) { +pub fn cargotest(build: &Build, stage: u32, host: &Triple) { let ref compiler = Compiler::new(stage, host); // Configure PATH to find the right rustc. NB. we have to use PATH @@ -69,14 +69,14 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) { /// This tool in `src/tools` checks up on various bits and pieces of style and /// otherwise just implements a few lint-like checks that are specific to the /// compiler itself. -pub fn tidy(build: &Build, stage: u32, host: &str) { +pub fn tidy(build: &Build, stage: u32, host: &Triple) { println!("tidy check stage{} ({})", stage, host); let compiler = Compiler::new(stage, host); build.run(build.tool_cmd(&compiler, "tidy") .arg(build.src.join("src"))); } -fn testdir(build: &Build, host: &str) -> PathBuf { +fn testdir(build: &Build, host: &Triple) -> PathBuf { build.out.join(host).join("test") } @@ -87,7 +87,7 @@ fn testdir(build: &Build, host: &str) -> PathBuf { /// "run-pass" or `suite` can be something like `debuginfo`. pub fn compiletest(build: &Build, compiler: &Compiler, - target: &str, + target: &Triple, mode: &str, suite: &str) { println!("Check compiletest {} ({} -> {})", suite, compiler.host, target); @@ -130,7 +130,7 @@ pub fn compiletest(build: &Build, let python_default = "python"; cmd.arg("--docck-python").arg(python_default); - if build.config.build.ends_with("apple-darwin") { + if build.config.build.is_apple_darwin() { // Force /usr/bin/python on OSX for LLDB tests because we're loading the // LLDB plugin's compiled module which only works with the system python // (namely not Homebrew-installed python) @@ -178,7 +178,7 @@ pub fn compiletest(build: &Build, // Running a C compiler on MSVC requires a few env vars to be set, to be // sure to set them here. - if target.contains("msvc") { + if target.is_msvc() { for &(ref k, ref v) in build.cc[target].0.env() { if k != "PATH" { cmd.env(k, v); @@ -189,7 +189,7 @@ pub fn compiletest(build: &Build, cmd.arg("--adb-path").arg("adb"); cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); - if target.contains("android") { + if target.is_android() { // Assume that cc for this target comes from the android sysroot cmd.arg("--android-cross-path") .arg(build.cc(target).parent().unwrap().parent().unwrap()); @@ -262,7 +262,7 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { /// arguments, and those arguments are discovered from `Cargo.lock`. pub fn krate(build: &Build, compiler: &Compiler, - target: &str, + target: &Triple, mode: Mode) { let (name, path, features) = match mode { Mode::Libstd => ("libstd", "src/rustc/std_shim", build.std_features()), @@ -320,7 +320,7 @@ pub fn krate(build: &Build, dylib_path.insert(0, build.sysroot_libdir(compiler, target)); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - if target.contains("android") { + if target.is_android() { build.run(cargo.arg("--no-run")); krate_android(build, compiler, target, mode); } else { @@ -331,7 +331,7 @@ pub fn krate(build: &Build, fn krate_android(build: &Build, compiler: &Compiler, - target: &str, + target: &Triple, mode: Mode) { let mut tests = Vec::new(); let out_dir = build.cargo_out(compiler, mode, target); @@ -372,7 +372,7 @@ fn krate_android(build: &Build, } fn find_tests(dir: &Path, - target: &str, + target: &Triple, dst: &mut Vec) { for e in t!(dir.read_dir()).map(|e| t!(e)) { let file_type = t!(e.file_type()); @@ -380,8 +380,8 @@ fn find_tests(dir: &Path, continue } let filename = e.file_name().into_string().unwrap(); - if (target.contains("windows") && filename.ends_with(".exe")) || - (!target.contains("windows") && !filename.contains(".")) { + if (target.is_windows() && filename.ends_with(".exe")) || + (!target.is_windows() && !filename.contains(".")) { dst.push(e.path()); } } @@ -389,7 +389,7 @@ fn find_tests(dir: &Path, pub fn android_copy_libs(build: &Build, compiler: &Compiler, - target: &str) { + target: &Triple) { println!("Android copy libs to emulator ({})", target); build.run(Command::new("adb").arg("remount")); build.run(Command::new("adb").args(&["shell", "rm", "-r", ADB_TEST_DIR])); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9de438cfa7d50..71fb7f061746a 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -26,14 +26,14 @@ use build_helper::output; use filetime::FileTime; use util::{exe, staticlib, libdir, mtime, is_dylib, copy}; -use {Build, Compiler, Mode}; +use {Build, Compiler, Mode, Triple}; /// Build the standard library. /// /// This will build the standard library for a particular stage of the build /// using the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. -pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { +pub fn std<'a>(build: &'a Build, target: &Triple, compiler: &Compiler<'a>) { println!("Building stage{} std artifacts ({} -> {})", compiler.stage, compiler.host, target); @@ -71,7 +71,7 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { cargo.env("JEMALLOC_OVERRIDE", jemalloc); } } - if target.contains("musl") { + if target.is_musl() { if let Some(p) = build.musl_root(target) { cargo.env("MUSL_ROOT", p); } @@ -87,9 +87,9 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { /// Links those artifacts generated in the given `stage` for `target` produced /// by `compiler` into `host`'s sysroot. pub fn std_link(build: &Build, - target: &str, + target: &Triple, compiler: &Compiler, - host: &str) { + host: &Triple) { let target_compiler = Compiler::new(compiler.stage, host); let libdir = build.sysroot_libdir(&target_compiler, target); let out_dir = build.cargo_out(compiler, Mode::Libstd, target); @@ -103,7 +103,7 @@ pub fn std_link(build: &Build, } add_to_sysroot(&out_dir, &libdir); - if target.contains("musl") && !target.contains("mips") { + if target.is_musl() && !target.is_mips() { copy_musl_third_party_objects(build, &libdir); } } @@ -123,8 +123,8 @@ fn copy_musl_third_party_objects(build: &Build, into: &Path) { /// They don't require any library support as they're just plain old object /// files, so we just use the nightly snapshot compiler to always build them (as /// no other compilers are guaranteed to be available). -fn build_startup_objects(build: &Build, target: &str, into: &Path) { - if !target.contains("pc-windows-gnu") { +fn build_startup_objects(build: &Build, target: &Triple, into: &Path) { + if !target.is_pc_windows_gnu() { return } let compiler = Compiler::new(0, &build.config.build); @@ -150,7 +150,8 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) { /// This will build libtest and supporting libraries for a particular stage of /// the build using the `compiler` targeting the `target` architecture. The /// artifacts created will also be linked into the sysroot directory. -pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { +pub fn test<'a>(build: &'a Build, target: &Triple, + compiler: &Compiler<'a>) { println!("Building stage{} test artifacts ({} -> {})", compiler.stage, compiler.host, target); let out_dir = build.cargo_out(compiler, Mode::Libtest, target); @@ -168,9 +169,9 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { /// Links those artifacts generated in the given `stage` for `target` produced /// by `compiler` into `host`'s sysroot. pub fn test_link(build: &Build, - target: &str, + target: &Triple, compiler: &Compiler, - host: &str) { + host: &Triple) { let target_compiler = Compiler::new(compiler.stage, host); let libdir = build.sysroot_libdir(&target_compiler, target); let out_dir = build.cargo_out(compiler, Mode::Libtest, target); @@ -182,7 +183,7 @@ pub fn test_link(build: &Build, /// This will build the compiler for a particular stage of the build using /// the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. -pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { +pub fn rustc<'a>(build: &'a Build, target: &Triple, compiler: &Compiler<'a>) { println!("Building stage{} compiler artifacts ({} -> {})", compiler.stage, compiler.host, target); @@ -241,9 +242,9 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { /// Links those artifacts generated in the given `stage` for `target` produced /// by `compiler` into `host`'s sysroot. pub fn rustc_link(build: &Build, - target: &str, + target: &Triple, compiler: &Compiler, - host: &str) { + host: &Triple) { let target_compiler = Compiler::new(compiler.stage, host); let libdir = build.sysroot_libdir(&target_compiler, target); let out_dir = build.cargo_out(compiler, Mode::Librustc, target); @@ -252,13 +253,15 @@ pub fn rustc_link(build: &Build, /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. -fn libstd_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { +fn libstd_stamp(build: &Build, compiler: &Compiler, + target: &Triple) -> PathBuf { build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp") } /// Cargo's output path for libtest in a given stage, compiled by a particular /// compiler for the specified target. -fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { +fn libtest_stamp(build: &Build, compiler: &Compiler, + target: &Triple) -> PathBuf { build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp") } @@ -273,7 +276,7 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf { /// This will assemble a compiler in `build/$host/stage$stage`. The compiler /// must have been previously produced by the `stage - 1` build.config.build /// compiler. -pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { +pub fn assemble_rustc(build: &Build, stage: u32, host: &Triple) { assert!(stage > 0, "the stage0 compiler isn't assembled, it's downloaded"); // The compiler that we're assembling let target_compiler = Compiler::new(stage, host); @@ -360,7 +363,7 @@ fn add_to_sysroot(out_dir: &Path, sysroot_dst: &Path) { /// /// This will build the specified tool with the specified `host` compiler in /// `stage` into the normal cargo output directory. -pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) { +pub fn tool(build: &Build, stage: u32, host: &Triple, tool: &str) { println!("Building stage{} tool {} ({})", stage, tool, host); let compiler = Compiler::new(stage, host); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0f69bcfbb649d..8a082a821098b 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -23,6 +23,7 @@ use std::process; use num_cpus; use rustc_serialize::Decodable; use toml::{Parser, Decoder, Value}; +use Triple; /// Global configuration for the entire build and/or bootstrap. /// @@ -43,7 +44,7 @@ pub struct Config { pub submodules: bool, pub compiler_docs: bool, pub docs: bool, - pub target_config: HashMap, + pub target_config: HashMap, // llvm codegen options pub llvm_assertions: bool, @@ -62,9 +63,9 @@ pub struct Config { pub rust_optimize_tests: bool, pub rust_debuginfo_tests: bool, - pub build: String, - pub host: Vec, - pub target: Vec, + pub build: Triple, + pub host: Vec, + pub target: Vec, pub rustc: Option, pub cargo: Option, pub local_rebuild: bool, @@ -104,15 +105,15 @@ struct TomlConfig { build: Option, llvm: Option, rust: Option, - target: Option>, + target: Option>, } /// TOML representation of various global build decisions. #[derive(RustcDecodable, Default, Clone)] struct Build { - build: Option, - host: Vec, - target: Vec, + build: Option, + host: Vec, + target: Vec, cargo: Option, rustc: Option, compiler_docs: Option, @@ -172,7 +173,7 @@ impl Config { config.docs = true; config.rust_rpath = true; config.rust_codegen_units = 1; - config.build = build.to_string(); + config.build = build.into(); config.channel = "dev".to_string(); config.codegen_tests = true; @@ -205,7 +206,7 @@ impl Config { }).unwrap_or_else(|| TomlConfig::default()); let build = toml.build.clone().unwrap_or(Build::default()); - set(&mut config.build, build.build.clone()); + set(&mut config.build, build.build); config.host.push(config.build.clone()); for host in build.host.iter() { if !config.host.contains(host) { @@ -333,13 +334,13 @@ impl Config { } match key { - "CFG_BUILD" => self.build = value.to_string(), + "CFG_BUILD" => self.build = value.into(), "CFG_HOST" => { - self.host = value.split(" ").map(|s| s.to_string()) + self.host = value.split(" ").map(|s| s.into()) .collect(); } "CFG_TARGET" => { - self.target = value.split(" ").map(|s| s.to_string()) + self.target = value.split(" ").map(|s| s.into()) .collect(); } "CFG_MUSL_ROOT" if value.len() > 0 => { @@ -369,25 +370,25 @@ impl Config { target.jemalloc = Some(PathBuf::from(value)); } "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { - let target = "arm-linux-androideabi".to_string(); + let target = "arm-linux-androideabi".into(); let target = self.target_config.entry(target) .or_insert(Target::default()); target.ndk = Some(PathBuf::from(value)); } "CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { - let target = "armv7-linux-androideabi".to_string(); + let target = "armv7-linux-androideabi".into(); let target = self.target_config.entry(target) .or_insert(Target::default()); target.ndk = Some(PathBuf::from(value)); } "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = "i686-linux-android".to_string(); + let target = "i686-linux-android".into(); let target = self.target_config.entry(target) .or_insert(Target::default()); target.ndk = Some(PathBuf::from(value)); } "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = "aarch64-linux-android".to_string(); + let target = "aarch64-linux-android".into(); let target = self.target_config.entry(target) .or_insert(Target::default()); target.ndk = Some(PathBuf::from(value)); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 31b7db168b48f..56986e119f47c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -23,7 +23,7 @@ use std::io::Write; use std::path::{PathBuf, Path}; use std::process::Command; -use {Build, Compiler}; +use {Build, Compiler, Triple}; use util::{cp_r, libdir, is_dylib, cp_filtered, copy}; use regex::{RegexSet, quote}; @@ -47,7 +47,7 @@ fn tmpdir(build: &Build) -> PathBuf { /// Builds the `rust-docs` installer component. /// /// Slurps up documentation from the `stage`'s `host`. -pub fn docs(build: &Build, stage: u32, host: &str) { +pub fn docs(build: &Build, stage: u32, host: &Triple) { println!("Dist docs stage{} ({})", stage, host); let name = format!("rust-docs-{}", package_vers(build)); let image = tmpdir(build).join(format!("{}-{}-image", name, name)); @@ -75,7 +75,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { // As part of this step, *also* copy the docs directory to a directory which // buildbot typically uploads. - if host == build.config.build { + if host == &build.config.build { let dst = distdir(build).join("doc").join(&build.package_vers); t!(fs::create_dir_all(&dst)); cp_r(&src, &dst); @@ -88,7 +88,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { /// without any extra installed software (e.g. we bundle gcc, libraries, etc). /// Currently just shells out to a python script, but that should be rewritten /// in Rust. -pub fn mingw(build: &Build, host: &str) { +pub fn mingw(build: &Build, host: &Triple) { println!("Dist mingw ({})", host); let name = format!("rust-mingw-{}", package_vers(build)); let image = tmpdir(build).join(format!("{}-{}-image", name, host)); @@ -123,7 +123,7 @@ pub fn mingw(build: &Build, host: &str) { } /// Creates the `rustc` installer component. -pub fn rustc(build: &Build, stage: u32, host: &str) { +pub fn rustc(build: &Build, stage: u32, host: &Triple) { println!("Dist rustc stage{} ({})", stage, host); let name = format!("rustc-{}", package_vers(build)); let image = tmpdir(build).join(format!("{}-{}-image", name, host)); @@ -159,7 +159,7 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { // licenses, so to be safe we just include it here in all MinGW packages. // // FIXME: this script should be rewritten into Rust - if host.contains("pc-windows-gnu") { + if host.is_pc_windows_gnu() { let mut cmd = Command::new("python"); cmd.arg(build.src.join("src/etc/make-win-dist.py")) .arg(&image) @@ -189,7 +189,8 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { t!(fs::remove_dir_all(&image)); t!(fs::remove_dir_all(&overlay)); - fn prepare_image(build: &Build, stage: u32, host: &str, image: &Path) { + fn prepare_image(build: &Build, stage: u32, host: &Triple, + image: &Path) { let src = build.sysroot(&Compiler::new(stage, host)); let libdir = libdir(host); @@ -230,13 +231,13 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { /// Copies debugger scripts for `host` into the `sysroot` specified. pub fn debugger_scripts(build: &Build, sysroot: &Path, - host: &str) { + host: &Triple) { let cp_debugger_script = |file: &str| { let dst = sysroot.join("lib/rustlib/etc"); t!(fs::create_dir_all(&dst)); install(&build.src.join("src/etc/").join(file), &dst, 0o644); }; - if host.contains("windows-msvc") { + if host.is_windows_msvc() { // no debugger scripts } else { cp_debugger_script("debugger_pretty_printers_common.py"); @@ -258,7 +259,7 @@ pub fn debugger_scripts(build: &Build, /// Creates the `rust-std` installer component as compiled by `compiler` for the /// target `target`. -pub fn std(build: &Build, compiler: &Compiler, target: &str) { +pub fn std(build: &Build, compiler: &Compiler, target: &Triple) { println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host, target); let name = format!("rust-std-{}", package_vers(build)); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index c2636384dbb2b..b3c2f9d862d4e 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -22,7 +22,7 @@ use std::io::prelude::*; use std::path::Path; use std::process::Command; -use {Build, Compiler, Mode}; +use {Build, Compiler, Mode, Triple}; use util::{up_to_date, cp_r}; /// Invoke `rustbook` as compiled in `stage` for `target` for the doc book @@ -30,7 +30,8 @@ use util::{up_to_date, cp_r}; /// /// This will not actually generate any documentation if the documentation has /// already been generated. -pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str, out: &Path) { +pub fn rustbook(build: &Build, stage: u32, target: &Triple, name: &str, + out: &Path) { t!(fs::create_dir_all(out)); let out = out.join(name); @@ -57,7 +58,7 @@ pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str, out: &Path) /// `STAMP` alongw ith providing the various header/footer HTML we've cutomized. /// /// In the end, this is just a glorified wrapper around rustdoc! -pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn standalone(build: &Build, stage: u32, target: &Triple, out: &Path) { println!("Documenting stage{} standalone ({})", stage, target); t!(fs::create_dir_all(out)); @@ -131,7 +132,7 @@ pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) { /// /// This will generate all documentation for the standard library and its /// dependencies. This is largely just a wrapper around `cargo doc`. -pub fn std(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn std(build: &Build, stage: u32, target: &Triple, out: &Path) { println!("Documenting stage{} std ({})", stage, target); t!(fs::create_dir_all(out)); let compiler = Compiler::new(stage, &build.config.build); @@ -153,7 +154,7 @@ pub fn std(build: &Build, stage: u32, target: &str, out: &Path) { /// /// This will generate all documentation for libtest and its dependencies. This /// is largely just a wrapper around `cargo doc`. -pub fn test(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn test(build: &Build, stage: u32, target: &Triple, out: &Path) { println!("Documenting stage{} test ({})", stage, target); t!(fs::create_dir_all(out)); let compiler = Compiler::new(stage, &build.config.build); @@ -174,7 +175,7 @@ pub fn test(build: &Build, stage: u32, target: &str, out: &Path) { /// /// This will generate all documentation for the compiler libraries and their /// dependencies. This is largely just a wrapper around `cargo doc`. -pub fn rustc(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn rustc(build: &Build, stage: u32, target: &Triple, out: &Path) { println!("Documenting stage{} compiler ({})", stage, target); t!(fs::create_dir_all(out)); let compiler = Compiler::new(stage, &build.config.build); @@ -194,7 +195,7 @@ pub fn rustc(build: &Build, stage: u32, target: &str, out: &Path) { /// Generates the HTML rendered error-index by running the /// `error_index_generator` tool. -pub fn error_index(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn error_index(build: &Build, stage: u32, target: &Triple, out: &Path) { println!("Documenting stage{} error index ({})", stage, target); t!(fs::create_dir_all(out)); let compiler = Compiler::new(stage, &build.config.build); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index d925997f36c21..2673e729b2c07 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -20,6 +20,8 @@ use std::slice; use getopts::Options; +use Triple; + /// Deserialized version of all flags for this compile. pub struct Flags { pub verbose: bool, @@ -36,7 +38,7 @@ pub struct Flags { } pub struct Filter { - values: Vec, + values: Vec, } impl Flags { @@ -81,8 +83,18 @@ impl Flags { clean: m.opt_present("clean"), stage: m.opt_str("stage").map(|j| j.parse().unwrap()), build: m.opt_str("build").unwrap(), - host: Filter { values: m.opt_strs("host") }, - target: Filter { values: m.opt_strs("target") }, + host: Filter { + values: m.opt_strs("host") + .into_iter() + .map(|s| s.into()) + .collect() + }, + target: Filter { + values: m.opt_strs("target") + .into_iter() + .map(|s| s.into()) + .collect() + }, step: m.opt_strs("step"), config: cfg_file, src: m.opt_str("src").map(PathBuf::from), @@ -93,11 +105,11 @@ impl Flags { } impl Filter { - pub fn contains(&self, name: &str) -> bool { + pub fn contains(&self, name: &Triple) -> bool { self.values.len() == 0 || self.values.iter().any(|s| s == name) } - pub fn iter(&self) -> slice::Iter { + pub fn iter(&self) -> slice::Iter { self.values.iter() } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index a5146c846ce28..e1a9d19cbea7d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -65,6 +65,7 @@ mod flags; mod native; mod sanity; mod step; +mod triple; pub mod util; #[cfg(windows)] @@ -77,6 +78,7 @@ mod job { pub use config::Config; pub use flags::Flags; +pub use triple::Triple; /// A structure representing a Rust compiler. /// @@ -86,7 +88,7 @@ pub use flags::Flags; #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] pub struct Compiler<'a> { stage: u32, - host: &'a str, + host: &'a Triple, } /// Global configuration for the build system. @@ -128,8 +130,8 @@ pub struct Build { lldb_python_dir: Option, // Runtime state filled in later on - cc: HashMap)>, - cxx: HashMap, + cc: HashMap)>, + cxx: HashMap, } /// The various "modes" of invoking Cargo. @@ -402,9 +404,9 @@ impl Build { "ui", "ui"); } CheckDebuginfo { compiler } => { - if target.target.contains("msvc") { + if target.target.is_msvc() { // nothing to do - } else if target.target.contains("apple") { + } else if target.target.is_apple() { check::compiletest(self, &compiler, target.target, "debuginfo-lldb", "debuginfo"); } else { @@ -596,7 +598,7 @@ impl Build { fn cargo(&self, compiler: &Compiler, mode: Mode, - target: &str, + target: &Triple, cmd: &str) -> Command { let mut cargo = Command::new(&self.cargo); let out_dir = self.stage_out(compiler, mode); @@ -646,7 +648,7 @@ impl Build { // the build. // // FIXME: the guard against msvc shouldn't need to be here - if !target.contains("msvc") { + if !target.is_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(" ")); @@ -654,7 +656,7 @@ impl Build { // If we're building for OSX, inform the compiler and the linker that // we want to build a compiler runnable on 10.7 - if target.contains("apple-darwin") { + if target.is_apple_darwin() { cargo.env("MACOSX_DEPLOYMENT_TARGET", "10.7"); } @@ -757,7 +759,7 @@ impl Build { /// Returns the libdir where the standard library and other artifacts are /// found for a compiler's sysroot. - fn sysroot_libdir(&self, compiler: &Compiler, target: &str) -> PathBuf { + fn sysroot_libdir(&self, compiler: &Compiler, target: &Triple) -> PathBuf { self.sysroot(compiler).join("lib").join("rustlib") .join(target).join("lib") } @@ -783,7 +785,7 @@ impl Build { fn cargo_out(&self, compiler: &Compiler, mode: Mode, - target: &str) -> PathBuf { + target: &Triple) -> PathBuf { self.stage_out(compiler, mode).join(target).join(self.cargo_dir()) } @@ -791,14 +793,14 @@ impl Build { /// /// Note that if LLVM is configured externally then the directory returned /// will likely be empty. - fn llvm_out(&self, target: &str) -> PathBuf { + fn llvm_out(&self, target: &Triple) -> PathBuf { self.out.join(target).join("llvm") } /// Returns true if no custom `llvm-config` is set for the specified target. /// /// If no custom `llvm-config` was specified then Rust's llvm will be used. - fn is_rust_llvm(&self, target: &str) -> bool { + fn is_rust_llvm(&self, target: &Triple) -> bool { match self.config.target_config.get(target) { Some(ref c) => c.llvm_config.is_none(), None => true @@ -809,7 +811,7 @@ impl Build { /// /// If a custom `llvm-config` was specified for target then that's returned /// instead. - fn llvm_config(&self, target: &str) -> PathBuf { + fn llvm_config(&self, target: &Triple) -> PathBuf { let target_config = self.config.target_config.get(target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { s.clone() @@ -820,14 +822,14 @@ impl Build { } /// Returns the path to `FileCheck` binary for the specified target - fn llvm_filecheck(&self, target: &str) -> PathBuf { + fn llvm_filecheck(&self, target: &Triple) -> PathBuf { let target_config = self.config.target_config.get(target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { s.parent().unwrap().join(exe("FileCheck", target)) } else { let base = self.llvm_out(&self.config.build).join("build"); let exe = exe("FileCheck", target); - if self.config.build.contains("msvc") { + if self.config.build.is_msvc() { base.join("Release/bin").join(exe) } else { base.join("bin").join(exe) @@ -837,7 +839,7 @@ impl Build { /// Root output directory for rust_test_helpers library compiled for /// `target` - fn test_helpers_out(&self, target: &str) -> PathBuf { + fn test_helpers_out(&self, target: &Triple) -> PathBuf { self.out.join(target).join("rust-test-helpers") } @@ -906,13 +908,13 @@ impl Build { } /// Returns the path to the C compiler for the target specified. - fn cc(&self, target: &str) -> &Path { + fn cc(&self, target: &Triple) -> &Path { self.cc[target].0.path() } /// Returns a list of flags to pass to the C compiler for the target /// specified. - fn cflags(&self, target: &str) -> Vec { + fn cflags(&self, target: &Triple) -> Vec { // Filter out -O and /O (the optimization flags) that we picked up from // gcc-rs because the build scripts will determine that for themselves. let mut base = self.cc[target].0.args().iter() @@ -924,14 +926,14 @@ impl Build { // indicating that we want libc++ (more filled out than libstdc++) and // we want to compile for 10.7. This way we can ensure that // LLVM/jemalloc/etc are all properly compiled. - if target.contains("apple-darwin") { + if target.is_apple_darwin() { base.push("-stdlib=libc++".into()); base.push("-mmacosx-version-min=10.7".into()); } // This is a hack, because newer binutils broke things on some vms/distros // (i.e., linking against unknown relocs disabled by the following flag) // See: https://github.com/rust-lang/rust/issues/34978 - match target { + match &target.0 as &str { "i586-unknown-linux-gnu" | "i686-unknown-linux-musl" | "x86_64-unknown-linux-musl" => { @@ -943,13 +945,13 @@ impl Build { } /// Returns the path to the `ar` archive utility for the target specified. - fn ar(&self, target: &str) -> Option<&Path> { + fn ar(&self, target: &Triple) -> Option<&Path> { self.cc[target].1.as_ref().map(|p| &**p) } /// Returns the path to the C++ compiler for the target specified, may panic /// if no C++ compiler was configured for the target. - fn cxx(&self, target: &str) -> &Path { + fn cxx(&self, target: &Triple) -> &Path { match self.cxx.get(target) { Some(p) => p.path(), None => panic!("\n\ntarget `{}` is not configured as a host, @@ -958,7 +960,7 @@ impl Build { } /// Returns flags to pass to the compiler to generate code for `target`. - fn rustc_flags(&self, target: &str) -> Vec { + fn rustc_flags(&self, target: &Triple) -> Vec { // New flags should be added here with great caution! // // It's quite unfortunate to **require** flags to generate code for a @@ -967,14 +969,14 @@ impl Build { // than an entry here. let mut base = Vec::new(); - if target != self.config.build && !target.contains("msvc") { + if target != &self.config.build && !target.is_msvc() { base.push(format!("-Clinker={}", self.cc(target).display())); } return base } /// Returns the "musl root" for this `target`, if defined - fn musl_root(&self, target: &str) -> Option<&Path> { + fn musl_root(&self, target: &Triple) -> Option<&Path> { self.config.target_config[target].musl_root.as_ref() .or(self.config.musl_root.as_ref()) .map(|p| &**p) @@ -983,12 +985,12 @@ impl Build { impl<'a> Compiler<'a> { /// Creates a new complier for the specified stage/host - fn new(stage: u32, host: &'a str) -> Compiler<'a> { + fn new(stage: u32, host: &'a Triple) -> Compiler<'a> { Compiler { stage: stage, host: host } } /// Returns whether this is a snapshot compiler for `build`'s configuration fn is_snapshot(&self, build: &Build) -> bool { - self.stage == 0 && self.host == build.config.build + self.stage == 0 && self.host == &build.config.build } } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index df6408e5fe1c8..faf656df9098d 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -26,11 +26,11 @@ use build_helper::output; use cmake; use gcc; -use Build; +use {Build, Triple}; use util::up_to_date; /// Compile LLVM for `target`. -pub fn llvm(build: &Build, target: &str) { +pub fn llvm(build: &Build, target: &Triple) { // If we're using a custom LLVM bail out here, but we can only use a // custom LLVM for the build triple. if let Some(config) = build.config.target_config.get(target) { @@ -60,8 +60,8 @@ pub fn llvm(build: &Build, target: &str) { if build.config.ninja { cfg.generator("Ninja"); } - cfg.target(target) - .host(&build.config.build) + cfg.target(&target.0) + .host(&build.config.build.0) .out_dir(&dst) .profile(if build.config.llvm_optimize {"Release"} else {"Debug"}) .define("LLVM_ENABLE_ASSERTIONS", assertions) @@ -75,24 +75,24 @@ pub fn llvm(build: &Build, target: &str) { .define("LLVM_ENABLE_LIBEDIT", "OFF") .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string()); - if target.starts_with("i686") { + if target.is_i686() { cfg.define("LLVM_BUILD_32_BITS", "ON"); } // http://llvm.org/docs/HowToCrossCompileLLVM.html - if target != build.config.build { + if target != &build.config.build { // FIXME: if the llvm root for the build triple is overridden then we // should use llvm-tblgen from there, also should verify that it // actually exists most of the time in normal installs of LLVM. let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen"); cfg.define("CMAKE_CROSSCOMPILING", "True") - .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) + .define("LLVM_TARGET_ARCH", target.arch()) .define("LLVM_TABLEGEN", &host) .define("LLVM_DEFAULT_TARGET_TRIPLE", target); } // MSVC handles compiler business itself - if !target.contains("msvc") { + if !target.is_msvc() { if build.config.ccache { cfg.define("CMAKE_C_COMPILER", "ccache") .define("CMAKE_C_COMPILER_ARG1", build.cc(target)) @@ -133,7 +133,7 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { /// Compiles the `rust_test_helpers.c` library which we used in various /// `run-pass` test suites for ABI testing. -pub fn test_helpers(build: &Build, target: &str) { +pub fn test_helpers(build: &Build, target: &Triple) { let dst = build.test_helpers_out(target); let src = build.src.join("src/rt/rust_test_helpers.c"); if up_to_date(&src, &dst.join("librust_test_helpers.a")) { @@ -145,8 +145,8 @@ pub fn test_helpers(build: &Build, target: &str) { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false) .out_dir(&dst) - .target(target) - .host(&build.config.build) + .target(&target.0) + .host(&build.config.build.0) .opt_level(0) .debug(false) .file(build.src.join("src/rt/rust_test_helpers.c")) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 05c35543e3e5b..78072e24f974e 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -101,22 +101,22 @@ pub fn check(build: &mut Build) { for target in build.config.target.iter() { // Either can't build or don't want to run jemalloc on these targets - if target.contains("rumprun") || - target.contains("bitrig") || - target.contains("openbsd") || - target.contains("msvc") || - target.contains("emscripten") { + if target.is_rumprun() || + target.is_bitrig() || + target.is_openbsd() || + target.is_msvc() || + target.is_emscripten() { build.config.use_jemalloc = false; } // Can't compile for iOS unless we're on OSX - if target.contains("apple-ios") && - !build.config.build.contains("apple-darwin") { + if target.is_apple_ios() && + !build.config.build.is_apple_darwin() { panic!("the iOS target is only supported on OSX"); } // Make sure musl-root is valid if specified - if target.contains("musl") && !target.contains("mips") { + if target.is_musl() && !target.is_mips() { match build.musl_root(target) { Some(root) => { if fs::metadata(root.join("lib/libc.a")).is_err() { @@ -136,7 +136,7 @@ pub fn check(build: &mut Build) { } } - if target.contains("msvc") { + if target.is_msvc() { // There are three builds of cmake on windows: MSVC, MinGW, and // Cygwin. The Cygwin build does not have generators for Visual // Studio, so detect that here and error. @@ -157,7 +157,7 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } } - if target.contains("arm-linux-android") { + if target.is_arm_linux_android() { need_cmd("adb".as_ref()); } } diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 5f391b70fbe88..2fc87bdbb8680 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -22,12 +22,12 @@ use std::collections::HashSet; -use {Build, Compiler}; +use {Build, Compiler, Triple}; #[derive(Hash, Eq, PartialEq, Clone, Debug)] pub struct Step<'a> { pub src: Source<'a>, - pub target: &'a str, + pub target: &'a Triple, } /// Macro used to iterate over all targets that are recognized by the build @@ -56,15 +56,15 @@ macro_rules! targets { // host's directory also provided. (libstd_link, LibstdLink { compiler: Compiler<'a>, - host: &'a str + host: &'a Triple }), (libtest_link, LibtestLink { compiler: Compiler<'a>, - host: &'a str + host: &'a Triple }), (librustc_link, LibrustcLink { compiler: Compiler<'a>, - host: &'a str + host: &'a Triple }), // Various tools that we can build as part of the build. @@ -204,8 +204,7 @@ fn top_level(build: &Build) -> Vec { }; let target = Step { src: Source::Llvm { _dummy: () }, - target: build.flags.target.iter().next().map(|x| &x[..]) - .unwrap_or(host.target) + target: build.flags.target.iter().next().unwrap_or(host.target) }; // First, try to find steps on the command line. @@ -225,7 +224,7 @@ fn top_level(build: &Build) -> Vec { continue } let host = t.target(host); - if host.target == build.config.build { + if host.target == &build.config.build { targets.push(host.librustc(host.compiler(stage))); } else { targets.push(host.librustc_link(t.compiler(stage), host.target)); @@ -235,7 +234,7 @@ fn top_level(build: &Build) -> Vec { continue } - if host.target == build.config.build { + if host.target == &build.config.build { targets.push(host.target(target) .libtest(host.compiler(stage))); } else { @@ -259,7 +258,7 @@ fn add_steps<'a>(build: &'a Build, stage: u32, compiler: Compiler<'a>, _dummy: (), - host: &'a str, + host: &'a Triple, } for step in build.flags.step.iter() { @@ -305,7 +304,7 @@ impl<'a> Step<'a> { Compiler::new(stage, self.target) } - fn target(&self, target: &'a str) -> Step<'a> { + fn target(&self, target: &'a Triple) -> Step<'a> { Step { target: target, src: self.src.clone() } } @@ -421,7 +420,7 @@ impl<'a> Step<'a> { // If we're testing the build triple, then we know we can // actually run binaries and such, so we run all possible tests // that we know about. - if self.target == build.config.build { + if self.target == &build.config.build { base.extend(vec![ // docs-related self.check_docs(compiler), @@ -493,7 +492,7 @@ impl<'a> Step<'a> { self.target(compiler.host).tool_compiletest(compiler.stage), self.test_helpers(()), ]; - if self.target.contains("android") { + if self.target.is_android() { base.push(self.android_copy_libs(compiler)); } base @@ -572,7 +571,7 @@ impl<'a> Step<'a> { let host = self.target(host); base.push(host.dist_src(())); base.push(host.dist_rustc(stage)); - if host.target.contains("windows-gnu") { + if host.target.is_windows_gnu() { base.push(host.dist_mingw(())); } diff --git a/src/bootstrap/triple.rs b/src/bootstrap/triple.rs new file mode 100644 index 0000000000000..006fdc93fc895 --- /dev/null +++ b/src/bootstrap/triple.rs @@ -0,0 +1,126 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::convert; +use std::ffi; +use std::fmt; +use std::path; + +/// Platform represented by a hyphen-delimited string. Does not +/// necessarily consist of three items. e.g.: +/// +/// * `i686-apple-darwin` +/// * `powerpc-unknown-linux-gnu` +#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, RustcDecodable)] +pub struct Triple(pub String); + +impl Triple { + pub fn arch(&self) -> &str { + self.0.split('-').next().unwrap() + } + + pub fn is_msvc(&self) -> bool { + self.0.contains("msvc") + } + + pub fn is_windows(&self) -> bool { + self.0.contains("windows") + } + + pub fn is_windows_msvc(&self) -> bool { + self.0.contains("windows-msvc") + } + + pub fn is_apple(&self) -> bool { + self.0.contains("apple") + } + + pub fn is_apple_darwin(&self) -> bool { + self.0.contains("apple-darwin") + } + + pub fn is_android(&self) -> bool { + self.0.contains("android") + } + + pub fn is_rumprun(&self) -> bool { + self.0.contains("rumprun") + } + + pub fn is_bitrig(&self) -> bool { + self.0.contains("bitrig") + } + + pub fn is_openbsd(&self) -> bool { + self.0.contains("openbsd") + } + + pub fn is_emscripten(&self) -> bool { + self.0.contains("emscripten") + } + + pub fn is_arm_linux_android(&self) -> bool { + self.0.contains("arm-linux-android") + } + + pub fn is_pc_windows_gnu(&self) -> bool { + self.0.contains("pc-windows-gnu") + } + + pub fn is_windows_gnu(&self) -> bool { + self.0.contains("windows-gnu") + } + + pub fn is_mips(&self) -> bool { + self.0.contains("mips") + } + + pub fn is_musl(&self) -> bool { + self.0.contains("musl") + } + + pub fn is_apple_ios(&self) -> bool { + self.0.contains("musl") + } + + pub fn is_i686(&self) -> bool { + self.0.starts_with("i686") + } +} + +impl fmt::Display for Triple { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl convert::AsRef for Triple { + fn as_ref(&self) -> &path::Path { + self.0.as_ref() + } +} + +impl convert::AsRef for Triple { + fn as_ref(&self) -> &ffi::OsStr { + self.0.as_ref() + } +} + +impl<'a> convert::From for Triple { + fn from(s: String) -> Triple { + Triple(s) + } +} + +impl<'a> convert::From<&'a str> for Triple { + fn from(s: &'a str) -> Triple { + Triple(s.into()) + } +} diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 6c0a32a54d919..9866e3e91c3d8 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -20,10 +20,11 @@ use std::path::{Path, PathBuf}; use std::process::Command; use filetime::FileTime; +use Triple; /// Returns the `name` as the filename of a static library for `target`. -pub fn staticlib(name: &str, target: &str) -> String { - if target.contains("windows") { +pub fn staticlib(name: &str, target: &Triple) -> String { + if target.is_windows() { format!("{}.lib", name) } else { format!("lib{}.a", name) @@ -98,8 +99,8 @@ pub fn cp_filtered bool>(src: &Path, dst: &Path, filter: &F) { /// Given an executable called `name`, return the filename for the /// executable for a particular target. -pub fn exe(name: &str, target: &str) -> String { - if target.contains("windows") { +pub fn exe(name: &str, target: &Triple) -> String { + if target.is_windows() { format!("{}.exe", name) } else { name.to_string() @@ -113,8 +114,8 @@ pub fn is_dylib(name: &str) -> bool { /// Returns the corresponding relative library directory that the compiler's /// dylibs will be found in. -pub fn libdir(target: &str) -> &'static str { - if target.contains("windows") {"bin"} else {"lib"} +pub fn libdir(target: &Triple) -> &'static str { + if target.is_windows() {"bin"} else {"lib"} } /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path.