diff options
-rw-r--r-- | src/args.rs | 7 | ||||
-rw-r--r-- | src/context.rs | 67 | ||||
-rw-r--r-- | src/resolve.rs | 12 | ||||
-rw-r--r-- | src/task.rs | 6 |
4 files changed, 72 insertions, 20 deletions
diff --git a/src/args.rs b/src/args.rs index 5192ab7..d7f2306 100644 --- a/src/args.rs +++ b/src/args.rs @@ -41,3 +41,10 @@ impl hash::Hash for TaskArgs { pub fn arg<A: Into<Arg>>(key: &str, value: A) -> (String, Rc<Arg>) { (key.to_string(), Rc::new(value.into())) } + +#[derive(Clone, Debug, Deserialize, Default, PartialEq, Eq)] +pub struct ArgMapping(pub HashMap<String, String>); + +impl hash::Hash for ArgMapping { + fn hash<H: hash::Hasher>(&self, _state: &mut H) {} +} diff --git a/src/context.rs b/src/context.rs index 2eb83bf..f81ea1e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, collections::{HashMap, HashSet}, fmt::Display, hash::Hash, @@ -10,7 +11,7 @@ use std::{ use serde::Serialize; use crate::{ - args::{arg, Arg, ArgType, TaskArgs}, + args::{arg, Arg, ArgMapping, ArgType, TaskArgs}, task::*, types::TaskID, util::error, @@ -20,6 +21,7 @@ use crate::{ pub enum Error<'ctx> { TaskNotFound(&'ctx TaskID), InvalidArgument(&'ctx TaskID, &'ctx str), + InvalidArgRef(&'ctx TaskID, &'ctx str), } impl<'ctx> Display for Error<'ctx> { @@ -31,6 +33,11 @@ impl<'ctx> Display for Error<'ctx> { "Invalid or missing argument '{}' for task '{}'", arg, task ), + Error::InvalidArgRef(task, arg) => write!( + f, + "Invalid reference for argument '{}' of task '{}'", + arg, task + ), } } } @@ -131,34 +138,58 @@ impl Context { self.task_ref(id, &self.default_args).ok() } + fn map_args<'ctx, 'args>( + task: &'ctx TaskID, + mapping: &'ctx ArgMapping, + args: &'args TaskArgs, + build_dep: bool, + ) -> Result<'ctx, Cow<'args, TaskArgs>> { + if mapping.0.is_empty() && !build_dep { + return Ok(Cow::Borrowed(args)); + } + + let mut ret = args.clone(); + + if build_dep { + ret.0.insert("host".to_string(), args.0["build"].clone()); + + // TODO: Hack for correct target of toolchain build depends (gcc -> binutils) + if !ret.0.contains_key("target") { + if let Some(host) = args.0.get("host") { + ret.0.insert("target".to_string(), host.clone()); + } + } + } + + for (to, from) in &mapping.0 { + let value = args + .0 + .get(from) + .ok_or_else(|| Error::InvalidArgRef(task, to))?; + ret.0.insert(to.clone(), value.clone()); + } + + Ok(Cow::Owned(ret)) + } + fn inherit_ref<'ctx>(&'ctx self, dep: &'ctx InheritDep, args: &TaskArgs) -> Result<TaskRef> { - self.task_ref(&dep.task, args) + let mapped_args = Context::map_args(&dep.task, &dep.args, args, false)?; + self.task_ref(&dep.task, mapped_args.as_ref()) } pub fn output_ref<'ctx>( &'ctx self, dep: &'ctx OutputDep, args: &TaskArgs, + build_dep: bool, ) -> Result<OutputRef<'ctx>> { + let mapped_args = Context::map_args(&dep.task, &dep.args, args, build_dep)?; Ok(OutputRef { - task: self.task_ref(&dep.task, args)?, + task: self.task_ref(&dep.task, mapped_args.as_ref())?, output: &dep.output, }) } - fn build_depend_args(args: &TaskArgs) -> TaskArgs { - let mut ret = args.clone(); - - ret.0.insert("host".to_string(), args.0["build"].clone()); - - // TODO: Hack for correct target of toolchain build depends (gcc -> binutils) - if !ret.0.contains_key("target") { - ret.0.insert("target".to_string(), args.0["host"].clone()); - } - - ret - } - pub fn get_inherit_depend<'ctx>( &'ctx self, task_ref: &TaskRef<'ctx>, @@ -178,7 +209,7 @@ impl Context { let task = self.get(task_ref.id)?; task.build_depends .iter() - .map(|dep| self.output_ref(dep, &Context::build_depend_args(&task_ref.args))) + .map(|dep| self.output_ref(dep, &task_ref.args, true)) .collect() } @@ -189,7 +220,7 @@ impl Context { let task = self.get(task_ref.id)?; task.depends .iter() - .map(|dep| self.output_ref(dep, &task_ref.args)) + .map(|dep| self.output_ref(dep, &task_ref.args, false)) .collect() } diff --git a/src/resolve.rs b/src/resolve.rs index 32ceedc..5032351 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -53,6 +53,7 @@ pub enum Error<'ctx> { OutputNotFound(DepChain<'ctx>, &'ctx str), DependencyCycle(DepChain<'ctx>), InvalidArgument(DepChain<'ctx>, &'ctx str), + InvalidArgRef(DepChain<'ctx>, &'ctx str), } impl<'ctx> Error<'ctx> { @@ -74,6 +75,7 @@ impl<'ctx> Error<'ctx> { Error::OutputNotFound(ref mut tasks, _) => tasks, Error::DependencyCycle(ref mut tasks) => tasks, Error::InvalidArgument(ref mut tasks, _) => tasks, + Error::InvalidArgRef(ref mut tasks, _) => tasks, }; tasks.0.push(task.clone()); } @@ -98,6 +100,13 @@ impl<'ctx> fmt::Display for Error<'ctx> { arg, tasks ) } + Error::InvalidArgRef(tasks, arg) => { + write!( + f, + "Invalid reference for argument '{}' of task: {}", + arg, tasks + ) + } } } } @@ -107,6 +116,7 @@ impl<'ctx> From<context::Error<'ctx>> for Error<'ctx> { match err { context::Error::TaskNotFound(task) => Error::task_not_found(task), context::Error::InvalidArgument(task, arg) => Error::InvalidArgument(task.into(), arg), + context::Error::InvalidArgRef(task, arg) => Error::InvalidArgRef(task.into(), arg), } } } @@ -152,7 +162,7 @@ where let mut errors = Vec::new(); for runtime_dep in &output.runtime_depends { - match ctx.output_ref(runtime_dep, &task.args) { + match ctx.output_ref(runtime_dep, &task.args, false) { Ok(output_ref) => { for mut error in add_dep(ret, ctx, output_ref) { error.extend(task); diff --git a/src/task.rs b/src/task.rs index 6428985..10cb8e8 100644 --- a/src/task.rs +++ b/src/task.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use serde::Deserialize; use crate::{ - args::ArgType, + args::{ArgMapping, ArgType}, types::{StringHash, TaskID}, }; @@ -20,11 +20,15 @@ fn default_output_name() -> String { #[derive(Clone, Debug, Deserialize)] pub struct InheritDep { pub task: TaskID, + #[serde(default)] + pub args: ArgMapping, } #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Hash)] pub struct OutputDep { pub task: TaskID, + #[serde(default)] + pub args: ArgMapping, #[serde(default = "default_output_name")] pub output: String, } |