一个同事刚遇到这个问题,我想问一下以下问题是否有任何巧妙的解决方案:我有一个GNU makefile:
a: | b
touch $@
b:c
touch $@
c:
touch $@
然后我跑步:
~/tmp> make a
touch c
touch b
touch a
~/tmp> make a
make: `a' is up to date.
~/tmp> touch b
~/tmp> make a
make: `a' is up to date.
~/tmp> touch c
~/tmp> make a
touch b
如果我触摸b
,它将重建a
,而不重建c
。如果仅订单先决条件正在调用b
,是否可以不重建它? (在实际情况下,b
是一个具有数百个依赖项的文件,当调用make a
时可能不会存在。我不能使b
的先决条件成为仅顺序的,因为这会破坏[ C0])
该行为是完全正确的。您指示make b
忽略make
和a
之间的紧密依赖性,并且仅取决于b
存在。而b
和a
共享日期依赖性。
这是c
和a: b
之间的区别。
如果要调查此案(或其他a: | b
魔术 :)):
[尝试以下操作,您会发现make
很热衷,并告诉您它对make
目标的作用:
b
现在,添加一个严格的依赖项:
% touch b
% LANG=C make -rd | awk '/^Considering/,/^$/ {print}'
Considering target file `a'.
Considering target file `b'.
Considering target file `c'.
Finished prerequisites of target file `c'.
No need to remake target `c'.
Finished prerequisites of target file `b'.
Prerequisite `c' is older than target `b'.
No need to remake target `b'.
Finished prerequisites of target file `a'.
Prerequisite `b' is order-only for target `a'. <--- "order-only"
No need to remake target `a'.
并比较结果:
% echo "a:b" >> Makefile
我使用了% touch b
% LANG=C make -rd | awk '/^Considering/,/^$/ {print}'
Considering target file 'a'.
Considering target file 'b'.
Considering target file 'c'.
Finished prerequisites of target file 'c'.
No need to remake target 'c'.
Finished prerequisites of target file 'b'.
Prerequisite 'c' is older than target 'b'.
No need to remake target 'b'.
Pruning file 'b'.
Finished prerequisites of target file 'a'.
Prerequisite 'b' is order-only for target 'a'.
Prerequisite 'b' is newer than target 'a'. <--- additional "date dependency"
Must remake target 'a'.
touch a <--- 'a' is rebuilt
Putting child 0x1b09ec0 (a) PID 5940 on the chain.
Live child 0x1b09ec0 (a) PID 5940
Reaping winning child 0x1b09ec0 PID 5940
Removing child 0x1b09ec0 PID 5940 from chain.
Successfully remade target file 'a'.
(没有隐式规则),因为此示例不使用它们,并且它是无聊读取。
除了注释,您的问题陈述是非常通用的,与描述实际用例相距甚远。这使得它非常简短,易于阅读和理解。另一方面,理解和解决或解决您的specific问题更加不确定。
我已经看到您的完全相同的通用问题陈述适用于此其他用例:
make -r
此代码的意思是:“在没有nimble_exe的情况下构建big_lib,但不在乎它何时过期”,这表面上与“仅订购的依赖项”甚至nimble_exe: nimble_srcs | big_lib
touch $@
big_lib: biglib_many_sources_and_headers
touch $@
sleep 1 # simulate a long [no-op] build time
biglib_many_sources_and_headers
touch $@
的定义相匹配。
不幸的是,如果有人更改了used to match ninja's behavior until 2011中的任何内容,则biglib_many_sources_and_headers
会重建make nimble_exe
,但不是
big_lib
!这表明“仅订购依赖项”根本不是针对该用例设计的。因此,我建议改为:nimble_exe