From 31a35ac86e41a698a5eafcc0b4cbfa64e2066c39 Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Sat, 3 Apr 2021 11:29:04 -0600 Subject: correctly handle conditional lines inside rule body --- src/makefile/mod.rs | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 1 deletion(-) (limited to 'src/makefile/mod.rs') diff --git a/src/makefile/mod.rs b/src/makefile/mod.rs index 7904d08..88a3abb 100644 --- a/src/makefile/mod.rs +++ b/src/makefile/mod.rs @@ -22,9 +22,10 @@ mod pattern; mod target; mod token; +use command_line::CommandLine; use inference_rules::InferenceRule; pub use input::MakefileReader; -use r#macro::Set as MacroSet; +use r#macro::{Set as MacroSet, Source as MacroSource}; use target::Target; use token::TokenString; @@ -38,6 +39,56 @@ pub struct Makefile<'a> { } impl<'a> Makefile<'a> { + pub fn new(args: &'a Args) -> Self { + let mut inference_rules = vec![]; + let mut macros = MacroSet::new(); + let mut targets = HashMap::new(); + let first_non_special_target = None; + + if !args.no_builtin_rules { + inference_rules.extend(builtin_inference_rules()); + macros.add_builtins(); + targets.extend( + builtin_targets() + .into_iter() + .map(|t| (t.name.clone(), Rc::new(RefCell::new(t)))), + ); + } + + macros.add_env(); + + for r#macro in args.macros() { + if let [name, value] = *r#macro.splitn(2, '=').collect::>() { + macros.set( + name.into(), + MacroSource::CommandLineOrMakeflags, + TokenString::text(value), + ); + } + } + + Makefile { + inference_rules, + macros, + targets: RefCell::new(targets), + first_non_special_target, + args, + } + } + + pub fn extend(&mut self, new: MakefileReader) { + self.inference_rules.extend(new.inference_rules); + self.macros.extend(new.macros); + self.targets.borrow_mut().extend( + new.targets + .into_iter() + .map(|(k, v)| (k, Rc::new(RefCell::new(v)))), + ); + if self.first_non_special_target.is_none() { + self.first_non_special_target = new.first_non_special_target; + } + } + fn special_target_has_prereq(&self, target: &str, name: &str) -> bool { let targets = self.targets.borrow(); match targets.get(target) { @@ -247,3 +298,79 @@ impl fmt::Display for Makefile<'_> { Ok(()) } } + +fn builtin_inference_rules() -> Vec { + // This is a terrible idea. + macro_rules! prepend_dot { + ($x:tt) => { + concat!(".", stringify!($x)) + }; + () => { + "" + }; + } + + macro_rules! make { + {$(.$first:tt$(.$second:tt)?: + $($cmd:literal)+)+} => { + vec![$( + InferenceRule { + product: prepend_dot!($($second)?).into(), + prereq: concat!(".", stringify!($first)).into(), + commands: vec![$(CommandLine::from($cmd.parse().unwrap())),+], + } + ),+] + }; + } + + make! { + .c: + "$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<" + .f: + "$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<" + .sh: + "cp $< $@" + "chmod a+x $@" + + .c.o: + "$(CC) $(CFLAGS) -c $<" + .f.o: + "$(FC) $(FFLAGS) -c $<" + .y.o: + "$(YACC) $(YFLAGS) $<" + "$(CC) $(CFLAGS) -c y.tab.c" + "rm -f y.tab.c" + "mv y.tab.o $@" + .l.o: + "$(LEX) $(LFLAGS) $<" + "$(CC) $(CFLAGS) -c lex.yy.c" + "rm -f lex.yy.c" + "mv lex.yy.o $@" + .y.c: + "$(YACC) $(YFLAGS) $<" + "mv y.tab.c $@" + .l.c: + "$(LEX) $(LFLAGS) $<" + "mv lex.yy.c $@" + .c.a: + "$(CC) -c $(CFLAGS) $<" + "$(AR) $(ARFLAGS) $@ $*.o" + "rm -f $*.o" + .f.a: + "$(FC) -c $(FFLAGS) $<" + "$(AR) $(ARFLAGS) $@ $*.o" + "rm -f $*.o" + } +} +fn builtin_targets() -> Vec { + // even i'm not going to do that just for this + vec![Target { + name: ".SUFFIXES".into(), + prerequisites: vec![".o", ".c", ".y", ".l", ".a", ".sh", ".f"] + .into_iter() + .map(String::from) + .collect(), + commands: vec![], + already_updated: Cell::new(false), + }] +} -- cgit v1.2.3