gpt4 book ai didi

c++ - 将两个相似的 make 规则减少为一个通用规则

转载 作者:行者123 更新时间:2023-12-05 05:30:13 24 4
gpt4 key购买 nike

假设我有两个制作对象文件的规则(每个都在 obj/ 中),一个取决于目录 A 中的 .cpp 文件 - 让我们称它为 src - 一个依赖于 .cpp 文件目录 B,它是 A 的子目录 - 称之为 src/demos。他们的规则是这样的:

$(ODIR)/%.o : $(SRC)/%.cpp $(DEPS)
$(CXX) -c -o $@ $< $(CXXFLAGS)

$(ODIR)/%.o : $(DEMODIR)/%.cpp $(DEPS)
$(CXX) -c -o $@ $< $(CXXFLAGS)

如您所见,我正在重复一个秘诀,为这些目录制定两条规则。有没有办法可以将这两个规则“压缩”为一个?我考虑过以某种方式使用通配符来匹配 src/*.cppsrc/demos/*.cpp,但我不确定那会怎样在规则中实现。

提前致谢!

最佳答案

有两种解决方案。

  1. 将目标文件放在不同目录中的简单方法,并且能够防止名称冲突。
  2. 保留您的确切目录结构但有点复杂并且不能防止名称冲突的稳健性。

两个解决方案中使用的序言变量(它们在您的实际设置中看起来会有所不同)

SRC=src/
DEMODIR=src/demos/
ODIR=out/
DEPS=

sources=$(wildcard $(SRC)*.cpp) $(wildcard $(DEMODIR)*.cpp)

解决方案 1(我的推荐)。

目标文件遵循源文件的目录结构。

objects=$(patsubst %.cpp,$(ODIR)%.o,$(sources))
$(objects): $(ODIR)%.o: %.cpp $(DEPS)
$(CXX) -c -o $@ $< $(CXXFLAGS)

解决方案 2(您的目录结构)。

objects=$(patsubst %.cpp,$(ODIR)%.o,$(sources))
flatobjects=$(patsubst $(ODIR)$(SRC)%, $(ODIR)%, $(objects))
f_retrieve=$$(findstring $(join $(SRC),$(1:.o=.cpp)),$(sources)) $$(findstring $(join $(DEMODIR),$(1:.o=.cpp)),$(sources))

.SECONDEXPANSION:
$(flatobjects): $(ODIR)%.o: $(call f_retrieve,%.o) $(DEPS)
$(CXX) -c -o $@ $< $(CXXFLAGS)

这可能会在您同时拥有 src/a.cppsrc/demos/a.cpp 时中断,因此仅在此基础上推荐解决方案 1。

诀窍是在 $(sources) 变量中搜索每个目标的先决条件以找到匹配的源文件(通过 findstring)。请注意 .SECONDEXPANSION 部分和 findstring 之前的双 $。直接这样做在理论上应该可行,但 GNU make 在规则中不喜欢它。放松要展开两次的表达式即可。

演示(方案二)

./src: a.cpp b.cpp c.cpp
./src/demos: x.cpp y.cpp z.cpp

附加辅助规则:flatobjects: $(flatobjects)

$ make flatobjects 
gcc -c -o out/a.o src/a.cpp
gcc -c -o out/b.o src/b.cpp
gcc -c -o out/c.o src/c.cpp
gcc -c -o out/x.o src/demos/x.cpp
gcc -c -o out/y.o src/demos/y.cpp
gcc -c -o out/z.o src/demos/z.cpp

关于c++ - 将两个相似的 make 规则减少为一个通用规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74756874/

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