3

考虑我的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) $<

现在如果我打电话给make gui_backend,我得到

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

为什么不对$(BUILDDIR)/%.o这里的模式做出选择?如果我通过添加规则明确说明

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

它似乎工作。但是,我想使 makefile 尽可能简洁。

运行 make with-d给我以下(完整的输出在这里):

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'.
        [...]

顺便说一句,我正在运行 GNU Make 3.81。

另外,我只是注意到,如果我先运行make src/config.pb.cc然后make build/config.pb.o手动运行,它就可以工作。

为什么这不起作用?

4

2 回答 2

1

你的例子对我来说是正确的。我看到的模式规则和显式规则之间的唯一区别是显式规则没有 order-only 先决条件。您正在运行哪个版本的 GNU make?您确定它支持仅订购的先决条件吗?如果不匹配,则模式规则将不匹配,因为它正在尝试找到一种方法来构建目标,例如|并且不能。

每当你遇到这样的问题时,最简单的事情就是运行make -d。输出量很大,但也很有启发性:找到它试图构建的部分,config.pb.o看看它正在尝试什么模式,以及为什么它决定放弃那个模式。

于 2013-06-19T14:26:41.843 回答
0

我也在构建 proto 文件,我正在使用这些 Makefile 目标:

%.pb.cpp: %.proto
    protoc --cpp_out=. $<
    mv $(@:cpp=cc) $@

%.pb.h: %.pb.cpp ;

build/%.o: %.cpp
    @mkdir -p $(@D)
    $(CXX) $(CXXFLAGS) $(NON_PROFILE_CXXFLAGS) -MD -MF $(@:%.o=%.d) -MT $@ -c $< -o $@

我可以执行

rm -rf build/lsm.pb.o lsm.pb.h lsm.pb.cpp
make build/lsm.pb.o

它正确地找到了依赖关系。对我来说,在我将分号添加到第一条规则的末尾之前,我无法让它工作。出于某种原因,Make 不喜欢用于模式规则的空配方。

六岁的问题在这一点上,但希望这个答案可以帮助像我这样最终来到这里的其他人。

于 2019-04-21T22:02:51.450 回答