忽略仅订单先决条件

Ignore order-only prerequisites

我有一组目标,应该根据一些订单要求执行。有正确的顺序:

  1. wake
  2. fuse
  3. flash
  4. eep
  5. verify
  6. lock

其中一些目标被归类为另一个(虚假的)空目标:

.PHONY: wake
full: fuse flash eep lock

不幸的是,当我调用 make full --dry-run 时,我看到 make 试图以错误的顺序执行规则:wake flash eep lock fuse。因此我得到不正确的结果(擦除 MCU)。

我已尝试添加一些仅订单先决条件。这是我的 Makefile 的骨架:

.PHONY: wake
wake:
        <...>

.PHONY: flash
flash: build/main.hex | fuse
        <...>

.PHONY: eep
eep: build/main.eep.hex | fuse flash
        <...>

.PHONY: verify
verify: build/main.hex | fuse flash eep
        <...>

.PHONY: fuse
fuse: | wake
        <...>

.PHONY: lock
lock: | fuse flash eep
        <...>

build/main.hex: <some files here>
        <...>

现在 make full 工作正常,但即使我尝试执行某些特定规则,PHONY order-only 目标的规则也会执行。例如: make eep 导致执行 wake fuse flash eep。 我不想浪费时间完全刷机,而我只需要编写新的 eep 映像。

似乎所谓的“仅订单先决条件”被视为常规先决条件。

如何强制“仅订单先决条件”像真正的仅订单需求一样工作?有没有更优雅的方案?

我想你误解了 order-only 指的是什么。 Order only表示先决条件必须在target之前构建,但是如果order-only先决条件比target更新,则不需要重建target。但是,如果 order-only 先决条件不存在,目标仍然被认为是过时的(并且因为您所有的目标都是 .PHONY,其中 none 存在...)

您可以使用 'sentinel' 文件,而不是使用虚假目标,这些文件基本上是虚拟文件,标记 if/when 每个目标都是最后一个 运行:

.PHONY: flash fuse wake eep verify lock all

all:   verify
flash: .flash.sentinel
fuse:  .fuse.sentinel
wake:  .wake.sentinel
eep:   .eep.sentinel


.flash.sentinel: build/main.hex .fuse.sentinel
    <...>
    touch $@

.fuse.sentinel: .wake.sentinel
    <...>
    touch $@

.eep.sentinel: build/main.eep.hex fuse.sentinel flash.sentinel
    <...>
    touch $@
 
.wake.sentinel: build/main.eep.hex fuse.sentinel flash.sentinel
    <...>
    touch $@

verify: build/main.hex eep.sentinel fuse.sentinel flash.sentinel
    <...>

注意,在干净的构建中,make all 将重建生成 .sentinel 文件的所有内容。对 make all 的后续调用只会重建任何被认为过时的内容。因此,例如,如果您修改了 build/main.hex,它会重建 flasheepwakefuse,但如果您不进行任何更改,它不会做任何事情(因为一切都已经完成)。如果您构建 make flash,它将重建闪存,以及它认为过时的任何其他先决条件。

现在,另一方面,如果您想在键入 make flash 时强制 闪现规则 运行,无论是否有其他目标已过时,那么您可以添加一个对称树,一个有先决条件,一个没有:

.PHONY: flash fuse wake eep verify lock 
.PHONY: do_flash do_fuse do_wake do_eep do_verify do_lock
.PHONY: all

all:   do_lock

flash do_flash:
   <...>

fuse do_fuse:
   <...>

wake do_wake:
   <...>

eep do_eep:   
   <...>

verify do_verify:
   <...>

lock do_lock:
   <...>

do_fuse : do_wake 
do_flash : do_fuse 
do_eep : do_flash 
do_verify : do_eep 
do_lock : do_verify 

这意味着如果您执行 make flash,它没有先决条件,并且只会 运行 规则。如果你做 make allall 有先决条件 do_verify,它有另一个先决条件,等等,一直往下,所有这些都将是 运行 的正确顺序。