Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern rule depending on another pattern rule

consider the following fragment of my makefile:

gui_backend: $(BUILDDIR)/gui_backend

$(BUILDDIR)/gui_backend: $(BUILDDIR)/gui_backend.o $(BUILDDIR)/config.pb.o
    $(CXX) $(LDFLAGS) -o $@ $^

$(BUILDDIR)/%.o: $(SRCDIR)/%.cc $(SRCDIR)/%.h | $(BUILDDIR)
    $(CXX) $(CXXFLAGS) -c -o $@ $<

$(SRCDIR)/%.pb.cc: $(PROTODIR)/%.proto
    $(PROTOC) $(PROTOOPTIONS) --cpp_out=$(SRCDIR) $<

now if I call to make gui_backend, I get

make: *** No rule to make target `build/config.pb.o', needed by `build/gui_backend'.

Why doesn't make pick up on the $(BUILDDIR)/%.o pattern here? If I state things explicitly by adding the rule

$(BUILDDIR)/config.pb.o: $(SRCDIR)/config.pb.cc $(SRCDIR)/config.pb.h | $(BUILDDIR)
    $(CXX) $(CXXFLAGS) -c -o $@ $<

it seems to work. However, I would like to keep the makefile as concise as possible.

Running make with -d gives me the following (complete output here):

Considering target file `build/config.pb.o'.
       File `build/config.pb.o' does not exist.
       Looking for an implicit rule for `build/config.pb.o'.
       Trying pattern rule with stem `config.pb'.
       Trying implicit prerequisite `src/config.pb.cc'.
       Trying pattern rule with stem `config.pb'.
       Trying implicit prerequisite `build/config.pb.c'.
       Trying pattern rule with stem `config.pb'.
       Trying implicit prerequisite `build/config.pb.cc'.
       Trying pattern rule with stem `config.pb'.
       [...]
       Trying implicit prerequisite `build/SCCS/s.config.pb.o'.
       Trying pattern rule with stem `config.pb'.
       Trying implicit prerequisite `src/config.pb.cc'.
       Looking for a rule with intermediate file `src/config.pb.cc'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem `config'.
        Trying implicit prerequisite `src/proto/config.proto'.
        [...]

I'm running GNU Make 3.81, btw.

Also, I just noticed that if I run make src/config.pb.cc and then make build/config.pb.o manually, it works.

Why doesn't this work?

like image 690
DeX3 Avatar asked Jan 24 '26 11:01

DeX3


1 Answers

Your example looks correct to me. The only difference between the pattern rule and the explicit rule I see is that the explicit rule doesn't have the order-only prerequisite. What version of GNU make are you running? Are you sure it supports order-only prerequisites? If it doesn't then the pattern rule will not match as it's trying to find a way to build a target like | and can't.

Whenever you hit issues like this the simplest thing to do is run make -d. The output is voluminous but it is also very enlightening: find the section where it's trying to build config.pb.o and see what patterns it's trying and why it decides to give up on that one.

like image 192
MadScientist Avatar answered Jan 26 '26 13:01

MadScientist