diff options
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | src/makefile/macro.rs | 4 | ||||
-rw-r--r-- | src/makefile/mod.rs | 19 | ||||
-rw-r--r-- | src/makefile/token.rs | 37 |
5 files changed, 51 insertions, 18 deletions
@@ -10,10 +10,14 @@ license-file = "LICENSE.md" keywords = ["build", "make"] categories = ["development-tools"] +[features] +default = ['full'] +full = ['dirs', 'glob'] + [dependencies] -dirs = "3.0.1" +dirs = { version = "3.0.1", optional = true } eyre = "0.6.5" -glob = "0.3.0" +glob = { version = "0.3.0", optional = true } jane-eyre = "0.3.0" lazy_static = "1.4.0" nom = "6.1.2" @@ -11,6 +11,7 @@ Not explicitly aiming for full support for [every GNU make feature](https://www. - library handling not implemented - some POSIX-specified features are pending (search `TODO` for a list) - builtin macro `MAKE` is defined as `makers` +- specifying the `.POSIX` special target doesn't opt out of extensions (but you can install with `--no-default-features` to get only POSIX behavior) ## status diff --git a/src/makefile/macro.rs b/src/makefile/macro.rs index e760282..bb4a72d 100644 --- a/src/makefile/macro.rs +++ b/src/makefile/macro.rs @@ -5,6 +5,7 @@ use std::fmt; use eyre::{bail, Result, WrapErr}; use regex::Regex; +#[cfg(feature = "full")] use super::functions; use super::token::{Token, TokenString}; @@ -71,6 +72,7 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> { self.data.insert(name, (source, text)); } + #[cfg(feature = "full")] pub fn is_defined(&self, name: &str) -> bool { self.data.contains_key(name) } @@ -113,6 +115,7 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> { }; result.push_str(¯o_value); } + #[cfg(feature = "full")] Token::FunctionCall { name, args } => { result.push_str(&functions::expand_call(name, args, self)?); } @@ -129,6 +132,7 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> { } } + #[cfg(feature = "full")] pub fn with_overlay<'s>(&'s self) -> Set<'s, 'lookup> { Set { parent: Some(self), diff --git a/src/makefile/mod.rs b/src/makefile/mod.rs index 5be18e0..9038150 100644 --- a/src/makefile/mod.rs +++ b/src/makefile/mod.rs @@ -15,15 +15,19 @@ use regex::Regex; use crate::args::Args; mod command_line; +#[cfg(feature = "full")] mod conditional; +#[cfg(feature = "full")] mod functions; mod inference_rules; mod r#macro; +#[cfg(feature = "full")] mod pattern; mod target; mod token; use command_line::CommandLine; +#[cfg(feature = "full")] use conditional::{Line as ConditionalLine, State as ConditionalState}; use inference_rules::InferenceRule; use r#macro::{Set as MacroSet, Source as MacroSource}; @@ -154,6 +158,7 @@ impl<'a> Makefile<'a> { ) }) .peekable(); + #[cfg(feature = "full")] let mut conditional_stack: Vec<ConditionalState> = vec![]; while let Some((line_number, line)) = lines_iter.next() { let mut line = line?; @@ -174,6 +179,7 @@ impl<'a> Makefile<'a> { let line = COMMENT.replace(&line, "").into_owned(); // skip lines if we need to + #[cfg(feature = "full")] if conditional_stack .last() .map_or(false, ConditionalState::skipping) @@ -192,16 +198,20 @@ impl<'a> Makefile<'a> { for field in fields { self.and_read_file(field)?; } - } else if let Some(line) = - ConditionalLine::from(&line, |t| self.expand_macros(t, None))? - { + continue; + } + + #[cfg(feature = "full")] + if let Some(line) = ConditionalLine::from(&line, |t| self.expand_macros(t, None))? { line.action( conditional_stack.last(), |name| self.macros.is_defined(name), |t| self.expand_macros(t, None), )? .apply_to(&mut conditional_stack); - } else if line.trim().is_empty() { + continue; + } + if line.trim().is_empty() { // handle blank lines continue; } else { @@ -711,6 +721,7 @@ mod test { } } + #[cfg(feature = "full")] #[test] fn basic_conditionals() -> R { let file = " diff --git a/src/makefile/token.rs b/src/makefile/token.rs index 60cffe0..8bd0179 100644 --- a/src/makefile/token.rs +++ b/src/makefile/token.rs @@ -5,13 +5,15 @@ use eyre::WrapErr; use nom::{ branch::alt, bytes::complete::{tag, take_till1, take_while1}, - character::complete::{anychar, space1}, + character::complete::anychar, combinator::{all_consuming, map, opt, verify}, error::{context, convert_error, ContextError, ParseError, VerboseError}, - multi::{many1, separated_list1}, + multi::many1, sequence::{delimited, pair, preceded, separated_pair}, Finish, IResult, }; +#[cfg(feature = "full")] +use nom::{character::complete::space1, multi::separated_list1}; trait Err<'a>: 'a + ParseError<&'a str> + ContextError<&'a str> {} impl<'a, T: 'a + ParseError<&'a str> + ContextError<&'a str>> Err<'a> for T {} @@ -25,6 +27,7 @@ impl TokenString { Self(vec![Token::Text(text.into())]) } + #[cfg(feature = "full")] pub fn r#macro(name: impl Into<String>) -> Self { Self(vec![Token::MacroExpansion { name: name.into(), @@ -60,6 +63,7 @@ impl TokenString { None } + #[cfg(feature = "full")] pub fn starts_with(&self, pattern: &str) -> bool { match self.0.first() { Some(Token::Text(t)) => t.starts_with(pattern), @@ -74,6 +78,7 @@ impl TokenString { } } + #[cfg(feature = "full")] pub fn strip_prefix(&mut self, suffix: &str) { if let Some(Token::Text(t)) = self.0.first_mut() { if let Some(x) = t.strip_prefix(suffix) { @@ -100,6 +105,7 @@ impl TokenString { } } + #[cfg(feature = "full")] pub fn trim_end(&mut self) { if let Some(Token::Text(t)) = self.0.last_mut() { *t = t.trim_end().into(); @@ -123,6 +129,7 @@ pub enum Token { name: String, replacement: Option<(TokenString, TokenString)>, }, + #[cfg(feature = "full")] FunctionCall { name: String, args: Vec<TokenString>, @@ -141,6 +148,7 @@ impl fmt::Display for Token { name, replacement: Some((r1, r2)), } => write!(f, "$({}:{}={})", name, r1, r2), + #[cfg(feature = "full")] Self::FunctionCall { name, args } => write!( f, "$({} {})", @@ -183,6 +191,7 @@ fn macro_expansion_body<'a, E: Err<'a>>( ) } +#[cfg(feature = "full")] fn function_call_body<'a, E: Err<'a>>( end: char, ) -> impl FnMut(&'a str) -> IResult<&'a str, Token, E> { @@ -202,20 +211,22 @@ fn function_call_body<'a, E: Err<'a>>( ) } +#[cfg(feature = "full")] +fn macro_body<'a, E: Err<'a>>(end: char) -> impl FnMut(&'a str) -> IResult<&'a str, Token, E> { + alt((function_call_body(end), macro_expansion_body(end))) +} + +#[cfg(not(feature = "full"))] +fn macro_body<'a, E: Err<'a>>(end: char) -> impl FnMut(&'a str) -> IResult<&'a str, Token, E> { + macro_expansion_body(end) +} + fn parens_macro_expansion<'a, E: Err<'a>>(input: &'a str) -> IResult<&'a str, Token, E> { - delimited( - tag("$("), - alt((function_call_body(')'), macro_expansion_body(')'))), - tag(")"), - )(input) + delimited(tag("$("), macro_body(')'), tag(")"))(input) } fn braces_macro_expansion<'a, E: Err<'a>>(input: &'a str) -> IResult<&'a str, Token, E> { - delimited( - tag("${"), - alt((function_call_body('}'), macro_expansion_body('}'))), - tag("}"), - )(input) + delimited(tag("${"), macro_body('}'), tag("}"))(input) } fn tiny_macro_expansion<'a, E: Err<'a>>(input: &'a str) -> IResult<&'a str, Token, E> { @@ -328,6 +339,7 @@ mod test { } } + #[cfg(feature = "full")] fn token_function_call(name: impl Into<String>, args: Vec<impl Into<TokenString>>) -> Token { Token::FunctionCall { name: name.into(), @@ -430,6 +442,7 @@ mod test { Ok(()) } + #[cfg(feature = "full")] #[test] fn function_hell() -> R { let text = "$(foo bar, $(baz))"; |