From 2254b27cbeabd7f9e656a79afc7e0343d72f0685 Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Sun, 17 Nov 2024 18:20:20 -0700 Subject: propagate command line macros through MAKEFLAGS for recursive calls --- README.md | 4 ++++ src/args.rs | 51 ++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index fdae87c..933fe6c 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,10 @@ list of features that are needed for version 1.0: ## changelog +### next - TBD + +- propagate command line macros through `MAKEFLAGS` for recursive calls + ### v0.8.0 - 2024-11-15 - license is worse diff --git a/src/args.rs b/src/args.rs index f5097f8..f0892cb 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,6 +1,7 @@ use std::env; use std::ffi::OsString; use std::iter; +use std::ops::AddAssign; use std::path::PathBuf; use clap::Parser; @@ -158,14 +159,13 @@ impl Args { // POSIX spec says "Any options specified in the MAKEFLAGS environment variable // shall be evaluated before any options specified on the make utility command // line." - // TODO allow macro definitions in MAKEFLAGS // POSIX says we have to accept // > The characters are option letters without the leading // > characters or separation used on a make utility command line. let makeflags_given = !env_makeflags.is_empty(); let makeflags_spaces = env_makeflags.contains(' '); let makeflags_leading_dash = env_makeflags.starts_with('-'); - let makeflags_has_equals = env_makeflags.starts_with('='); + let makeflags_has_equals = env_makeflags.contains('='); let makeflags_obviously_full = makeflags_spaces || makeflags_leading_dash || makeflags_has_equals; let env_makeflags = if makeflags_given && !makeflags_obviously_full { @@ -211,38 +211,58 @@ impl Args { } pub fn makeflags(&self) -> String { - let mut result = String::new(); + let mut flags = String::new(); if self.environment_overrides { - result.push('e'); + flags.push('e'); } if self.ignore_errors { - result.push('i'); + flags.push('i'); } if self.keep_going { - result.push('k'); + flags.push('k'); } if self.dry_run { - result.push('n'); + flags.push('n'); } if self.print_everything { - result.push('p'); + flags.push('p'); } if self.question { - result.push('q'); + flags.push('q'); } if self.no_builtin_rules { - result.push('r'); + flags.push('r'); } if self.no_keep_going { - result.push('S'); + flags.push('S'); } if self.silent { - result.push('s'); + flags.push('s'); } if self.touch { - result.push('t'); + flags.push('t'); } // TODO decide whether or not print_directory should go here too + + let macros = self + .targets_or_macros + .iter() + .map(|x| x.as_ref()) + .filter(|x: &&str| x.contains('=')) + .collect::>() + .join(" "); + + let mut result = String::new(); + if !flags.is_empty() && !macros.is_empty() { + result.push('-'); + } + result.add_assign(&flags); + // TODO consider -- to separate flags from macros - GNU does it but it would require + // gnarly splicing to not override recursive macros + if !flags.is_empty() && !macros.is_empty() { + result += " "; + } + result.add_assign(¯os); result } } @@ -477,7 +497,7 @@ mod test { #[test] fn nightmare() { - let makeflags = "-nrs -k foo=bar"; + let makeflags = "-nrs -k -- foo=bar"; let args = "makers -eipqtSf foo -f bruh bar baz=yeet"; let args = Args::from_given_args_and_given_env( args.split_whitespace().map(OsString::from), @@ -503,8 +523,9 @@ mod test { print_directory: false, #[cfg(feature = "full")] no_print_directory: false, - targets_or_macros: vec!["foo=bar".into(), "bar".into(), "baz=yeet".into()], + targets_or_macros: vec!["bar".into(), "baz=yeet".into(), "foo=bar".into()], } ); + assert_eq!(args.makeflags(), "-einpqrSst -- baz=yeet foo=bar"); } } -- cgit v1.2.3