我们有一个 Makefile,其中包含调用脚本来生成 C 标头的配方,然后将其包含到许多其他源文件中:
gen-header.h: $(INPUT)
script.py $(INPUT) -o gen-header.h
# GMake and GCC rules to produce and include .d files for .c files
# to track header/source dependencies follow
最近,script.py 中添加了优化,以便避免覆盖输出文件(如果存在)并且其内容不会更改(例如,如果仅更新
$(INPUT)
中的非功能性注释)。在这种情况下,输出 gen-header.h
的访问时间和创建时间都不会更新。
优化的预期目标当然是避免在
$(INPUT)
中的更改未传播到标头时重新编译依赖于 gen-header.h 的所有文件(还有其他生成过程使用 $(INPUT)
的不同部分来生成与 gen-header.h 无关的不同源文件)
问题是:这种情况会让 Make 感到困惑吗?或者对于配方来说这是可以接受的行为吗?
问题是:这种情况会让 Make 感到困惑吗?或者对于配方来说这是可以接受的行为吗?
会不会混淆
make
?不会。如果目标的配方没有构建该目标,或者没有在每次运行时构建它,那么make
本质上不会失败。它可能会或可能不会给您的构建带来问题,具体取决于您的 makefile 的细节和其他细节,但您描述的情况听起来是良性的。
它不会混淆 make,因此,在这种特殊情况下是无害的,因为唯一的结果是每次运行 Make 时都会重复运行
script.py $(INPUT) -o gen-header.h
操作。
但是,您通常希望避免这种情况。
类似的规则
target: source
action
从某种意义上说,是一个“承诺”,运行
action
将导致target
比source
更新。当我发现在某些情况下(可能涉及该操作的副作用?)这确实导致了问题时,我会感到零惊讶。
幸运的是,这很容易避免。在这种情况下我会写
# Note: `script.py` doesn't rewrite `gen-header.h` if it wouldn't change
gen-header.h: $(INPUT)
script.py $(INPUT) -o gen-header.h && touch $@
...只是为了提醒自己,在将来调试 Makefile 时会发生这种情况。这会迫使目标文件
$@
更新,从而保持对 Make 的隐含承诺。