gpt4 book ai didi

makefile - GNU 使 : Using the filter function in prerequisites

转载 作者:行者123 更新时间:2023-12-01 08:03:17 30 4
gpt4 key购买 nike

我想编译一些 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”。 cpp',它在 SOURCES 变量中命名。不,我不能重命名任何一个文件;这种名称冲突根本存在,我对此无能为力。

所以我的问题是:如何告诉 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 $^

最佳答案

我怀疑解决您问题的最简单方法是摆脱 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 $^

我将规则更改为使用 $^而不是 $<以防你有不止一个依赖。根据您的情况,这可能是对的,也可能是错的;如果不是您需要的,请还原更改。

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

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

关于makefile - GNU 使 : Using the filter function in prerequisites,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13592154/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com