summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/args.rs7
-rw-r--r--src/context.rs67
-rw-r--r--src/resolve.rs12
-rw-r--r--src/task.rs6
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,
}