aboutsummaryrefslogtreecommitdiff
path: root/src/makefile/target.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/makefile/target.rs')
-rw-r--r--src/makefile/target.rs81
1 files changed, 79 insertions, 2 deletions
diff --git a/src/makefile/target.rs b/src/makefile/target.rs
index 506bde8..5de280d 100644
--- a/src/makefile/target.rs
+++ b/src/makefile/target.rs
@@ -1,6 +1,8 @@
-use std::cell::Cell;
+use std::cell::{Cell, RefCell};
+use std::collections::HashMap;
use std::fmt;
use std::fs::metadata;
+use std::rc::Rc;
use std::time::SystemTime;
use eyre::{Result, WrapErr};
@@ -19,6 +21,17 @@ pub struct Target {
}
impl Target {
+ pub fn extend(&mut self, other: Target) {
+ assert_eq!(&self.name, &other.name);
+ self.prerequisites.extend(other.prerequisites);
+ assert!(self.commands.is_empty() || other.commands.is_empty());
+ self.commands.extend(other.commands);
+ assert!(self.stem.is_none() || other.stem.is_none());
+ self.stem = self.stem.take().or(other.stem);
+ let already_updated = self.already_updated.get() || other.already_updated.get();
+ self.already_updated.set(already_updated);
+ }
+
fn modified_time(&self) -> Option<SystemTime> {
metadata(&self.name)
.and_then(|metadata| metadata.modified())
@@ -55,7 +68,7 @@ impl Target {
.unwrap_or(false)
});
log::trace!(
- "{:>50} exists: {}, newer than dependencies: {}",
+ "{:} exists: {}, newer than dependencies: {}",
self.name,
exists,
newer_than_all_dependencies
@@ -64,6 +77,7 @@ impl Target {
}
pub fn update(&self, file: &Makefile) -> Result<()> {
+ log::info!("{}: {:?}", &self.name, &self.prerequisites);
for prereq in &self.prerequisites {
file.update_target(prereq)
.wrap_err_with(|| format!("as a dependency for target {}", self.name))?;
@@ -101,3 +115,66 @@ impl fmt::Display for Target {
Ok(())
}
}
+
+// for targets that won't change out from under us (don't need refcelling)
+#[derive(Clone, Default)]
+pub struct StaticTargetSet {
+ data: HashMap<String, Target>,
+}
+
+impl StaticTargetSet {
+ pub fn get(&self, name: &str) -> Option<&Target> {
+ self.data.get(name)
+ }
+
+ pub fn put(&mut self, target: Target) {
+ if target.name == ".SUFFIXES" && target.prerequisites.is_empty() {
+ self.data.remove(&target.name);
+ }
+ if let Some(existing_target) = self.data.get_mut(&target.name) {
+ existing_target.extend(target);
+ } else {
+ self.data.insert(target.name.clone(), target);
+ }
+ }
+}
+
+impl Into<HashMap<String, Target>> for StaticTargetSet {
+ fn into(self) -> HashMap<String, Target> {
+ self.data
+ }
+}
+
+// for targets that might become updated and so need refcelling
+#[derive(Clone, Default)]
+pub struct DynamicTargetSet {
+ data: HashMap<String, Rc<RefCell<Target>>>,
+}
+
+impl DynamicTargetSet {
+ pub fn get(&self, name: &str) -> Option<Rc<RefCell<Target>>> {
+ self.data.get(name).map(|x| Rc::clone(x))
+ }
+
+ pub fn put(&mut self, target: Target) {
+ if let Some(existing_target) = self.data.get_mut(&target.name) {
+ existing_target.borrow_mut().extend(target);
+ } else {
+ self.data
+ .insert(target.name.clone(), Rc::new(RefCell::new(target)));
+ }
+ }
+
+ pub fn has(&self, name: &str) -> bool {
+ self.data.contains_key(name)
+ }
+}
+
+impl fmt::Display for DynamicTargetSet {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ for target in self.data.values() {
+ writeln!(f, "{}", target.borrow())?;
+ }
+ Ok(())
+ }
+}