第二次运行时,Makefile会产生不同的结果

时间:2015-12-07 15:26:07

标签: makefile gnu-make

我在makefile中有这样的规则:

target : dependencies
   rm -rd somedirectory
   runcodecoverage.exe # this generates somefile
   $(eval COVERAGE=$(shell grep "blah" somefile))
   @echo $(COVERAGE)

当我第一次运行此文件时(清洁后),回声不会打印任何内容。但是在第二次和之后,它会打印出正确的结果。如果我用grep "blah" somefile替换$(eval ..)行我得到了我想要的结果,所以问题必须是使用$(eval)和$(shell)。为什么会这样?

编辑:我通过添加新的依赖项解决了这个问题,所以它现在看起来像这样:

generatesomefile : 
   runcodecoverage.exe # this generates somefile

target : dependencies generatesomefile
   rm -rd somedirectory
   $(eval COVERAGE=$(shell grep "blah" somefile))
   @echo $(COVERAGE)

似乎$(eval)一旦被" target"替换为grep的结果。目标已输入,即使我希望它在runco​​decoverage.exe运行后运行。从这个意义上说,我认为正确的答案是不对的 - 文档在变量扩展中说这个:

规则定义

规则总是以相同的方式扩展,无论形式如何:

立即:立即;延期的         推迟

2 个答案:

答案 0 :(得分:1)

The eval function并不像您认为的那样工作。

第一次运行Make时,它会扩展eval函数并在执行任何规则之前执行变量赋值由于没有somefile,{ {1}}不返回任何内容,grep保持为空。当Make执行规则时,它会将空变量传递给COVERAGE,它会及时报告任何内容。

第二次运行Make时,它再次展开echo函数,执行eval grep(在第一次运行中构建),并将结果存储在somefile。然后它执行规则并将COVERAGE传递给COVERAGE,然后将其放在屏幕上。

答案 1 :(得分:1)

解析Makefile时$(eval ...)运行,而不是在执行配方时运行。

我不清楚你期望发生什么;在配方中设置Make变量似乎不是一种可持续的方法,但它在很大程度上取决于您需要使用此变量的位置和方式。如果您只需要输出同一配方的覆盖范围,请用

替换最后几行
grep "blah" somefile