diff --git a/src/sysroot.rs b/src/sysroot.rs index 8d9d230..4e78e94 100644 --- a/src/sysroot.rs +++ b/src/sysroot.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::io::{self, Write}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::{env, fs}; use rustc_version::VersionMeta; @@ -236,9 +236,15 @@ pub fn update( message_format: Option<&str> ) -> Result<()> { let ctoml = cargo::toml(root)?; - let xtoml = xargo::toml(root)?; + let (xtoml_parent, xtoml) = xargo::toml(root)?; - let blueprint = Blueprint::from(xtoml.as_ref(), cmode.triple(), root, &src)?; + // As paths in the 'Xargo.toml' can be relative to the directory containing + // the 'Xargo.toml', we need to pass the path containing it to the + // Blueprint. Otherwise, if no 'Xargo.toml' is found, we use the regular + // root path. + let base_path: &Path = xtoml_parent.unwrap_or_else(|| root.path()); + + let blueprint = Blueprint::from(xtoml.as_ref(), cmode.triple(), &base_path, &src)?; let hash = hash(cmode, &blueprint, rustflags, &ctoml, meta)?; @@ -364,10 +370,10 @@ impl Blueprint { Ok(()) } - fn from(toml: Option<&xargo::Toml>, target: &str, root: &Root, src: &Src) -> Result { + fn from(toml: Option<&xargo::Toml>, target: &str, base_path: &Path, src: &Src) -> Result { fn make_path_absolute( crate_spec: &mut toml::Table, - root: &Root, + base_path: &Path, on_error_path: F, ) -> Result<()> where @@ -382,7 +388,7 @@ impl Blueprint { if !p.is_absolute() { *path = Value::String( - root.path() + base_path .join(&p) .canonicalize() .chain_err(|| format!("couldn't canonicalize {}", p.display()))? @@ -407,7 +413,7 @@ impl Blueprint { for (k2, v) in v.as_table_mut(|| format!("patch.{}", k1))?.iter_mut() { let krate = v.as_table_mut(|| format!("patch.{}.{}", k1, k2))?; - make_path_absolute(krate, root, || format!("patch.{}.{}", k1, k2))?; + make_path_absolute(krate, base_path, || format!("patch.{}.{}", k1, k2))?; } } @@ -487,7 +493,7 @@ impl Blueprint { 0 }; - make_path_absolute(&mut map, root, || format!("dependencies.{}", k))?; + make_path_absolute(&mut map, base_path, || format!("dependencies.{}", k))?; if !map.contains_key("path") && !map.contains_key("git") { // No path and no git given. This might be in the sysroot, but if we don't find it there we assume it comes from crates.io. diff --git a/src/xargo.rs b/src/xargo.rs index 06b21bd..c56d203 100644 --- a/src/xargo.rs +++ b/src/xargo.rs @@ -1,4 +1,4 @@ -use std::path::{Display, PathBuf}; +use std::path::{Display, Path, PathBuf}; use std::process::ExitStatus; use std::{env, mem}; use std::io::{self, Write}; @@ -120,11 +120,13 @@ impl Toml { } } -pub fn toml(root: &Root) -> Result> { +/// Returns the closest directory containing a 'Xargo.toml' and the parsed +/// content of this 'Xargo.toml' +pub fn toml(root: &Root) -> Result<(Option<&Path>, Option)> { if let Some(p) = util::search(root.path(), "Xargo.toml") { - util::parse(&p.join("Xargo.toml")).map(|t| Some(Toml { table: t })) + Ok((Some(p), util::parse(&p.join("Xargo.toml")).map(|t| Some(Toml { table: t }))?)) } else { - Ok(None) + Ok((None, None)) } } diff --git a/tests/smoke.rs b/tests/smoke.rs index b5dbe63..7610869 100644 --- a/tests/smoke.rs +++ b/tests/smoke.rs @@ -170,6 +170,18 @@ struct Project { td: TempDir, } +/// Create a simple project +fn create_simple_project(project_path: &Path, name: &'static str, library_source: &'static str) -> Result<()> { + xargo()? + .args(&["init", "-q", "--lib", "--vcs", "none", "--name", name]) + .current_dir(project_path) + .run()?; + + write(&project_path.join("src/lib.rs"), false, library_source)?; + + Ok(()) +} + impl Project { /// Creates a new project with given name in a temporary directory. fn new(name: &'static str) -> Result { @@ -194,13 +206,7 @@ impl Project { let td = TempDir::new_in(dir, "xargo").chain_err(|| "couldn't create a temporary directory")?; - xargo()? - .args(&["init", "-q", "--lib", "--vcs", "none", "--name", name]) - .current_dir(td.path()) - .run()?; - - write(&td.path().join("src/lib.rs"), false, "#![no_std]")?; - + create_simple_project(td.path(), name, "#![no_std]")?; write(&td.path().join(format!("{}.json", name)), false, JSON)?; Ok(Project { name: name, td: td }) @@ -363,18 +369,28 @@ fn target_dependencies() { fn run() -> Result<()> { // need this exact target name to get the right gcc flags const TARGET: &'static str = "thumbv7m-none-eabi"; + const STAGE1: &'static str = "stage1"; let td = TempDir::new("xargo").chain_err(|| "couldn't create a temporary directory")?; let project = Project::new_in(td.path().to_path_buf(), TARGET)?; + + let stage1_path = td.path().join(STAGE1); + + mkdir(stage1_path.as_path())?; + create_simple_project(stage1_path.as_path(), STAGE1, "#![no_std]")?; write(&td.path().join("Xargo.toml"), false, r#" [target.thumbv7m-none-eabi.dependencies.alloc] + +[target.thumbv7m-none-eabi.dependencies.stage1] +stage = 1 +path = "stage1" "#, )?; project.build(TARGET)?; assert!(exists("core", TARGET)?); assert!(exists("alloc", TARGET)?); - + assert!(exists("stage1", TARGET)?); Ok(()) }