diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index a8434c3efb358..98857485778c3 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -20,6 +20,7 @@ use std::io::prelude::*; use std::path::PathBuf; use std::process; +use util::build_path; use num_cpus; use rustc_serialize::Decodable; use toml::{Parser, Decoder, Value}; @@ -343,7 +344,7 @@ impl Config { .collect(); } "CFG_MUSL_ROOT" if value.len() > 0 => { - self.musl_root = Some(PathBuf::from(value)); + self.musl_root = Some(build_path(value)); } "CFG_DEFAULT_AR" if value.len() > 0 => { self.rustc_default_ar = Some(value.to_string()); @@ -355,24 +356,24 @@ impl Config { self.channel = value.to_string(); } "CFG_PREFIX" => { - self.prefix = Some(value.to_string()); + self.prefix = Some(build_path(value).to_str().unwrap().to_owned()); } "CFG_LLVM_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); - let root = PathBuf::from(value); + let root = build_path(value); target.llvm_config = Some(root.join("bin/llvm-config")); } "CFG_JEMALLOC_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); - target.jemalloc = Some(PathBuf::from(value)); + target.jemalloc = Some(build_path(value)); } "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { let target = "arm-linux-androideabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(build_path(value)); } "CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { let target = "armv7-linux-androideabi".to_string(); @@ -384,13 +385,13 @@ impl Config { let target = "i686-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(build_path(value)); } "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { let target = "aarch64-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(build_path(value)); } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { self.rustc = Some(PathBuf::from(value).join("bin/rustc")); diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index c4e6399c2c36d..1685d5f09c429 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -22,6 +22,7 @@ use std::collections::HashSet; use std::env; use std::ffi::{OsStr, OsString}; use std::fs; +use std::path::PathBuf; use std::process::Command; use build_helper::output; @@ -132,6 +133,35 @@ pub fn check(build: &mut Build) { panic!("the iOS target is only supported on OSX"); } + // Ensure that LLVM's libraries are reachable so we can run the compiler + if let Some(config) = build.config.target_config.get(target) { + if let Some(ref llvm_config) = config.llvm_config { + let llvm_mode = output(Command::new(&llvm_config).arg("--shared-mode")); + if llvm_mode.trim() == "shared" { + if cfg!(target_os = "macos") { + let dypath = env::var_os("DYLD_LIBRARY_PATH").unwrap_or(OsString::new()); + let lib = output(Command::new(&llvm_config).arg("--libdir")); + let lib_canonical = PathBuf::from(lib.trim()).canonicalize().unwrap(); + let lib_in_dypath = env::split_paths(&dypath).find(|p| { + p.canonicalize().ok().map_or(false, |c| c.eq(&lib_canonical)) + }); + if lib_in_dypath.is_none() { + panic!("Unable to find LLVM's library folder {} in DYLD_LIBRARY_PATH", lib.trim()); + } + } else if cfg!(windows) { + let bin = output(Command::new(&llvm_config).arg("--bindir")); + let bin_canonical = PathBuf::from(bin.trim()).canonicalize().unwrap(); + let bin_in_path = env::split_paths(&path).find(|p| { + p.canonicalize().ok().map_or(false, |c| c.eq(&bin_canonical)) + }); + if bin_in_path.is_none() { + panic!("Unable to find LLVM's binary folder {} in PATH", bin.trim()); + } + } + } + } + } + // Make sure musl-root is valid if specified if target.contains("musl") && !target.contains("mips") { match build.musl_root(target) { diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 6c0a32a54d919..3be1c884ef29c 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -30,6 +30,29 @@ pub fn staticlib(name: &str, target: &str) -> String { } } +#[cfg(not(windows))] +pub fn build_path(path: &str) -> PathBuf { + PathBuf::from(path) +} + +#[cfg(windows)] +pub fn build_path(path: &str) -> PathBuf { + use std::io::{stderr, Write}; + use build_helper::output; + + if path.chars().next() == Some('/') { + let output = output(&mut Command::new("cygpath").arg("-w").arg(path)); + let win_path = output.trim_right(); + writeln!(&mut stderr(), + "note: Converted Unix path '{}' to Windows path '{}'", + path, + win_path).ok(); + PathBuf::from(win_path) + } else { + PathBuf::from(path) + } +} + /// Returns the last-modified time for `path`, or zero if it doesn't exist. pub fn mtime(path: &Path) -> FileTime { fs::metadata(path).map(|f| { diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 5257575a94e8b..11c98dd1d9cee 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -21,7 +21,7 @@ fn main() { println!("cargo:rustc-cfg=cargobuild"); let target = env::var("TARGET").expect("TARGET was not set"); - let llvm_config = env::var_os("LLVM_CONFIG") + let mut llvm_config = env::var_os("LLVM_CONFIG") .map(PathBuf::from) .unwrap_or_else(|| { if let Some(dir) = env::var_os("CARGO_TARGET_DIR") @@ -39,6 +39,7 @@ fn main() { PathBuf::from("llvm-config") }); + llvm_config.set_extension(env::consts::EXE_EXTENSION); println!("cargo:rerun-if-changed={}", llvm_config.display()); // Test whether we're cross-compiling LLVM. This is a pretty rare case @@ -124,9 +125,10 @@ fn main() { .cpp_link_stdlib(None) // we handle this below .compile("librustllvm.a"); - // Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then + // Link in all LLVM libraries, if we're using 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 llvm_static = output(Command::new(&llvm_config).arg("--shared-mode")).trim() == "static"; let mut cmd = Command::new(&llvm_config); cmd.arg("--libs"); if !is_crossed { @@ -161,7 +163,7 @@ fn main() { continue } - let kind = if name.starts_with("LLVM") { + let kind = if name.starts_with("LLVM") && llvm_static { "static" } else { "dylib" @@ -192,6 +194,13 @@ fn main() { } } + if !llvm_static && cfg!(windows) { + // Use --bindir as the search path. DLLs will be placed here. + // llvm-config is bugged and doesn't doesn't indicate this on Windows + let bin = output(Command::new(&llvm_config).arg("--bindir")); + println!("cargo:rustc-link-search=native={}", bin.trim()); + } + // C++ runtime library if !target.contains("msvc") { if let Some(s) = env::var_os("LLVM_STATIC_STDCPP") {