Makefile GNU Make:在前提条件中使用过滤器函数 我想编译一些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)

Makefile GNU Make:在前提条件中使用过滤器函数 我想编译一些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),makefile,gnu-make,Makefile,Gnu Make,但这不起作用 更新:在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 $^ 我认为解决您的问题最简单的方法是去掉VPATH,

但这不起作用


更新:在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 $^

我认为解决您的问题最简单的方法是去掉
VPATH
,并明确记录每个依赖项。这可以很容易地从
来源
定义中获得;也许您想定义一个函数,但它实际上可以归结为:

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 $^

我将规则更改为使用
$^
而不是
$为什么需要将所有
.o
文件放在一个平面目录中?这就是现有构建的工作方式,其他处理这些对象文件的工具依赖于此。每个源文件都有一个单独的规则,而不是模式规则?但是我不能进行并行构建,对吗?@pokita上面的显式依赖不会影响并行构建。换句话说,依赖关系树是如何构建的并不重要,一旦构建了依赖关系树,它就可以并行地重新生成目标。无论如何,这些不是独立的规则,只是独立的依赖关系。如果说有什么区别的话,那么一条一次性构建所有内容的规则是不可比拟的;独立、独立的依赖链可以独立构建,也可以并行构建。对答案进行了一些更新。非常感谢!由于我在使用gcc编译期间自动生成依赖项,所以我确实使用了您的建议,使用“define”生成这些显式依赖项,这非常有效。
%.o : # Dependencies declared above
    @echo Should compile $^ into $@
    @echo Compiling $^