Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 738
Alastair Avatar asked Oct 10 '22 04:10

Alastair


2 Answers

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) $$<))
like image 167
Eric Melski Avatar answered Oct 14 '22 03:10

Eric Melski


This should work:

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

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

Another idea:

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

%.c : %.cpp
    ln $< $@  # or cp -p

Another idea is to make GNU make generate the two pattern rules. There are essentally two ways of doing this:

  • write them to makefiles (%-cc.mk or similar) that you include within your actual makefile with GNU make's include statement
  • generate and evaluate them inline with GNU make's $(eval) and $(call) functions

Like most everything else in the C/Unix development toolchain, these techniques are essentially a form of preprocessing, making them easy to understand at the price of being really hard to use (lots of double or triple escaping, really hard to keep track of what is expanded when; debugging can be a royal pain, at least in my experience).

So reserve them for more complicated use cases (of which Stack Overflow lists a few).

like image 30
reinierpost Avatar answered Oct 14 '22 03:10

reinierpost