Makefile的同一目标中是否可以有多个先决条件模式?

时间:2018-08-24 07:11:30

标签: makefile

我有两个这样的目标

$(OBJ1): $(BUILDDIR)/%.o: $(BUILDROOT)/proto/a/%.pb.cc

$(OBJ2): $(BUILDDIR)/%.o: $(BUILDROOT)/proto/a/b/%.pb.cc

是否可以将这两者以某种方式组合到同一个目标中?

1 个答案:

答案 0 :(得分:2)

可能,但是您需要高级制作功能(宏):

SRC := $(shell find $(BUILDROOT)/proto -type f -name '*.cc')
OBJ := $(addprefix $(BUILDDIR)/,$(patsubst %.cc,%.o,$(notdir $(SRC))))

compile: $(OBJ)

# $(1) is the cc source file
define MY_rule
$$(BUILDDIR)/$$(patsubst %.cc,%.o,$$(notdir $(1))): $(1)
    $$(CXX) -c $$(CXXFLAGS) -o $$@ $$<
endef
$(foreach f,$(SRC),$(eval $(call MY_rule,$(f))))

演示:

$ ls -R proto
proto:
dira

proto/dira:
a.cc  dirb

proto/dira/dirb:
b.cc
$ make BUILDROOT=. BUILDDIR=build compile
g++ -c -o build/a.o proto/dira/a.cc
g++ -c -o build/b.o proto/dira/dirb/b.cc   

请查看section about the eval function中的GNU make manual,以获取完整说明。

最新更新:建议您对另一个(现已删除)类似问题的一条评论建议使用vpath指令。这也很棘手,并增加了一个重要的约束,即所有源文件必须具有不同的基名。为了完整起见,并假设满足约束条件,这是另一个基于vpath的解决方案:

vpath <pattern> dira dirb dirc:...

告诉我们,在搜索与<pattern>匹配的文件时,必须浏览列出的目录。因此,让我们:

  1. 计算所有源文件和相应目标文件的基本名称:

    SRC := $(notdir $(shell find $(BUILDROOT)/proto -type f -name '*.cc'))
    OBJ := $(addprefix $(BUILDDIR)/,$(patsubst %.cc,%.o,$(SRC)))
    
  2. 获取$(BUILDROOT)/proto中所有目录的列表:

    DIR := $(shell find $(BUILDROOT)/proto -type d)
    
  3. 现在,我们准备使用vpath指令:

    vpath %.cc $(DIR)
    

就是这样。总而言之,以下应该起作用:

SRC   := $(notdir $(shell find $(BUILDROOT)/proto -type f -name '*.cc'))
DIR   := $(shell find $(BUILDROOT)/proto -type d)
OBJ   := $(addprefix $(BUILDDIR)/,$(patsubst %.cc,%.o,$(SRC)))

vpath %.cc $(DIR)

compile: $(OBJ)

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