Reputation: 428
I have a set of files of the form [name].c, some of which #include an associated [name].h file. I want a makefile target that re-builds [name].o if [name].c or [name].h are modified. I tried:
$(OBJDIR)/%.o : $(SRCDIR)/%.c $(SRCDIR)/%.h
#Implementation of target omitted
However, for the .c files that don't have associated .h files, make complains on the above rule. I tried:
$(OBJDIR)/%.o : $(SRCDIR)/%.c $(wildcard $(SRCDIR)/%.h)
#Implementation of target omitted
This builds, but modifying the .h files does not trigger a rebuild. Is there some reason I can't use % in this way?
Note: I'm trying to avoid a solution that uses makedeps.pl or makefile generation (because I am not actually working with .c or .h files).
Upvotes: 0
Views: 354
Reputation: 101081
Your attempt won't work because variables and functions that appear as part of target or prerequisite lists are expanded immediately, when the makefile is read in. At that point, obviously, there's no way to know what %
might expand to later, when make is trying to figure out how to build targets, so it's actually expanding the literal string <srcdir>/%.h
of which presumably there is none.
One answer is to move the prerequisites to a separate rule:
$(OBJDIR)/foo.o : $(wildcard $(SRCDIR)/foo.h)
$(OBJDIR)/bar.o : $(wildcard $(SRCDIR)/bar.h)
$(OBJDIR)/baz.o : $(wildcard $(SRCDIR)/baz.h)
If you don't want to have to write this out, you can use eval to do it for you: suppose you have a variable listing the object files:
OBJECTS = foo.o bar.o baz.o
$(foreach O,$(OBJECTS),$(eval $(OBJDIR)/$O : $(wildcard $(SRCDIR)/$(O:.o=.h))))
(that might not be exactly right).
Alternatively, you can enable .SECONDEXPANSION
and write:
.SECONDEXPANSION:
$(OBJDIR)/%.o : $(SRCDIR)/%.c $$(wildcard $(SRCDIR)/%.h)
#Implementation of target omitted
(note the extra $
escaping the wildcard function).
Upvotes: 1