diff options
-rw-r--r-- | examples/bar.yml | 2 | ||||
-rw-r--r-- | examples/binutils.yml | 2 | ||||
-rw-r--r-- | examples/foo.yml | 2 | ||||
-rw-r--r-- | examples/gcc-libs.yml | 2 | ||||
-rw-r--r-- | examples/gcc.yml | 4 | ||||
-rw-r--r-- | examples/glibc.yml | 2 | ||||
-rw-r--r-- | examples/libgcc-initial.yml | 2 | ||||
-rw-r--r-- | examples/linux-uapi-headers.yml | 2 | ||||
-rw-r--r-- | examples/ls.yml | 2 | ||||
-rw-r--r-- | src/executor.rs | 21 | ||||
-rw-r--r-- | src/resolve.rs | 30 | ||||
-rw-r--r-- | src/types.rs | 17 |
12 files changed, 74 insertions, 14 deletions
diff --git a/examples/bar.yml b/examples/bar.yml index ca01afa..ece6fd1 100644 --- a/examples/bar.yml +++ b/examples/bar.yml @@ -1,5 +1,7 @@ tasks: build: + output: + default: {} run: | findmnt -o +PROPAGATION mkdir -p "${DESTDIR}" diff --git a/examples/binutils.yml b/examples/binutils.yml index 56342f7..c05d965 100644 --- a/examples/binutils.yml +++ b/examples/binutils.yml @@ -41,6 +41,8 @@ tasks: install: inherit: task: 'binutils:compile' + output: + default: {} run: | cd binutils-build make DESTDIR="$DESTDIR" install diff --git a/examples/foo.yml b/examples/foo.yml index 6b50c07..6b82812 100644 --- a/examples/foo.yml +++ b/examples/foo.yml @@ -1,5 +1,7 @@ tasks: build: + output: + default: {} run: | ls -lha ls -lha /proc/self/fd diff --git a/examples/gcc-libs.yml b/examples/gcc-libs.yml index ccd6ebf..8eda21b 100644 --- a/examples/gcc-libs.yml +++ b/examples/gcc-libs.yml @@ -19,6 +19,8 @@ tasks: target_depends: - task: 'linux-uapi-headers:install' - task: 'glibc:install' + output: + default: {} run: | cd gcc-build make DESTDIR="$DESTDIR" install-target-libgcc install-target-libstdc++-v3 install-target-libgomp install-target-libquadmath install-target-libatomic diff --git a/examples/gcc.yml b/examples/gcc.yml index 8c938e5..7a215a9 100644 --- a/examples/gcc.yml +++ b/examples/gcc.yml @@ -9,6 +9,8 @@ tasks: sed -i -e 's@^MULTILIB_OSDIRNAMES@# &@' gcc-11.2.0/gcc/config/*/t-* header-stubs: + output: + default: {} run: | mkdir -p "${DESTDIR}${PREFIX}/include" touch "${DESTDIR}${PREFIX}/include/limits.h" @@ -80,6 +82,8 @@ tasks: install: inherit: task: 'gcc:compile' + output: + default: {} run: | cd gcc-build make DESTDIR="$DESTDIR" install-host diff --git a/examples/glibc.yml b/examples/glibc.yml index 19d5f85..d98a1fa 100644 --- a/examples/glibc.yml +++ b/examples/glibc.yml @@ -73,6 +73,8 @@ tasks: - task: 'libgcc-initial:install' target_depends: - task: 'linux-uapi-headers:install' + output: + default: {} run: | cd glibc-build make install_root="${DESTDIR}" install diff --git a/examples/libgcc-initial.yml b/examples/libgcc-initial.yml index 35f1bd5..086f9ee 100644 --- a/examples/libgcc-initial.yml +++ b/examples/libgcc-initial.yml @@ -39,6 +39,8 @@ tasks: task: 'libgcc-initial:compile' build_depends: - task: 'binutils:install' + output: + default: {} run: | cd gcc-build make DESTDIR="$DESTDIR" install-target-libgcc diff --git a/examples/linux-uapi-headers.yml b/examples/linux-uapi-headers.yml index 02b58b3..95f6d11 100644 --- a/examples/linux-uapi-headers.yml +++ b/examples/linux-uapi-headers.yml @@ -9,6 +9,8 @@ tasks: install: inherit: task: 'linux-uapi-headers:unpack' + output: + default: {} run: | TARGET_ARCH=arm64 diff --git a/examples/ls.yml b/examples/ls.yml index b2cc678..63816a0 100644 --- a/examples/ls.yml +++ b/examples/ls.yml @@ -3,6 +3,8 @@ tasks: target_depends: - task: 'foo:build' - task: 'bar:build' + output: + default: {} run: | ls -lh / ls -lhR "${SYSROOT}" diff --git a/src/executor.rs b/src/executor.rs index 1e76fea..d9cde15 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -25,6 +25,7 @@ struct TaskInput<'a> { pub id: &'a TaskRef, pub inherit: Option<InputHash>, pub depends: &'a HashMap<DependencyHash, Dependency>, + pub output: &'a HashMap<String, Output>, pub action: &'a Action, pub env: &'a HashMap<String, String>, } @@ -96,15 +97,18 @@ impl<'a> Executor<'a> { for task in taskset { let task_def = tasks.get(&task.id).expect("Invalid TaskRef"); - if task_def.get_depends().next().is_none() { - exc.tasks_runnable.push(task); - } else { - for dep in task_def.get_depends() { - let rdep = exc.rdeps.entry(dep.clone()).or_default(); - rdep.push(task.clone()); - } + let mut has_depends = false; + for dep in task_def.get_depend_tasks() { + let rdep = exc.rdeps.entry(dep.clone()).or_default(); + rdep.push(task.clone()); + has_depends = true; + } + + if has_depends { exc.tasks_blocked.insert(task); + } else { + exc.tasks_runnable.push(task); } } @@ -117,7 +121,7 @@ impl<'a> Executor<'a> { fn deps_satisfied(&self, task_ref: &TaskRef) -> bool { let task = self.tasks.get(&task_ref.id).expect("Invalid TaskRef"); - task.get_depends() + task.get_depend_tasks() .all(|dep| self.tasks_done.contains_key(dep)) } @@ -162,6 +166,7 @@ impl<'a> Executor<'a> { id: &task_ref, inherit: inherit_hash, depends: &task_deps, + output: &task_def.output, action: &task_def.action, env: &env, } diff --git a/src/resolve.rs b/src/resolve.rs index 5811446..14294d1 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -25,6 +25,7 @@ impl fmt::Display for DepChain { #[derive(Debug)] pub enum Error { TaskNotFound(DepChain), + OutputNotFound(DepChain, String), DependencyCycle(DepChain), } @@ -32,6 +33,7 @@ impl Error { fn extend(&mut self, task: TaskRef) { let tasks = match self { Error::TaskNotFound(ref mut tasks) => tasks, + Error::OutputNotFound(ref mut tasks, _) => tasks, Error::DependencyCycle(ref mut tasks) => tasks, }; tasks.0.push(task); @@ -44,6 +46,9 @@ impl fmt::Display for Error { Error::TaskNotFound(tasks) => { write!(f, "Task not found: {}", tasks) } + Error::OutputNotFound(tasks, output) => { + write!(f, "Output '{}' not found: {}", output, tasks) + } Error::DependencyCycle(tasks) => { write!(f, "Dependency Cycle: {}", tasks) } @@ -79,7 +84,7 @@ impl<'a> Resolver<'a> { .all(|resolved| *resolved == ResolveState::Resolved) } - pub fn add_task(&mut self, task: &TaskRef) -> Vec<Error> { + fn add_task(&mut self, task: &TaskRef, output: Option<&str>) -> Vec<Error> { match self.resolve_state.get(task) { Some(ResolveState::Resolving) => { return vec![Error::DependencyCycle(DepChain(vec![task.clone()]))] @@ -93,17 +98,32 @@ impl<'a> Resolver<'a> { Some(task_def) => task_def, }; + if let Some(task_output) = output { + if !task_def.output.contains_key(task_output) { + return vec![Error::OutputNotFound( + DepChain(vec![task.clone()]), + task_output.to_string(), + )]; + } + } + self.resolve_state .insert(task.clone(), ResolveState::Resolving); let mut ret = Vec::new(); - - for dep in task_def.get_depends() { - let errors = self.add_task(dep); + let mut handle_errors = |errors: Vec<Error>| { for mut error in errors { error.extend(task.clone()); ret.push(error); } + }; + + if let Some(inherit) = &task_def.inherit { + handle_errors(self.add_task(inherit, None)); + } + + for dep in task_def.get_depend_outputs() { + handle_errors(self.add_task(&dep.task, Some(&dep.output))); } if ret.is_empty() { @@ -119,7 +139,7 @@ impl<'a> Resolver<'a> { } pub fn add_goal(&mut self, task: &TaskRef) -> Vec<Error> { - let ret = self.add_task(task); + let ret = self.add_task(task, None); debug_assert!(self.tasks_resolved()); ret } diff --git a/src/types.rs b/src/types.rs index a6a7fee..af0fb92 100644 --- a/src/types.rs +++ b/src/types.rs @@ -104,6 +104,11 @@ fn default_output_name() -> String { "default".to_string() } +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Output { + pub path: Option<String>, +} + #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct OutputRef { #[serde(flatten)] @@ -122,12 +127,14 @@ pub struct Task { pub build_depends: HashSet<OutputRef>, #[serde(default)] pub target_depends: HashSet<OutputRef>, + #[serde(default)] + pub output: HashMap<String, Output>, #[serde(flatten)] pub action: Action, } impl Task { - pub fn get_depends(&self) -> impl Iterator<Item = &TaskRef> { + pub fn get_depend_tasks(&self) -> impl Iterator<Item = &TaskRef> { self.inherit .iter() .chain( @@ -139,6 +146,14 @@ impl Task { .collect::<HashSet<_>>() .into_iter() } + + pub fn get_depend_outputs(&self) -> impl Iterator<Item = &OutputRef> { + self.build_depends + .iter() + .chain(self.target_depends.iter()) + .collect::<HashSet<_>>() + .into_iter() + } } pub type TaskMap = HashMap<String, Task>; |