【问题标题】:GNU Make: Using the filter function in prerequisitesGNU Make:在先决条件中使用过滤器功能
【发布时间】:2012-11-27 20:05:39
【问题描述】:

我想编译一些 C++ 文件,我绝对必须将所有目标文件放在一个单独的构建目录中,但存储完全平坦,即没有任何进一步的子目录。我知道使用 VPATH 的常见解决方案,如下所示:

SOURCES = foo/one.cpp \
    foo/bar/two.cpp \
    foo/bar/sub/three.cpp

OBJDIR = obj

VPATH=$(dir $(SOURCES))

OBJECTS = $(addprefix $(OBJDIR)/, $(notdir $(SOURCES:%.cpp=%.o)))

$(OBJDIR)/%.o : %.cpp
    @echo Should compile: $(filter %/$*.cpp, $(SOURCES))
    @echo Compiling $<

all: $(OBJECTS)

这个例子非常有效:我在“obj”子目录中获得了三个目标文件 one.o、two.o、three.o(您可以假设它只是存在)。

现在是使用 VPATH 时的问题:如果碰巧有一个文件 'foo/three.cpp',那么将编译 this 而不是 'foo/bar/sub/three。在 SOURCES 变量中命名的 cpp'。不,我不能重命名任何一个文件;这个名字冲突只是存在,我对此无能为力。

所以我的问题是:我如何告诉 Make 使用出现在 SOURCES 变量中的“.cpp”文件?我认为最好的解决方案是在目标的先决条件中使用“过滤器”语句。我认为这应该可以使用二次扩展,但我不知道如何处理'%'。比如我试过

 .SECONDEXPANSION:
$(OBJDIR)/%.o : $$(filter %/$$*.cpp, $(SOURCES))

但这不起作用。


更新:在 Tripleee 的帮助下,我设法使用以下方法完成了这项工作:

define make-deps
$(OBJDIR)/$(notdir $(1:%.cpp=%.o)): $1
endef

$(foreach d, $(SOURCES), $(eval $(call make-deps,$d)))

%.o : 
    @echo Should compile $^ into $@
    @echo Compiling $^

【问题讨论】:

  • 为什么要将所有.o文件放到一个平面目录中?
  • 这就是现有构建的工作方式,处理这些目标文件的其他工具依赖于此。

标签: makefile gnu-make


【解决方案1】:

我怀疑解决您问题的最简单方法是摆脱 VPATH 并明确记录每个依赖项。这可以很容易地从您的SOURCES 定义中获得;也许你想定义一个函数,但归根结底是这样的:

obj/one.o: foo/one.cpp
obj/two.o: foo/bar/two.cpp
obj/three.o: foo/bar/sub/three.cpp

实际规则可以保留,只是它不再包含内联依赖项,您可以跳过 obj/ 子目录,因为它在每个依赖项中都显式声明:

%.o : # Dependencies declared above
    @echo Should compile $^ into $@
    @echo Compiling $^

我将规则更改为使用$^ 而不是$&lt;,以防您拥有多个依赖项。对于您的情况,这可能是正确的或错误的;如果不是您需要的,请还原更改。

为了不需要手动维护依赖关系,您可能希望为每个%.cpp 文件生成%.d。见the GNU Make manual。 (我尝试使用define 来做到这一点,但您似乎无法使用foreach 循环声明依赖关系。)

针对评论中的问题,这不应以任何方式影响并行构建;当VPATH 中有多个具有相同名称的 biuld 候选对象时,它只会消除原始 Makefile 不明确的依赖关系。没有新的依赖,也没有新的规则。

【讨论】:

  • 每个源文件的单独规则而不是模式规则?但是我不能进行并行构建,可以吗?
  • @pokita 像上面这样的显式依赖不会影响并行构建。换句话说,依赖树的构建方式无关紧要,一旦构建完成,它就可以并行重新生成目标。
  • 那些不是独立的规则,反正就是独立的依赖。如果有的话,一次构建所有东西的单一规则是无与伦比的。独立的、独立的依赖链可以独立构建,即也可以并行构建。
  • 稍微更新了答案。
  • 非常感谢!由于我在使用 gcc 编译期间生成了自动依赖项,因此我确实使用了您的建议 do use 'define' 来生成这些显式依赖项,效果很好。
猜你喜欢
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
  • 2012-02-21
  • 1970-01-01
相关资源
最近更新 更多