diff --git a/src/main.rs b/src/main.rs index 2575d16..883c7fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ use std::hash::{Hash, Hasher}; use std::io::Write; use std::path::{Path, PathBuf}; use std::process::ExitStatus; -use std::{env, io, process}; +use std::{env, ffi, io, process}; use rustc_version::Channel; @@ -56,9 +56,16 @@ impl CompilationMode { Ok(()) } - fn triple(&self) -> &str { + fn triple(&self) -> String { match *self { CompilationMode::Cross(ref target) => target.triple(), + CompilationMode::Native(ref triple) => triple.to_owned(), + } + } + + fn target_arg(&self) -> &str { + match *self { + CompilationMode::Cross(ref target) => target.target_arg(), CompilationMode::Native(ref triple) => triple, } } @@ -151,11 +158,9 @@ fn run() -> Result { }; let cmode = if let Some(triple) = args.target() { - if Path::new(triple).is_file() { - bail!( - "Xargo doesn't support files as an argument to --target. \ - Use `--target foo` instead of `--target foo.json`." - ) + let path = Path::new(triple); + if path.extension() == Some(ffi::OsStr::new("json")) { + Some(CompilationMode::Cross(Target::new_from_path(path, &cd)?)) } else if triple == meta.host { Some(CompilationMode::Native(meta.host.clone())) } else { @@ -175,7 +180,7 @@ fn run() -> Result { if let Some(cmode) = cmode { let home = xargo::home(&cmode)?; - let rustflags = cargo::rustflags(config.as_ref(), cmode.triple())?; + let rustflags = cargo::rustflags(config.as_ref(), &cmode.triple())?; sysroot::update( &cmode, diff --git a/src/rustc.rs b/src/rustc.rs index 3e86816..c5e7257 100644 --- a/src/rustc.rs +++ b/src/rustc.rs @@ -112,6 +112,7 @@ impl Sysroot { pub enum Target { Builtin { triple: String }, Custom { json: PathBuf, triple: String }, + Path { path: PathBuf }, } impl Target { @@ -148,10 +149,38 @@ impl Target { } } - pub fn triple(&self) -> &str { + pub fn new_from_path(path: &Path, cd: &CurrentDirectory) -> Result { + let json = cd.path().join(path).canonicalize().map_err(|err| { + format!("target path {:?} does not point to a valid file: {:?}", path, err) + })?; + Ok(Target::Path { path: json }) + } + + pub fn triple(&self) -> String { + use std::hash::{Hash, Hasher}; + use std::collections::hash_map::DefaultHasher; + + match *self { + Target::Builtin { ref triple } => triple.clone(), + Target::Custom { ref triple, .. } => triple.clone(), + Target::Path { ref path } => { + let stem = path.file_stem().expect("target path must not be empty").to_str() + .expect("target path must be valid unicode"); + let mut hasher = DefaultHasher::new(); + path.hash(&mut hasher); + let hash = hasher.finish(); + format!("{}-{}", stem, hash) + } + } + } + + pub fn target_arg(&self) -> &str { match *self { Target::Builtin { ref triple } => triple, Target::Custom { ref triple, .. } => triple, + Target::Path { ref path } => { + path.to_str().expect("target path contains invalid unicode") + }, } } diff --git a/src/sysroot.rs b/src/sysroot.rs index 1a0d9da..55fe783 100644 --- a/src/sysroot.rs +++ b/src/sysroot.rs @@ -46,7 +46,7 @@ name = "sysroot" version = "0.0.0" "#; - let rustlib = home.lock_rw(cmode.triple())?; + let rustlib = home.lock_rw(&cmode.triple())?; rustlib .remove_siblings() .chain_err(|| format!("couldn't clear {}", rustlib.path().display()))?; @@ -124,7 +124,7 @@ version = "0.0.0" } cmd.arg("--manifest-path"); cmd.arg(td.join("Cargo.toml")); - cmd.args(&["--target", cmode.triple()]); + cmd.args(&["--target", cmode.target_arg()]); if verbose { cmd.arg("-v"); @@ -155,7 +155,7 @@ version = "0.0.0" fn old_hash(cmode: &CompilationMode, home: &Home) -> Result> { // FIXME this should be `lock_ro` - let lock = home.lock_rw(cmode.triple())?; + let lock = home.lock_rw(&cmode.triple())?; let hfile = lock.parent().join(".hash"); if hfile.exists() { @@ -213,7 +213,7 @@ pub fn update( let ctoml = cargo::toml(root)?; let xtoml = xargo::toml(root)?; - let blueprint = Blueprint::from(xtoml.as_ref(), cmode.triple(), root, &src)?; + let blueprint = Blueprint::from(xtoml.as_ref(), &cmode.triple(), root, &src)?; let hash = hash(cmode, &blueprint, rustflags, &ctoml, meta)?; diff --git a/src/xargo.rs b/src/xargo.rs index ee92406..c0306f6 100644 --- a/src/xargo.rs +++ b/src/xargo.rs @@ -29,7 +29,7 @@ pub fn run( if args.subcommand() == Some(Subcommand::Doc) { cmd.env( "RUSTDOCFLAGS", - cargo::rustdocflags(config, cmode.triple())?.for_xargo(home), + cargo::rustdocflags(config, &cmode.triple())?.for_xargo(home), ); } @@ -39,7 +39,7 @@ pub fn run( } cmd.env("RUSTFLAGS", flags); - let locks = (home.lock_ro(&meta.host), home.lock_ro(cmode.triple())); + let locks = (home.lock_ro(&meta.host), home.lock_ro(&cmode.triple())); let status = cmd.run_and_get_status(verbose)?;