背景:
我们有一个位于开发运营管道中间的 Makefile,它以不寻常的方式做事,由于遗留原因不值得描述。这多年来一直运行良好,但在升级到 GNU Make 4.4 后,它开始生成以下形式的新警告:
Makefile:X: warning: pattern recipe did not update peer target 'Y'.
我 99% 确定此警告对我们的用例无害,但新的警告输出会导致我们管道中的 CI 故障。该 Makefile 由自动化脚本调用,输出也由自动化脚本解析,两者都不能轻易更改。
最小再现器:
生成文件:
%-seq %-par :: %.cpp force
$(MAKE) do_complicated_stuff SRC=$< TGT=$@
do_complicated_stuff:
@echo doing complicated stuff with SRC=$(SRC) TGT=$(TGT)
touch $(TGT)
%-seq :: %.c force
echo Error: this rule should not be run in this MRE
exit 1
.PHONY: force
命令:
$ rm -f *-{seq,par} ; touch foo.cpp ; make --no-print-directory foo-seq
make do_complicated_stuff SRC=foo.cpp TGT=foo-seq
doing complicated stuff with SRC=foo.cpp TGT=foo-seq
touch foo-seq
Makefile:2: warning: pattern recipe did not update peer target 'foo-par'.
这里make
被调用来构建 foo-seq
目标,但它提示 foo-par
目标不存在,甚至没有被提及。给定make
将调用命令一次只构建一个目标,并且 .PHONY
dependency 确保规则将运行(无论 Make 是否认为依赖项是最新的)。 Make 将在同一目录中多次调用(由脚本)来构建每个测试。
问题:
为什么 GNU Make 4.4 突然为过去一直默默地正常工作的习惯用法生成这个新警告,以及要消除这个无害警告的最小更改是什么?强>
限制/要求:
- 该解决方案可能需要涉及某种模式规则,因为可能的源文件名集无法在 Makefile 中进行编码。该名称仅在命令行上提供(无法更改),但规则需要将其与源文件的存在进行匹配,以确保选择并执行正确的规则。
- 在真实的 Makefile 中,上面建模的两条规则比此处显示的要复杂得多,因此我们希望避免为每个目标模式重复第一条规则(这确实会消除警告,但会导致可维护性问题) .
- 最后,出于可移植性的原因,该解决方案需要继续正常运行,并且所有版本的 GNU Make 回到 v3.80 时都不会出现新的警告(如果确实没有更好的解决方案,可能可以协商)。
最佳答案
目前的计划是,在 GNU make 的下一个版本中,这将成为错误而不是警告。所以你现在应该解决这个问题。更改的原因是 GNU make 处理模式的方式存在其他错误,如果不更改此错误就无法修复这些错误。
问题在于这条规则:
%-seq %-par :: %.cpp force
$(MAKE) do_complicated_stuff SRC=$< TGT=$@
我不确定您打算让这个规则实际做什么,但它告诉 make 它将做的是单次调用此配方将创建两个目标 %-seq
和 %-par
。这就是单个规则中的多个模式的含义,并且一直都是这样的含义。
如果您的配方实际上并未构建这两个目标,那么您将看到此问题。
最简单的做法是将规则编写两次,每个目标编写一次,这将适用于所有版本的 GNU make,并且始终是正确的编写方法:
%-seq :: %.cpp force
$(MAKE) do_complicated_stuff SRC=$< TGT=$@
%-par :: %.cpp force
$(MAKE) do_complicated_stuff SRC=$< TGT=$@
预计到达时间
想要避免“重复食谱”是很微不足道的。只需将其放入变量即可:
define COMPLEX_RECIPE
$(MAKE) do_complicated_stuff SRC=$< TGT=$@
endef
%-seq :: %.cpp force ; $(COMPLEX_RECIPE)
%-par :: %.cpp force ; $(COMPLEX_RECIPE)
关于Makefile警告: pattern recipe did not update peer target,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74449959/