Skip to content

Commit

Permalink
Auto merge of #49019 - phil-opp:target-spec, r=pnkfelix
Browse files Browse the repository at this point in the history
Introduce a TargetTriple enum to support absolute target paths

This PR replaces target triple strings with a `TargetTriple` enum, which represents either a target triple or a path to a JSON target file. The path variant is used if the `--target` argument has a `.json` extension, else the target triple variant is used.

The motivation of this PR is support for absolute target paths to avoid the need for setting the `RUST_TARGET_PATH` environment variable (see rust-lang/cargo#4905 for more information). For places where some kind of triple is needed (e.g. in the sysroot folder), we use the file name (without extension).

For compatibility, we keep the old behavior of searching for a file named `$(target_triple).json` in `RUST_TARGET_PATH` for non-official target triples.
  • Loading branch information
bors committed Mar 28, 2018
2 parents bcffdf1 + b889f98 commit d87c19d
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 57 deletions.
30 changes: 22 additions & 8 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use session::search_paths::SearchPaths;

use ich::StableHashingContext;
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
use rustc_back::target::Target;
use rustc_back::target::{Target, TargetTriple};
use rustc_data_structures::stable_hasher::ToStableHashKey;
use lint;
use middle::cstore;
Expand All @@ -47,7 +47,7 @@ use std::hash::Hasher;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashSet;
use std::iter::FromIterator;
use std::path::PathBuf;
use std::path::{Path, PathBuf};

pub struct Config {
pub target: Target,
Expand Down Expand Up @@ -367,7 +367,7 @@ top_level_options!(
libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
maybe_sysroot: Option<PathBuf> [TRACKED],

target_triple: String [TRACKED],
target_triple: TargetTriple [TRACKED],

test: bool [TRACKED],
error_format: ErrorOutputType [UNTRACKED],
Expand Down Expand Up @@ -567,7 +567,7 @@ pub fn basic_options() -> Options {
output_types: OutputTypes(BTreeMap::new()),
search_paths: SearchPaths::new(),
maybe_sysroot: None,
target_triple: host_triple().to_string(),
target_triple: TargetTriple::from_triple(host_triple()),
test: false,
incremental: None,
debugging_opts: basic_debugging_options(),
Expand Down Expand Up @@ -1922,9 +1922,21 @@ pub fn build_session_options_and_crate_config(
let cg = cg;

let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
let target = matches
.opt_str("target")
.unwrap_or(host_triple().to_string());
let target_triple = if let Some(target) = matches.opt_str("target") {
if target.ends_with(".json") {
let path = Path::new(&target);
match TargetTriple::from_path(&path) {
Ok(triple) => triple,
Err(_) => {
early_error(error_format, &format!("target file {:?} does not exist", path))
}
}
} else {
TargetTriple::TargetTriple(target)
}
} else {
TargetTriple::from_triple(host_triple())
};
let opt_level = {
if matches.opt_present("O") {
if cg.opt_level.is_some() {
Expand Down Expand Up @@ -2132,7 +2144,7 @@ pub fn build_session_options_and_crate_config(
output_types: OutputTypes(output_types),
search_paths,
maybe_sysroot: sysroot_opt,
target_triple: target,
target_triple,
test,
incremental,
debugging_opts,
Expand Down Expand Up @@ -2283,6 +2295,7 @@ mod dep_tracking {
Passes, Sanitizer};
use syntax::feature_gate::UnstableFeatures;
use rustc_back::{PanicStrategy, RelroLevel};
use rustc_back::target::TargetTriple;

pub trait DepTrackingHash {
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
Expand Down Expand Up @@ -2342,6 +2355,7 @@ mod dep_tracking {
impl_dep_tracking_hash_via_hash!(Sanitizer);
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
impl_dep_tracking_hash_via_hash!(Edition);
impl_dep_tracking_hash_via_hash!(TargetTriple);

impl_dep_tracking_hash_for_sortable_vec_of!(String);
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use syntax::feature_gate::AttributeType;
use syntax_pos::{MultiSpan, Span};

use rustc_back::{LinkerFlavor, PanicStrategy};
use rustc_back::target::Target;
use rustc_back::target::{Target, TargetTriple};
use rustc_data_structures::flock;
use jobserver::Client;

Expand Down Expand Up @@ -707,7 +707,7 @@ impl Session {
pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
filesearch::FileSearch::new(
self.sysroot(),
&self.opts.target_triple,
self.opts.target_triple.triple(),
&self.opts.search_paths,
kind,
)
Expand Down Expand Up @@ -1085,7 +1085,8 @@ pub fn build_session_(
span_diagnostic: errors::Handler,
codemap: Lrc<codemap::CodeMap>,
) -> Session {
let host = match Target::search(config::host_triple()) {
let host_triple = TargetTriple::from_triple(config::host_triple());
let host = match Target::search(&host_triple) {
Ok(t) => t,
Err(e) => {
span_diagnostic
Expand Down
114 changes: 89 additions & 25 deletions src/librustc_back/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
use serialize::json::{Json, ToJson};
use std::collections::BTreeMap;
use std::default::Default;
use std::{fmt, io};
use std::path::{Path, PathBuf};
use syntax::abi::{Abi, lookup as lookup_abi};

use {LinkerFlavor, PanicStrategy, RelroLevel};
Expand Down Expand Up @@ -824,11 +826,10 @@ impl Target {
///
/// The error string could come from any of the APIs called, including
/// filesystem access and JSON decoding.
pub fn search(target: &str) -> Result<Target, String> {
pub fn search(target_triple: &TargetTriple) -> Result<Target, String> {
use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::{Path, PathBuf};
use serialize::json;

fn load_file(path: &Path) -> Result<Target, String> {
Expand All @@ -838,35 +839,40 @@ impl Target {
Target::from_json(obj)
}

if let Ok(t) = load_specific(target) {
return Ok(t)
}

let path = Path::new(target);

if path.is_file() {
return load_file(&path);
}
match target_triple {
&TargetTriple::TargetTriple(ref target_triple) => {
// check if triple is in list of supported targets
if let Ok(t) = load_specific(target_triple) {
return Ok(t)
}

let path = {
let mut target = target.to_string();
target.push_str(".json");
PathBuf::from(target)
};
// search for a file named `target_triple`.json in RUST_TARGET_PATH
let path = {
let mut target = target_triple.to_string();
target.push_str(".json");
PathBuf::from(target)
};

let target_path = env::var_os("RUST_TARGET_PATH")
.unwrap_or(OsString::new());
let target_path = env::var_os("RUST_TARGET_PATH")
.unwrap_or(OsString::new());

// FIXME 16351: add a sane default search path?
// FIXME 16351: add a sane default search path?

for dir in env::split_paths(&target_path) {
let p = dir.join(&path);
if p.is_file() {
return load_file(&p);
for dir in env::split_paths(&target_path) {
let p = dir.join(&path);
if p.is_file() {
return load_file(&p);
}
}
Err(format!("Could not find specification for target {:?}", target_triple))
}
&TargetTriple::TargetPath(ref target_path) => {
if target_path.is_file() {
return load_file(&target_path);
}
Err(format!("Target path {:?} is not a valid file", target_path))
}
}

Err(format!("Could not find specification for target {:?}", target))
}
}

Expand Down Expand Up @@ -1014,3 +1020,61 @@ fn maybe_jemalloc() -> Option<String> {
None
}
}

/// Either a target triple string or a path to a JSON file.
#[derive(PartialEq, Clone, Debug, Hash, RustcEncodable, RustcDecodable)]
pub enum TargetTriple {
TargetTriple(String),
TargetPath(PathBuf),
}

impl TargetTriple {
/// Creates a target triple from the passed target triple string.
pub fn from_triple(triple: &str) -> Self {
TargetTriple::TargetTriple(triple.to_string())
}

/// Creates a target triple from the passed target path.
pub fn from_path(path: &Path) -> Result<Self, io::Error> {
let canonicalized_path = path.canonicalize()?;
Ok(TargetTriple::TargetPath(canonicalized_path))
}

/// Returns a string triple for this target.
///
/// If this target is a path, the file name (without extension) is returned.
pub fn triple(&self) -> &str {
match self {
&TargetTriple::TargetTriple(ref triple) => triple,
&TargetTriple::TargetPath(ref path) => {
path.file_stem().expect("target path must not be empty").to_str()
.expect("target path must be valid unicode")
}
}
}

/// Returns an extended string triple for this target.
///
/// If this target is a path, a hash of the path is appended to the triple returned
/// by `triple()`.
pub fn debug_triple(&self) -> String {
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;

let triple = self.triple();
if let &TargetTriple::TargetPath(ref path) = self {
let mut hasher = DefaultHasher::new();
path.hash(&mut hasher);
let hash = hasher.finish();
format!("{}-{}", triple, hash)
} else {
triple.to_owned()
}
}
}

impl fmt::Display for TargetTriple {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.debug_triple())
}
}
12 changes: 7 additions & 5 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use rustc::middle::cstore::DepKind;
use rustc::session::{Session, CrateDisambiguator};
use rustc::session::config::{Sanitizer, self};
use rustc_back::PanicStrategy;
use rustc_back::target::TargetTriple;
use rustc::session::search_paths::PathKind;
use rustc::middle;
use rustc::middle::cstore::{validate_crate_name, ExternCrate};
Expand Down Expand Up @@ -295,7 +296,7 @@ impl<'a> CrateLoader<'a> {

let mut proc_macro_locator = locator::Context {
target: &self.sess.host,
triple: config::host_triple(),
triple: &TargetTriple::from_triple(config::host_triple()),
filesearch: self.sess.host_filesearch(path_kind),
rejected_via_hash: vec![],
rejected_via_triple: vec![],
Expand Down Expand Up @@ -339,7 +340,7 @@ impl<'a> CrateLoader<'a> {
// don't want to match a host crate against an equivalent target one
// already loaded.
let root = library.metadata.get_root();
if locate_ctxt.triple == self.sess.opts.target_triple {
if locate_ctxt.triple == &self.sess.opts.target_triple {
let mut result = LoadResult::Loaded(library);
self.cstore.iter_crate_data(|cnum, data| {
if data.name() == root.name && root.hash == data.hash() {
Expand Down Expand Up @@ -426,8 +427,9 @@ impl<'a> CrateLoader<'a> {
fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol)
-> ExtensionCrate {
info!("read extension crate `extern crate {} as {}`", orig_name, rename);
let target_triple = &self.sess.opts.target_triple[..];
let is_cross = target_triple != config::host_triple();
let target_triple = &self.sess.opts.target_triple;
let host_triple = TargetTriple::from_triple(config::host_triple());
let is_cross = target_triple != &host_triple;
let mut target_only = false;
let mut locate_ctxt = locator::Context {
sess: self.sess,
Expand All @@ -437,7 +439,7 @@ impl<'a> CrateLoader<'a> {
hash: None,
filesearch: self.sess.host_filesearch(PathKind::Crate),
target: &self.sess.host,
triple: config::host_triple(),
triple: &host_triple,
root: &None,
rejected_via_hash: vec![],
rejected_via_triple: vec![],
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_metadata/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ use rustc::util::nodemap::FxHashMap;
use errors::DiagnosticBuilder;
use syntax::symbol::Symbol;
use syntax_pos::Span;
use rustc_back::target::Target;
use rustc_back::target::{Target, TargetTriple};

use std::cmp;
use std::fmt;
Expand All @@ -258,7 +258,7 @@ pub struct Context<'a> {
pub hash: Option<&'a Svh>,
// points to either self.sess.target.target or self.sess.host, must match triple
pub target: &'a Target,
pub triple: &'a str,
pub triple: &'a TargetTriple,
pub filesearch: FileSearch<'a>,
pub root: &'a Option<CratePaths>,
pub rejected_via_hash: Vec<CrateMismatch>,
Expand Down Expand Up @@ -394,7 +394,7 @@ impl<'a> Context<'a> {
add);

if (self.ident == "std" || self.ident == "core")
&& self.triple != config::host_triple() {
&& self.triple != &TargetTriple::from_triple(config::host_triple()) {
err.note(&format!("the `{}` target may not be installed", self.triple));
}
err.span_label(self.span, "can't find crate");
Expand Down Expand Up @@ -698,13 +698,13 @@ impl<'a> Context<'a> {
}
}

if root.triple != self.triple {
if &root.triple != self.triple {
info!("Rejecting via crate triple: expected {} got {}",
self.triple,
root.triple);
self.rejected_via_triple.push(CrateMismatch {
path: libpath.to_path_buf(),
got: root.triple,
got: format!("{}", root.triple),
});
return None;
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_metadata/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use rustc::mir;
use rustc::session::CrateDisambiguator;
use rustc::ty::{self, Ty, ReprOptions};
use rustc_back::PanicStrategy;
use rustc_back::target::TargetTriple;

use rustc_serialize as serialize;
use syntax::{ast, attr};
Expand Down Expand Up @@ -186,7 +187,7 @@ pub enum LazyState {
#[derive(RustcEncodable, RustcDecodable)]
pub struct CrateRoot {
pub name: Symbol,
pub triple: String,
pub triple: TargetTriple,
pub hash: hir::svh::Svh,
pub disambiguator: CrateDisambiguator,
pub panic_strategy: PanicStrategy,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ impl<'a, 'tcx> FnType<'tcx> {
"s390x" => cabi_s390x::compute_abi_info(cx, self),
"asmjs" => cabi_asmjs::compute_abi_info(cx, self),
"wasm32" => {
if cx.sess().opts.target_triple.contains("emscripten") {
if cx.sess().opts.target_triple.triple().contains("emscripten") {
cabi_asmjs::compute_abi_info(cx, self)
} else {
cabi_wasm32::compute_abi_info(cx, self)
Expand Down
Loading

0 comments on commit d87c19d

Please sign in to comment.