7

I have a c++ project with various extensions for the source files (.cpp, .c, .cc) and various extensions for the header files (.hpp, .h, .hh). The source files are located in a directory called SRC, and the header files are predictably in a directory called INC.

I would like to compile the source with a rule like

vpath %.c $(SRC)

%.o: %.c
    $(COMPILER) $(FLAGS) $< $(INCFLAG)$(INC)

This of course works if I know the source file will be of the form %.c, but in the case of multiple possible file extensions, I would need to build a similar rule for %.cpp and %.cc as well. Of course three rules isn't a big deal to write, but it would be nice to be able to use this makefile as a drag and drop for any project, even in a different language, without having to re-write the rules.

So how can I write a rule (or some other construct that accomplishes the same goal) that works like:

SRC_EXT = cpp c cc
vpath %.$(SRC_EXT) $(SRC)

%.o: %.$(SRC_EXT)
    $(COMPILER) $(FLAGS) $< $(INCFLAG)$(INC)

Thanks for your help.

jaco0646
  • 15,303
  • 7
  • 59
  • 83
user487100
  • 918
  • 1
  • 11
  • 22

1 Answers1

4

You can't in standard POSIX make. However since you mention vpath I'll assume you're using GNU make. If you have a sufficiently new version (3.81 or newer), you can do this easily enough with call and eval:

SRC_EXT = cpp c cc

define compile_rule
%.o : %.$1
        $$(COMPILER) $$(FLAGS) $$< $$(INCFLAG)$$(INC)
endef    
$(foreach EXT,$(SRC_EXT),$(eval $(call compile_rule,$(EXT))))

If you don't have sufficiently new GNU make, or would prefer an alternate solution, you can do the same thing with generated makefiles.

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • aha! great! I was wondering how to call a compile rule, but how does the foreach get called in the first place? Is it just sitting there in the file, as in it gets called right after you set the SRC_EXT variable? Will this force the recompilation of all the source files even if the .o's are up to date? – user487100 Jan 24 '12 at 15:29
  • 1
    Makefile parsing is all about expanding things. Whenever make encounters a variable or function in an "immediate context" (see "How Make Reads a Makefile" in the GNU make manual), it will expand it. That can involve many steps of course. Once the expansion is complete, whatever is left is parsed as a makefile. The eval function is extra-special. Basically this foreach loop is expanded and parsed by make when it reads in the makefile, and it defines rules the same way as if you'd written them out. So it behaves like any other make rule (won't force recompilation). – MadScientist Jan 25 '12 at 01:13
  • I don't get what `EXT` means, can someone explain? Edit: Nevermind, it seems like it's the `i` in a `for` loop. – ihsoy ih Dec 20 '12 at 02:41