我想编译一些 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',那么它将被编译而不是在 SOURCES 变量中命名的 'foo/bar/sub/three.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 $^