From e9bf0fc40c0eb7e9d4228b804d62f31b0a136528 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 20 Apr 2024 14:28:05 +0200 Subject: Rename directories to match crate names --- crates/driver/src/context.rs | 533 ------------------------------------------- 1 file changed, 533 deletions(-) delete mode 100644 crates/driver/src/context.rs (limited to 'crates/driver/src/context.rs') diff --git a/crates/driver/src/context.rs b/crates/driver/src/context.rs deleted file mode 100644 index be98813..0000000 --- a/crates/driver/src/context.rs +++ /dev/null @@ -1,533 +0,0 @@ -use std::{ - borrow::Cow, - cmp::Ordering, - collections::{HashMap, HashSet}, - fmt::Display, - hash::Hash, - ops::Index, - rc::Rc, - result, -}; - -use common::{ - error::{self, Contextualizable}, - string_hash::ArchiveHash, - types::TaskID, -}; - -use crate::{ - args::*, - parse::{self, TaskFlags}, - paths, - pin::{self, Pins}, - task::*, -}; - -#[derive(Debug, Clone, Copy)] -pub enum ErrorKind<'a> { - TaskNotFound, - InvalidArgument(&'a str), - InvalidArgRef(&'a str), -} - -#[derive(Debug, Clone, Copy)] -pub struct Error<'a> { - pub task: &'a TaskID, - pub kind: ErrorKind<'a>, -} - -impl<'a> Display for Error<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Error { task, kind } = self; - match kind { - ErrorKind::TaskNotFound => write!(f, "Task '{}' not found", task), - ErrorKind::InvalidArgument(arg) => write!( - f, - "Invalid or missing argument '{}' for task '{}'", - arg, task - ), - ErrorKind::InvalidArgRef(arg) => write!( - f, - "Invalid reference for argument '{}' of task '{}'", - arg, task - ), - } - } -} - -impl<'a> From> for error::Error { - fn from(err: Error) -> Self { - error::Error::new(err) - } -} - -pub type Result<'a, T> = result::Result>; - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct TaskRef<'ctx> { - pub id: &'ctx TaskID, - pub args: Rc, -} - -impl<'ctx> Display for TaskRef<'ctx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if !f.alternate() { - return self.id.fmt(f); - } - - let version_arg = match self.args.get("version") { - Some(Arg::String(s)) => Some(s), - _ => None, - }; - let host_arg = match self.args.get("host") { - Some(Arg::Platform(platform)) => Some(platform), - _ => None, - }; - let target_arg = match self.args.get("target") { - Some(Arg::Platform(platform)) => Some(platform), - _ => None, - }; - - write!(f, "{}", self.id.recipe)?; - if let Some(version) = version_arg { - write!(f, "#{}", version)?; - } - write!(f, "::{}", self.id.task)?; - - if host_arg.is_some() || target_arg.is_some() { - write!(f, "@")?; - } - - if let Some(host) = host_arg { - write!(f, "{}", host.short)?; - } - if let Some(target) = target_arg { - write!(f, ":{}", target.short)?; - } - Ok(()) - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct OutputRef<'ctx> { - pub task: TaskRef<'ctx>, - pub output: &'ctx str, -} - -fn platform_relation(args: &TaskArgs, from: &str, to: &str) -> Option { - let plat_from = match args.get(from)? { - Arg::Platform(plat) => plat, - _ => return None, - }; - let plat_to = match args.get(to)? { - Arg::Platform(plat) => plat, - _ => return None, - }; - - let plat_rel = if plat_from == plat_to { - PlatformRelation { - is_same: true, - sysroot: "".to_string(), - cross_compile: "".to_string(), - } - } else { - PlatformRelation { - is_same: false, - sysroot: paths::TASK_SYSROOT.to_string(), - cross_compile: format!("{}/bin/{}-", plat_from.prefix, plat_to.gnu_triplet), - } - }; - Some(plat_rel) -} - -#[derive(Debug)] -pub struct Context { - platforms: HashMap, - globals: TaskArgs, - tasks: HashMap>, - rootfs: (ArchiveHash, String), -} - -impl Context { - pub fn new(mut tasks: HashMap>, pins: Pins) -> error::Result { - let platforms: HashMap<_, _> = [ - arg( - "build", - Platform { - short: "build".to_string(), - gnu_triplet: "x86_64-linux-gnu".to_string(), - karch: "x86_64".to_string(), - prefix: "/opt/toolchain".to_string(), - }, - ), - arg( - "aarch64", - Platform { - short: "aarch64".to_string(), - gnu_triplet: "aarch64-linux-gnu".to_string(), - karch: "arm64".to_string(), - prefix: "/usr".to_string(), - }, - ), - ] - .into_iter() - .collect(); - - let globals = TaskArgs::from_iter([ - ("build".to_string(), platforms["build"].clone()), - arg("workdir", paths::TASK_WORKDIR.to_string()), - arg("dldir", paths::TASK_DLDIR.to_string()), - arg("destdir", paths::TASK_DESTDIR.to_string()), - arg("sysroot", paths::TASK_SYSROOT.to_string()), - ]); - let (rootfs, rootfs_provides) = - Context::handle_pins(pins).context("Failed to process pin list")?; - - Context::add_rootfs_tasks(&mut tasks, rootfs_provides, &globals) - .context("Failed to determine rootfs-provided tasks from pin list")?; - - Ok(Context { - platforms, - globals, - tasks, - rootfs, - }) - } - - fn handle_pins(pins: Pins) -> error::Result<((ArchiveHash, String), Vec)> { - let mut ret = None; - - for (name, pin) in pins { - if pin.is_rootfs { - if ret.is_some() { - return Err(error::Error::new("Multiple is-rootfs pins")); - } - let hash = pin.hash.context("is-rootfs pin without hash")?; - - ret = Some(((hash, name), pin.provides)); - } - } - - ret.context("No is-rootfs pins") - } - - fn add_rootfs_tasks( - tasks: &mut HashMap>, - provides: Vec, - globals: &TaskArgs, - ) -> error::Result<()> { - let build = globals.get("build").unwrap(); - - for pin::Provides { - recipe, - task, - output, - args, - } in provides - { - let mut task_def = TaskDef::default(); - - if let Some(host) = args.host { - if host != "build" { - return Err(error::Error::new(format!("Invalid host value '{}'", host))); - } - task_def.args.insert("host".to_string(), build.into()); - task_def.arg_match.set("host", Some(build)); - } - - if let Some(target) = args.target { - if target != "build" { - return Err(error::Error::new(format!( - "Invalid target value '{}'", - target - ))); - } - task_def.args.insert("target".to_string(), build.into()); - task_def.arg_match.set("target", Some(build)); - } - - for output_entry in output { - task_def - .output - .insert(output_entry.to_string(), Output::default()); - } - - task_def.priority = i32::MAX; - - tasks - .entry(TaskID { - recipe: recipe.to_string(), - task: task.to_string(), - }) - .or_default() - .push(task_def); - } - - Ok(()) - } - - pub fn get_rootfs(&self) -> &(ArchiveHash, String) { - &self.rootfs - } - - fn match_task(task: &TaskDef, args: &TaskArgs) -> bool { - task.arg_match - .iter() - .all(|(key, value)| args.get(key) == Some(value)) - } - - fn compare_tasks(task1: &TaskDef, task2: &TaskDef) -> Ordering { - task1 - .priority - .cmp(&task2.priority) - .then(deb_version::compare_versions( - task1.meta.version.as_deref().unwrap_or_default(), - task2.meta.version.as_deref().unwrap_or_default(), - )) - } - - fn select_task<'ctx>(tasks: &'ctx [TaskDef], args: &TaskArgs) -> Option<&'ctx TaskDef> { - tasks - .iter() - .filter(|task| Self::match_task(task, args)) - .max_by(|task1, task2| Self::compare_tasks(task1, task2)) - } - - fn get_with_args<'a>(&self, id: &'a TaskID, args: &TaskArgs) -> Result<'a, &TaskDef> { - self.tasks - .get(id) - .and_then(|tasks| Self::select_task(tasks, args)) - .ok_or(Error { - task: id, - kind: ErrorKind::TaskNotFound, - }) - } - - pub fn get<'a>(&self, task: &TaskRef<'a>) -> Result<'a, &TaskDef> { - self.get_with_args(task.id, task.args.as_ref()) - } - - fn task_ref<'ctx>(&'ctx self, id: &'ctx TaskID, args: &TaskArgs) -> Result { - let task_def = self.get_with_args(id, args)?; - - let mut arg_def: HashMap<_, _> = task_def.args.iter().map(|(k, &v)| (k, v)).collect(); - for (key, arg) in &self.globals { - // TODO: Handle conflicts between explicit args and globals - arg_def.insert(key, ArgType::from(arg)); - } - - let mut new_args = TaskArgs::default(); - - for (key, typ) in arg_def { - if let Some(arg) = args.get(key) { - if ArgType::from(arg) == typ { - new_args.set(key, Some(arg)); - continue; - } - } - return Err(Error { - task: id, - kind: ErrorKind::InvalidArgument(key), - }); - } - - let build_to_host = platform_relation(&new_args, "build", "host"); - let host_to_target = platform_relation(&new_args, "host", "target"); - let build_to_target = platform_relation(&new_args, "build", "target"); - - let cross_compile = build_to_host - .as_ref() - .map(|build_to_host| build_to_host.cross_compile.clone()); - - new_args.set("build_to_host", build_to_host); - new_args.set("host_to_target", host_to_target); - new_args.set("build_to_target", build_to_target); - - new_args.set("cross_compile", cross_compile); - - new_args.set("basename", Some(task_def.meta.basename.clone())); - new_args.set("recipename", Some(task_def.meta.recipename.clone())); - new_args.set("recipe", Some(task_def.meta.recipe.clone())); - new_args.set("name", Some(task_def.meta.name.clone())); - new_args.set("version", task_def.meta.version.clone()); - - Ok(TaskRef { - id, - args: Rc::new(new_args), - }) - } - - pub fn parse(&self, s: &str) -> error::Result<(TaskRef, TaskFlags)> { - let (parsed, flags) = parse::task_with_flags(s) - .ok() - .context("Invalid task syntax")?; - - let recipe = parsed.id.recipe.to_string(); - let task = parsed.id.task.to_string(); - - let id = TaskID { recipe, task }; - let (ctx_id, _) = self - .tasks - .get_key_value(&id) - .with_context(|| format!("Task {} not found", id))?; - - let mut args = self.globals.clone(); - - if let Some(host) = parsed.args.host { - let plat = self - .platforms - .get(host) - .with_context(|| format!("Platform '{}' not found", host))?; - args.set("host", Some(plat)); - args.set("target", Some(plat)); - } - if let Some(target) = parsed.args.target { - let plat = self - .platforms - .get(target) - .with_context(|| format!("Platform '{}' not found", target))?; - args.set("target", Some(plat)); - } - - let task_ref = self - .task_ref(ctx_id, &args) - .with_context(|| format!("Failed to instantiate task {}", id))?; - - Ok((task_ref, flags)) - } - - 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.set("host", args.get("build")); - ret.set("target", args.get("host")); - } - - for (to, from) in &mapping.0 { - let value = args.get(from).ok_or(Error { - task, - kind: ErrorKind::InvalidArgRef(to), - })?; - ret.set(to, Some(value.clone())); - } - - Ok(Cow::Owned(ret)) - } - - fn parent_ref<'ctx>(&'ctx self, dep: &'ctx ParentDep, args: &TaskArgs) -> Result { - let mapped_args = Context::map_args(&dep.dep.id, &dep.dep.args, args, false)?; - self.task_ref(&dep.dep.id, mapped_args.as_ref()) - } - - pub fn output_ref<'ctx>( - &'ctx self, - dep: &'ctx OutputDep, - args: &TaskArgs, - build_dep: bool, - ) -> Result> { - let mapped_args = Context::map_args(&dep.dep.id, &dep.dep.args, args, build_dep)?; - Ok(OutputRef { - task: self.task_ref(&dep.dep.id, mapped_args.as_ref())?, - output: &dep.output, - }) - } - - pub fn get_parent_depend<'ctx>( - &'ctx self, - task_ref: &TaskRef<'ctx>, - ) -> Result> { - let task = self.get(task_ref)?; - let Some(parent) = &task.parent else { - return Ok(None); - }; - Some(self.parent_ref(parent, &task_ref.args)).transpose() - } - - fn ancestor_iter<'ctx>( - &'ctx self, - task_ref: &TaskRef<'ctx>, - ) -> impl Iterator> { - struct Iter<'ctx>(&'ctx Context, Option>>); - - impl<'ctx> Iterator for Iter<'ctx> { - type Item = Result<'ctx, TaskRef<'ctx>>; - - fn next(&mut self) -> Option { - let task_ref = match self.1.take()? { - Ok(task_ref) => task_ref, - Err(err) => return Some(Err(err)), - }; - self.1 = self.0.get_parent_depend(&task_ref).transpose(); - Some(Ok(task_ref)) - } - } - - Iter(self, Some(Ok(task_ref.clone()))) - } - - pub fn get_build_depends<'ctx>( - &'ctx self, - task_ref: &TaskRef<'ctx>, - ) -> Result> { - let mut ret = HashSet::new(); - let mut allow_noinherit = true; - - for current in self.ancestor_iter(task_ref) { - let current_ref = current?; - let task = self.get(¤t_ref)?; - let entries = task - .build_depends - .iter() - .filter(|dep| allow_noinherit || !dep.noinherit) - .map(|dep| self.output_ref(dep, ¤t_ref.args, true)) - .collect::>>()?; - ret.extend(entries); - - allow_noinherit = false; - } - - Ok(ret) - } - - pub fn get_host_depends<'ctx>( - &'ctx self, - task_ref: &TaskRef<'ctx>, - ) -> Result> { - let mut ret = HashSet::new(); - let mut allow_noinherit = true; - - for current in self.ancestor_iter(task_ref) { - let current_ref = current?; - let task = self.get(¤t_ref)?; - let entries = task - .depends - .iter() - .filter(|dep| allow_noinherit || !dep.noinherit) - .map(|dep| self.output_ref(dep, ¤t_ref.args, false)) - .collect::>>()?; - ret.extend(entries); - - allow_noinherit = false; - } - - Ok(ret) - } -} - -impl Index<&TaskRef<'_>> for Context { - type Output = TaskDef; - - fn index(&self, index: &TaskRef) -> &TaskDef { - self.get(index).expect("Invalid TaskRef") - } -} -- cgit v1.2.3