aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2021-04-04 14:07:14 -0600
committerMelody Horn <melody@boringcactus.com>2021-04-04 14:07:14 -0600
commitf6117f5a1b8e5aa426b959c0fe5571de626070dc (patch)
treead8abed39be159174988e670113162461d881f24
parentcdffe0c58f939490fdfcef56843f8fab4433988b (diff)
downloadmakers-f6117f5a1b8e5aa426b959c0fe5571de626070dc.tar.gz
makers-f6117f5a1b8e5aa426b959c0fe5571de626070dc.zip
keep track of pattern stem to correctly populate `$*`
-rw-r--r--src/makefile/inference_rules.rs2
-rw-r--r--src/makefile/input.rs1
-rw-r--r--src/makefile/mod.rs27
-rw-r--r--src/makefile/target.rs1
4 files changed, 21 insertions, 10 deletions
diff --git a/src/makefile/inference_rules.rs b/src/makefile/inference_rules.rs
index 86e5598..57756c9 100644
--- a/src/makefile/inference_rules.rs
+++ b/src/makefile/inference_rules.rs
@@ -23,7 +23,7 @@ impl InferenceRule {
}
}
- fn first_match<'s, 't: 's>(&'s self, target_name: &'t str) -> Result<Option<Captures<'t>>> {
+ pub fn first_match<'s, 't: 's>(&'s self, target_name: &'t str) -> Result<Option<Captures<'t>>> {
self.products
.iter()
.map(|pattern| r#match(pattern, target_name))
diff --git a/src/makefile/input.rs b/src/makefile/input.rs
index 6ee5392..b02cdb6 100644
--- a/src/makefile/input.rs
+++ b/src/makefile/input.rs
@@ -446,6 +446,7 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> {
name: target.into(),
prerequisites: prerequisites.clone(),
commands: commands.clone(),
+ stem: None,
already_updated: Cell::new(false),
};
self.targets.insert(target.into(), new_target);
diff --git a/src/makefile/mod.rs b/src/makefile/mod.rs
index ce30623..cda5559 100644
--- a/src/makefile/mod.rs
+++ b/src/makefile/mod.rs
@@ -180,6 +180,9 @@ impl<'a> Makefile<'a> {
name: name.into(),
prerequisites: prereqs,
commands: rule.commands.clone(),
+ stem: rule
+ .first_match(name)?
+ .and_then(|x| x.get(0).map(|x| x.as_str().to_owned())),
already_updated: Cell::new(false),
});
break;
@@ -231,6 +234,7 @@ impl<'a> Makefile<'a> {
name: name.into(),
prerequisites: vec![],
commands,
+ stem: None,
already_updated: Cell::new(false),
});
} else {
@@ -240,6 +244,7 @@ impl<'a> Makefile<'a> {
name: name.into(),
prerequisites: vec![],
commands: vec![],
+ stem: None,
already_updated: Cell::new(true),
});
}
@@ -269,15 +274,15 @@ impl<'a> Makefile<'a> {
fn expand_macros(&self, text: &TokenString, target: Option<&Target>) -> Result<String> {
let target = target.cloned();
- let lookup_internal = move |name: &str| {
+ let lookup_internal = move |macro_name: &str| {
let target = target
.as_ref()
.ok_or_else(|| eyre!("internal macro but no current target!"))?;
- let macro_pieces = if name.starts_with('@') {
+ let macro_pieces = if macro_name.starts_with('@') {
// The $@ shall evaluate to the full target name of the
// current target.
vec![target.name.clone()]
- } else if name.starts_with('?') {
+ } else if macro_name.starts_with('?') {
// The $? macro shall evaluate to the list of prerequisites
// that are newer than the current target.
target
@@ -291,22 +296,25 @@ impl<'a> Makefile<'a> {
})
.cloned()
.collect()
- } else if name.starts_with('<') {
+ } else if macro_name.starts_with('<') {
// In an inference rule, the $< macro shall evaluate to the
// filename whose existence allowed the inference rule to be
// chosen for the target. In the .DEFAULT rule, the $< macro
// shall evaluate to the current target name.
// TODO make that actually be the case (rn exists_but_inferring_anyway might fuck that up)
vec![target.prerequisites.get(0).cloned().unwrap_or_default()]
- } else if name.starts_with('*') {
+ } else if macro_name.starts_with('*') {
// The $* macro shall evaluate to the current target name with
- // its suffix deleted.
- vec![Path::new(name).with_extension("").to_string_lossy().into()]
+ // its suffix deleted. (GNUism: the match stem)
+ vec![Path::new(target.stem.as_ref().unwrap_or(&target.name))
+ .with_extension("")
+ .to_string_lossy()
+ .into()]
} else {
unreachable!()
};
- let macro_pieces = if name.ends_with('D') {
+ let macro_pieces = if macro_name.ends_with('D') {
macro_pieces
.into_iter()
.map(|x| {
@@ -316,7 +324,7 @@ impl<'a> Makefile<'a> {
.map(|x| x.to_string_lossy().into())
})
.collect::<Result<_, _>>()?
- } else if name.ends_with('F') {
+ } else if macro_name.ends_with('F') {
macro_pieces
.into_iter()
.map(|x| {
@@ -433,6 +441,7 @@ fn builtin_targets() -> Vec<Target> {
.map(String::from)
.collect(),
commands: vec![],
+ stem: None,
already_updated: Cell::new(false),
}]
}
diff --git a/src/makefile/target.rs b/src/makefile/target.rs
index 1c382d0..506bde8 100644
--- a/src/makefile/target.rs
+++ b/src/makefile/target.rs
@@ -14,6 +14,7 @@ pub struct Target {
pub name: String,
pub prerequisites: Vec<String>,
pub commands: Vec<CommandLine>,
+ pub stem: Option<String>,
pub already_updated: Cell<bool>,
}