提交 d87c19db 编写于 作者: B bors

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.
......@@ -21,7 +21,7 @@
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;
......@@ -47,7 +47,7 @@
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,
......@@ -367,7 +367,7 @@ pub struct 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],
......@@ -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(),
......@@ -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() {
......@@ -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,
......@@ -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);
......@@ -2342,6 +2355,7 @@ fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
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);
......
......@@ -42,7 +42,7 @@
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;
......@@ -707,7 +707,7 @@ pub fn sysroot<'a>(&'a self) -> &'a Path {
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,
)
......@@ -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
......
......@@ -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};
......@@ -824,11 +826,10 @@ pub fn from_json(obj: Json) -> TargetResult {
///
/// 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> {
......@@ -838,35 +839,40 @@ fn load_file(path: &Path) -> Result<Target, String> {
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))
}
}
......@@ -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())
}
}
......@@ -22,6 +22,7 @@
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};
......@@ -295,7 +296,7 @@ fn resolve_crate(&mut self,
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![],
......@@ -339,7 +340,7 @@ fn load(&mut self, locate_ctxt: &mut locator::Context) -> Option<LoadResult> {
// 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() {
......@@ -426,8 +427,9 @@ fn resolve_crate_deps(&mut self,
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,
......@@ -437,7 +439,7 @@ fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol
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![],
......
......@@ -233,7 +233,7 @@
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;
......@@ -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>,
......@@ -394,7 +394,7 @@ pub fn report_errs(&mut self) -> ! {
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");
......@@ -698,13 +698,13 @@ fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<S
}
}
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;
}
......
......@@ -22,6 +22,7 @@
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};
......@@ -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,
......
......@@ -950,7 +950,7 @@ fn adjust_for_abi(&mut self,
"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)
......
......@@ -31,6 +31,7 @@
use rustc::hir::def_id::CrateNum;
use tempdir::TempDir;
use rustc_back::{PanicStrategy, RelroLevel};
use rustc_back::target::TargetTriple;
use context::get_reloc_model;
use llvm;
......@@ -81,7 +82,7 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command) {
}
};
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple, "link.exe");
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
let linker_path = sess.opts.cg.linker.as_ref().map(|s| &**s)
.or(sess.target.target.options.linker.as_ref().map(|s| s.as_ref()))
......@@ -812,7 +813,7 @@ fn escape_string(s: &[u8]) -> String {
}
}
if sess.opts.target_triple == "wasm32-unknown-unknown" {
if sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown") {
wasm::rewrite_imports(&out_filename, &trans.crate_info.wasm_imports);
wasm::add_custom_sections(&out_filename,
&trans.crate_info.wasm_custom_sections);
......@@ -1094,7 +1095,7 @@ fn link_args(cmd: &mut Linker,
// addl_lib_search_paths
if sess.opts.cg.rpath {
let sysroot = sess.sysroot();
let target_triple = &sess.opts.target_triple;
let target_triple = sess.opts.target_triple.triple();
let mut get_install_prefix_lib_path = || {
let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
let tlib = filesearch::relative_target_lib_path(sysroot, target_triple);
......
......@@ -859,7 +859,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
"rustc.embedded.module\0".as_ptr() as *const _,
);
llvm::LLVMSetInitializer(llglobal, llconst);
let section = if cgcx.opts.target_triple.contains("-ios") {
let section = if cgcx.opts.target_triple.triple().contains("-ios") {
"__LLVM,__bitcode\0"
} else {
".llvmbc\0"
......@@ -874,7 +874,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
"rustc.embedded.cmdline\0".as_ptr() as *const _,
);
llvm::LLVMSetInitializer(llglobal, llconst);
let section = if cgcx.opts.target_triple.contains("-ios") {
let section = if cgcx.opts.target_triple.triple().contains("-ios") {
"__LLVM,__cmdline\0"
} else {
".llvmcmd\0"
......
......@@ -73,6 +73,7 @@
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
use CrateInfo;
use rustc_data_structures::sync::Lrc;
use rustc_back::target::TargetTriple;
use std::any::Any;
use std::collections::BTreeMap;
......@@ -1086,7 +1087,7 @@ pub fn new(tcx: TyCtxt) -> CrateInfo {
let load_wasm_items = tcx.sess.crate_types.borrow()
.iter()
.any(|c| *c != config::CrateTypeRlib) &&
tcx.sess.opts.target_triple == "wasm32-unknown-unknown";
tcx.sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown");
if load_wasm_items {
info!("attempting to load all wasm sections");
......
......@@ -22,6 +22,7 @@
use rustc_resolve as resolve;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::CStore;
use rustc_back::target::TargetTriple;
use syntax::ast::NodeId;
use syntax::codemap;
......@@ -118,7 +119,7 @@ pub fn run_core(search_paths: SearchPaths,
cfgs: Vec<String>,
externs: config::Externs,
input: Input,
triple: Option<String>,
triple: Option<TargetTriple>,
maybe_sysroot: Option<PathBuf>,
allow_warnings: bool,
crate_name: Option<String>,
......@@ -133,6 +134,7 @@ pub fn run_core(search_paths: SearchPaths,
let warning_lint = lint::builtin::WARNINGS.name_lower();
let host_triple = TargetTriple::from_triple(config::host_triple());
let sessopts = config::Options {
maybe_sysroot,
search_paths,
......@@ -140,7 +142,7 @@ pub fn run_core(search_paths: SearchPaths,
lint_opts: if !allow_warnings { vec![(warning_lint, lint::Allow)] } else { vec![] },
lint_cap: Some(lint::Allow),
externs,
target_triple: triple.unwrap_or(config::host_triple().to_string()),
target_triple: triple.unwrap_or(host_triple),
// Ensure that rustdoc works even if rustc is feature-staged
unstable_features: UnstableFeatures::Allow,
actually_rustdoc: true,
......
......@@ -64,6 +64,7 @@
use externalfiles::ExternalHtml;
use rustc::session::search_paths::SearchPaths;
use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options, Externs};
use rustc_back::target::TargetTriple;
#[macro_use]
pub mod externalfiles;
......@@ -542,7 +543,13 @@ fn rust_input<R, F>(cratefile: PathBuf, externs: Externs, matches: &getopts::Mat
paths.add_path(s, ErrorOutputType::default());
}
let cfgs = matches.opt_strs("cfg");
let triple = matches.opt_str("target");
let triple = matches.opt_str("target").map(|target| {
if target.ends_with(".json") {
TargetTriple::TargetPath(PathBuf::from(target))
} else {
TargetTriple::TargetTriple(target)
}
});
let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
let crate_name = matches.opt_str("crate-name");
let crate_version = matches.opt_str("crate-version");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册