Skip to content

Commit d87c19d

Browse files
committed
Auto merge of #49019 - phil-opp:target-spec, r=pnkfelix
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.
2 parents bcffdf1 + b889f98 commit d87c19d

File tree

12 files changed

+150
-57
lines changed

12 files changed

+150
-57
lines changed

Diff for: src/librustc/session/config.rs

+22-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use session::search_paths::SearchPaths;
2121

2222
use ich::StableHashingContext;
2323
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
24-
use rustc_back::target::Target;
24+
use rustc_back::target::{Target, TargetTriple};
2525
use rustc_data_structures::stable_hasher::ToStableHashKey;
2626
use lint;
2727
use middle::cstore;
@@ -47,7 +47,7 @@ use std::hash::Hasher;
4747
use std::collections::hash_map::DefaultHasher;
4848
use std::collections::HashSet;
4949
use std::iter::FromIterator;
50-
use std::path::PathBuf;
50+
use std::path::{Path, PathBuf};
5151

5252
pub struct Config {
5353
pub target: Target,
@@ -367,7 +367,7 @@ top_level_options!(
367367
libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
368368
maybe_sysroot: Option<PathBuf> [TRACKED],
369369

370-
target_triple: String [TRACKED],
370+
target_triple: TargetTriple [TRACKED],
371371

372372
test: bool [TRACKED],
373373
error_format: ErrorOutputType [UNTRACKED],
@@ -567,7 +567,7 @@ pub fn basic_options() -> Options {
567567
output_types: OutputTypes(BTreeMap::new()),
568568
search_paths: SearchPaths::new(),
569569
maybe_sysroot: None,
570-
target_triple: host_triple().to_string(),
570+
target_triple: TargetTriple::from_triple(host_triple()),
571571
test: false,
572572
incremental: None,
573573
debugging_opts: basic_debugging_options(),
@@ -1922,9 +1922,21 @@ pub fn build_session_options_and_crate_config(
19221922
let cg = cg;
19231923

19241924
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
1925-
let target = matches
1926-
.opt_str("target")
1927-
.unwrap_or(host_triple().to_string());
1925+
let target_triple = if let Some(target) = matches.opt_str("target") {
1926+
if target.ends_with(".json") {
1927+
let path = Path::new(&target);
1928+
match TargetTriple::from_path(&path) {
1929+
Ok(triple) => triple,
1930+
Err(_) => {
1931+
early_error(error_format, &format!("target file {:?} does not exist", path))
1932+
}
1933+
}
1934+
} else {
1935+
TargetTriple::TargetTriple(target)
1936+
}
1937+
} else {
1938+
TargetTriple::from_triple(host_triple())
1939+
};
19281940
let opt_level = {
19291941
if matches.opt_present("O") {
19301942
if cg.opt_level.is_some() {
@@ -2132,7 +2144,7 @@ pub fn build_session_options_and_crate_config(
21322144
output_types: OutputTypes(output_types),
21332145
search_paths,
21342146
maybe_sysroot: sysroot_opt,
2135-
target_triple: target,
2147+
target_triple,
21362148
test,
21372149
incremental,
21382150
debugging_opts,
@@ -2283,6 +2295,7 @@ mod dep_tracking {
22832295
Passes, Sanitizer};
22842296
use syntax::feature_gate::UnstableFeatures;
22852297
use rustc_back::{PanicStrategy, RelroLevel};
2298+
use rustc_back::target::TargetTriple;
22862299

22872300
pub trait DepTrackingHash {
22882301
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
@@ -2342,6 +2355,7 @@ mod dep_tracking {
23422355
impl_dep_tracking_hash_via_hash!(Sanitizer);
23432356
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
23442357
impl_dep_tracking_hash_via_hash!(Edition);
2358+
impl_dep_tracking_hash_via_hash!(TargetTriple);
23452359

23462360
impl_dep_tracking_hash_for_sortable_vec_of!(String);
23472361
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);

Diff for: src/librustc/session/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use syntax::feature_gate::AttributeType;
4242
use syntax_pos::{MultiSpan, Span};
4343

4444
use rustc_back::{LinkerFlavor, PanicStrategy};
45-
use rustc_back::target::Target;
45+
use rustc_back::target::{Target, TargetTriple};
4646
use rustc_data_structures::flock;
4747
use jobserver::Client;
4848

@@ -707,7 +707,7 @@ impl Session {
707707
pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
708708
filesearch::FileSearch::new(
709709
self.sysroot(),
710-
&self.opts.target_triple,
710+
self.opts.target_triple.triple(),
711711
&self.opts.search_paths,
712712
kind,
713713
)
@@ -1085,7 +1085,8 @@ pub fn build_session_(
10851085
span_diagnostic: errors::Handler,
10861086
codemap: Lrc<codemap::CodeMap>,
10871087
) -> Session {
1088-
let host = match Target::search(config::host_triple()) {
1088+
let host_triple = TargetTriple::from_triple(config::host_triple());
1089+
let host = match Target::search(&host_triple) {
10891090
Ok(t) => t,
10901091
Err(e) => {
10911092
span_diagnostic

Diff for: src/librustc_back/target/mod.rs

+89-25
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
use serialize::json::{Json, ToJson};
4848
use std::collections::BTreeMap;
4949
use std::default::Default;
50+
use std::{fmt, io};
51+
use std::path::{Path, PathBuf};
5052
use syntax::abi::{Abi, lookup as lookup_abi};
5153

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

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

841-
if let Ok(t) = load_specific(target) {
842-
return Ok(t)
843-
}
844-
845-
let path = Path::new(target);
846-
847-
if path.is_file() {
848-
return load_file(&path);
849-
}
842+
match target_triple {
843+
&TargetTriple::TargetTriple(ref target_triple) => {
844+
// check if triple is in list of supported targets
845+
if let Ok(t) = load_specific(target_triple) {
846+
return Ok(t)
847+
}
850848

851-
let path = {
852-
let mut target = target.to_string();
853-
target.push_str(".json");
854-
PathBuf::from(target)
855-
};
849+
// search for a file named `target_triple`.json in RUST_TARGET_PATH
850+
let path = {
851+
let mut target = target_triple.to_string();
852+
target.push_str(".json");
853+
PathBuf::from(target)
854+
};
856855

857-
let target_path = env::var_os("RUST_TARGET_PATH")
858-
.unwrap_or(OsString::new());
856+
let target_path = env::var_os("RUST_TARGET_PATH")
857+
.unwrap_or(OsString::new());
859858

860-
// FIXME 16351: add a sane default search path?
859+
// FIXME 16351: add a sane default search path?
861860

862-
for dir in env::split_paths(&target_path) {
863-
let p = dir.join(&path);
864-
if p.is_file() {
865-
return load_file(&p);
861+
for dir in env::split_paths(&target_path) {
862+
let p = dir.join(&path);
863+
if p.is_file() {
864+
return load_file(&p);
865+
}
866+
}
867+
Err(format!("Could not find specification for target {:?}", target_triple))
868+
}
869+
&TargetTriple::TargetPath(ref target_path) => {
870+
if target_path.is_file() {
871+
return load_file(&target_path);
872+
}
873+
Err(format!("Target path {:?} is not a valid file", target_path))
866874
}
867875
}
868-
869-
Err(format!("Could not find specification for target {:?}", target))
870876
}
871877
}
872878

@@ -1014,3 +1020,61 @@ fn maybe_jemalloc() -> Option<String> {
10141020
None
10151021
}
10161022
}
1023+
1024+
/// Either a target triple string or a path to a JSON file.
1025+
#[derive(PartialEq, Clone, Debug, Hash, RustcEncodable, RustcDecodable)]
1026+
pub enum TargetTriple {
1027+
TargetTriple(String),
1028+
TargetPath(PathBuf),
1029+
}
1030+
1031+
impl TargetTriple {
1032+
/// Creates a target triple from the passed target triple string.
1033+
pub fn from_triple(triple: &str) -> Self {
1034+
TargetTriple::TargetTriple(triple.to_string())
1035+
}
1036+
1037+
/// Creates a target triple from the passed target path.
1038+
pub fn from_path(path: &Path) -> Result<Self, io::Error> {
1039+
let canonicalized_path = path.canonicalize()?;
1040+
Ok(TargetTriple::TargetPath(canonicalized_path))
1041+
}
1042+
1043+
/// Returns a string triple for this target.
1044+
///
1045+
/// If this target is a path, the file name (without extension) is returned.
1046+
pub fn triple(&self) -> &str {
1047+
match self {
1048+
&TargetTriple::TargetTriple(ref triple) => triple,
1049+
&TargetTriple::TargetPath(ref path) => {
1050+
path.file_stem().expect("target path must not be empty").to_str()
1051+
.expect("target path must be valid unicode")
1052+
}
1053+
}
1054+
}
1055+
1056+
/// Returns an extended string triple for this target.
1057+
///
1058+
/// If this target is a path, a hash of the path is appended to the triple returned
1059+
/// by `triple()`.
1060+
pub fn debug_triple(&self) -> String {
1061+
use std::hash::{Hash, Hasher};
1062+
use std::collections::hash_map::DefaultHasher;
1063+
1064+
let triple = self.triple();
1065+
if let &TargetTriple::TargetPath(ref path) = self {
1066+
let mut hasher = DefaultHasher::new();
1067+
path.hash(&mut hasher);
1068+
let hash = hasher.finish();
1069+
format!("{}-{}", triple, hash)
1070+
} else {
1071+
triple.to_owned()
1072+
}
1073+
}
1074+
}
1075+
1076+
impl fmt::Display for TargetTriple {
1077+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1078+
write!(f, "{}", self.debug_triple())
1079+
}
1080+
}

Diff for: src/librustc_metadata/creader.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc::middle::cstore::DepKind;
2222
use rustc::session::{Session, CrateDisambiguator};
2323
use rustc::session::config::{Sanitizer, self};
2424
use rustc_back::PanicStrategy;
25+
use rustc_back::target::TargetTriple;
2526
use rustc::session::search_paths::PathKind;
2627
use rustc::middle;
2728
use rustc::middle::cstore::{validate_crate_name, ExternCrate};
@@ -295,7 +296,7 @@ impl<'a> CrateLoader<'a> {
295296

296297
let mut proc_macro_locator = locator::Context {
297298
target: &self.sess.host,
298-
triple: config::host_triple(),
299+
triple: &TargetTriple::from_triple(config::host_triple()),
299300
filesearch: self.sess.host_filesearch(path_kind),
300301
rejected_via_hash: vec![],
301302
rejected_via_triple: vec![],
@@ -339,7 +340,7 @@ impl<'a> CrateLoader<'a> {
339340
// don't want to match a host crate against an equivalent target one
340341
// already loaded.
341342
let root = library.metadata.get_root();
342-
if locate_ctxt.triple == self.sess.opts.target_triple {
343+
if locate_ctxt.triple == &self.sess.opts.target_triple {
343344
let mut result = LoadResult::Loaded(library);
344345
self.cstore.iter_crate_data(|cnum, data| {
345346
if data.name() == root.name && root.hash == data.hash() {
@@ -426,8 +427,9 @@ impl<'a> CrateLoader<'a> {
426427
fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol)
427428
-> ExtensionCrate {
428429
info!("read extension crate `extern crate {} as {}`", orig_name, rename);
429-
let target_triple = &self.sess.opts.target_triple[..];
430-
let is_cross = target_triple != config::host_triple();
430+
let target_triple = &self.sess.opts.target_triple;
431+
let host_triple = TargetTriple::from_triple(config::host_triple());
432+
let is_cross = target_triple != &host_triple;
431433
let mut target_only = false;
432434
let mut locate_ctxt = locator::Context {
433435
sess: self.sess,
@@ -437,7 +439,7 @@ impl<'a> CrateLoader<'a> {
437439
hash: None,
438440
filesearch: self.sess.host_filesearch(PathKind::Crate),
439441
target: &self.sess.host,
440-
triple: config::host_triple(),
442+
triple: &host_triple,
441443
root: &None,
442444
rejected_via_hash: vec![],
443445
rejected_via_triple: vec![],

Diff for: src/librustc_metadata/locator.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ use rustc::util::nodemap::FxHashMap;
233233
use errors::DiagnosticBuilder;
234234
use syntax::symbol::Symbol;
235235
use syntax_pos::Span;
236-
use rustc_back::target::Target;
236+
use rustc_back::target::{Target, TargetTriple};
237237

238238
use std::cmp;
239239
use std::fmt;
@@ -258,7 +258,7 @@ pub struct Context<'a> {
258258
pub hash: Option<&'a Svh>,
259259
// points to either self.sess.target.target or self.sess.host, must match triple
260260
pub target: &'a Target,
261-
pub triple: &'a str,
261+
pub triple: &'a TargetTriple,
262262
pub filesearch: FileSearch<'a>,
263263
pub root: &'a Option<CratePaths>,
264264
pub rejected_via_hash: Vec<CrateMismatch>,
@@ -394,7 +394,7 @@ impl<'a> Context<'a> {
394394
add);
395395

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

701-
if root.triple != self.triple {
701+
if &root.triple != self.triple {
702702
info!("Rejecting via crate triple: expected {} got {}",
703703
self.triple,
704704
root.triple);
705705
self.rejected_via_triple.push(CrateMismatch {
706706
path: libpath.to_path_buf(),
707-
got: root.triple,
707+
got: format!("{}", root.triple),
708708
});
709709
return None;
710710
}

Diff for: src/librustc_metadata/schema.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc::mir;
2222
use rustc::session::CrateDisambiguator;
2323
use rustc::ty::{self, Ty, ReprOptions};
2424
use rustc_back::PanicStrategy;
25+
use rustc_back::target::TargetTriple;
2526

2627
use rustc_serialize as serialize;
2728
use syntax::{ast, attr};
@@ -186,7 +187,7 @@ pub enum LazyState {
186187
#[derive(RustcEncodable, RustcDecodable)]
187188
pub struct CrateRoot {
188189
pub name: Symbol,
189-
pub triple: String,
190+
pub triple: TargetTriple,
190191
pub hash: hir::svh::Svh,
191192
pub disambiguator: CrateDisambiguator,
192193
pub panic_strategy: PanicStrategy,

Diff for: src/librustc_trans/abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,7 @@ impl<'a, 'tcx> FnType<'tcx> {
950950
"s390x" => cabi_s390x::compute_abi_info(cx, self),
951951
"asmjs" => cabi_asmjs::compute_abi_info(cx, self),
952952
"wasm32" => {
953-
if cx.sess().opts.target_triple.contains("emscripten") {
953+
if cx.sess().opts.target_triple.triple().contains("emscripten") {
954954
cabi_asmjs::compute_abi_info(cx, self)
955955
} else {
956956
cabi_wasm32::compute_abi_info(cx, self)

0 commit comments

Comments
 (0)