类数据库文件作为 Makefile 中的目标和先决条件
Database-like files as targets and prerequisites in a Makefile
假设我有一个简单的 Makefile。
a1: some_script b
some_command $< b
a2: some_other_script b
some_command $< b
b: c
touch $@
c:
touch $@
其中 b
是生成 a1
和 a2
所需的一些类似数据库的文件。但是,每次访问 b
时(即使未更改)修改日期也会更改。因此,无论何时执行 a2
的规则,Make 都认为 a1
需要重新创建,因为使用了数据库 b
(即使 c
没有改变并且 b
保持不变)。我只想更新 a1
和 a2
如果 c
更新(因此 b
需要实际重新编译)。
我可以简单地让 a1
和 a2
直接依赖于 c,但这歪曲了真实的工作流程。
我不想删除 b
,所以将它作为中间文件是行不通的。
我也试过将 b
包含为仅订单依赖项,但 a1
和 a2
除非被迫,否则永远不会重新制作。
注意:Makefile 旨在自动执行脚本并跟踪研究项目(而不是软件项目)的依赖关系。也许 Make 不是解决此问题的正确工具。类似数据库的文件是 GeoPackages。
如果您不能依赖 b
的时间戳是准确的,那么您不需要在您的 makefile 中使用它。你可以这样做:
a1: some_script .buildc
some_command $< b
a2: some_other_script .buildc
some_command $< b
.buildc: c
command to update b
touch $@
c:
touch $@
仅当 c
比每次调用此命令时设置的 .buildc
更新时才会 运行 command to update b
,而不是当 b
更新时使用过。
您也许可以防止对 b
:
的时间戳进行无用的更改
a1: some_script b
touch -r b .b.a1
some_command $< b
touch -r .b.a1 b && rm .b.a1
a2: some_other_script b
touch -r b .b.a2
some_command $< b
touch -r .b.a2 b && rm .b.a2
但请注意:如果您运行以并行模式制作 (make -j
),a1
和 a2
食谱可能会 运行 并行潜在的竞争条件。因此,最好使用 .NOTPARALLEL:
或在食谱中使用 flock
来序列化它们。
我认为“order-only prerequisite”可能会成功:
a1: some_script | b
some_command $< b
a2: some_other_script | b
some_command $< b
b: c
touch $@
c:
touch $@
假设我有一个简单的 Makefile。
a1: some_script b
some_command $< b
a2: some_other_script b
some_command $< b
b: c
touch $@
c:
touch $@
其中 b
是生成 a1
和 a2
所需的一些类似数据库的文件。但是,每次访问 b
时(即使未更改)修改日期也会更改。因此,无论何时执行 a2
的规则,Make 都认为 a1
需要重新创建,因为使用了数据库 b
(即使 c
没有改变并且 b
保持不变)。我只想更新 a1
和 a2
如果 c
更新(因此 b
需要实际重新编译)。
我可以简单地让 a1
和 a2
直接依赖于 c,但这歪曲了真实的工作流程。
我不想删除 b
,所以将它作为中间文件是行不通的。
我也试过将 b
包含为仅订单依赖项,但 a1
和 a2
除非被迫,否则永远不会重新制作。
注意:Makefile 旨在自动执行脚本并跟踪研究项目(而不是软件项目)的依赖关系。也许 Make 不是解决此问题的正确工具。类似数据库的文件是 GeoPackages。
如果您不能依赖 b
的时间戳是准确的,那么您不需要在您的 makefile 中使用它。你可以这样做:
a1: some_script .buildc
some_command $< b
a2: some_other_script .buildc
some_command $< b
.buildc: c
command to update b
touch $@
c:
touch $@
仅当 c
比每次调用此命令时设置的 .buildc
更新时才会 运行 command to update b
,而不是当 b
更新时使用过。
您也许可以防止对 b
:
a1: some_script b
touch -r b .b.a1
some_command $< b
touch -r .b.a1 b && rm .b.a1
a2: some_other_script b
touch -r b .b.a2
some_command $< b
touch -r .b.a2 b && rm .b.a2
但请注意:如果您运行以并行模式制作 (make -j
),a1
和 a2
食谱可能会 运行 并行潜在的竞争条件。因此,最好使用 .NOTPARALLEL:
或在食谱中使用 flock
来序列化它们。
我认为“order-only prerequisite”可能会成功:
a1: some_script | b
some_command $< b
a2: some_other_script | b
some_command $< b
b: c
touch $@
c:
touch $@