Reputation: 5387
I have a makefile like this:
EXT = .cc
BLD = .build
all: bin/analyses/test
bin/analyses/test: $(BLD)/object.o
.SECONDEXPANSION:
$(DEPS): $(BLD)/%.d: src/%$(EXT) | $(BLD)/$$(dir %)
$(CXX) $(CPPFLAGS) -MM -MT '$(@:.d=.o)' $< -MF $@
$(BLD)/%.o: | $(BLD)
$(CXX) $(CXXFLAGS) -c $(filter %$(EXT),$^) -o $@
bin/%: $(BLD)/%.o | $$(dir bin/%)
$(CXX) $(LDFLAGS) $(filter %.o,$^) -o $@ $(LDLIBS)
bin/%/ $(BLD)/%/:
mkdir -p $@
If line 6 looks the way it is, then everything works. Both bin/analyses/test:
and bin/%:
rules are used. But if I change line 6 to
bin/analyses/%: $(BLD)/object.o
only the bin/%:
rule gets picked up.
How can I make multiple pattern rules match for the same target?
Upvotes: 0
Views: 165
Reputation: 99084
First, Make sometimes removes trailing slashes from targets, which can cause some confusion. In this case it takes your rule bin/%/ $(BLD)/%/: ...
, which you clearly intended for directories, and uses it for files, at least sometimes. It is easy enough to do without an explicit rule for directories, by using mkdir -p
in other rules.
Second, Make doesn't combine pattern rules the way it does ordinary rules. It finds one pattern rule and uses that. In a relatively simple case like this, we can write a rule that will do what we want:
all: bin/analyses/test
$(BLD)/%.o:
mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) -c $^ -o $@
bin/analyses/%: $(BLD)/analyses/%.o $(BLD)/object.o
mkdir -p $(dir $@)
$(CXX) $(LDFLAGS) $^ -o $@ $(LDLIBS)
bin/%: $(BLD)/%.o
mkdir -p $(dir $@)
$(CXX) $(LDFLAGS) $^ -o $@ $(LDLIBS)
(There is some obvious redundancy in those last two rules which I don't see how to iron out without making the makefile less readable, but it works as intended.)
Upvotes: 1