Search code examples
makefilerulestargets

Avoid duplicating GNU Make rules


I've been writing a Makefile that performs some dependency generation and I've found myself having to duplicate rules because the (legacy) codebase contains a mixture of .cpp and .cc files. It seems a bit unsightly. Is there anyway to specify that the prerequisites of a target can be either .cpp or .cc files?

So rather than having:

%.d : %.cpp
    $(CPP) -MM $(CPPFLAGS) $<

%.d : %.cc
    $(CPP) -MM $(CPPFLAGS) $<

Create something without the duplication like:

%.d : %.(cpp | cc)
    $(CPP) -MM $(CPPFLAGS) $<

Or is this enforced redundancy just an unfortunate element of GNU Make's design?


Solution

  • First option, use a variable to define the rule body once, and reuse it as needed:

    DEPGEN=$(CPP) -MM $(CPPFLAGS) $<
    %.d: %.cpp ; $(DEPGEN)
    %.d: %.cc  ; $(DEPGEN)
    

    Second option, use $(eval) to dynamically generate the rules:

    $(foreach src,cpp cc,$(eval %.d: %.$(src) ; $$(CPP) -MM $$(CPPFLAGS) $$<))