如何强制 make 重新启动并重新加载生成的 makefile?

How to force make to restart and reload generated makefiles?

手头的任务如下:在配方中调用的外部工具生成一个 makefile,该 makefile 应立即包含在 make 中。然后,另一个规则,使用包含的数据生成进一步的包含文件。 Make 应该重新启动,然后才处理进一步的规则。考虑以下示例:

$(info ------- Restart $(MAKE_RESTARTS))

all :

include a
include b

a : p
    touch a

b : a
    touch b

像这样工作:

        touch p 
        make
        ------- Restart
        touch a
        touch b
        ------- Restart 1
        make: Nothing to be done for 'all'.

我的问题是规则 b 需要 a 中包含的数据,但 b 是在包含 a 的更新版本之前执行的。 在执行 b 之前应该重新启动 Make。如何实现?我想看这个:

        touch p 
        make
        ------- Restart
        touch a
        ------- Restart 1
        touch b
        ------- Restart 2
        make: Nothing to be done for 'all'.

很容易检测是否包含a,当a不包含时可以隐藏b的规则。这适用于干净的构建,但当 a 已经存在于先前构建的磁盘上并且由于 p 已更新而触发规则时则无效。 只有 make 知道,规则 a:p 是否是最新的,无法用条件表达式检查。

有解决办法吗?

更新:根据@MadScientist 的建议,我是这样工作的:

$(info ------- Restart $(MAKE_RESTARTS))

all :

include b
include a

a : p
    @echo rule A
    touch a
    $(eval upd=1)

b : a
    @echo rule B
    $(if $(upd),@echo b skipped,touch b)

并且输出:

touch p
make   
------- Restart 
rule A
touch a
rule B
b skipped
------- Restart 1
rule B
touch b
------- Restart 2

完美!谢谢大家,大家圣诞快乐。

有不止一种方法可以做到这一点(通常使用 Make)。

我会这样做:将 include b 语句放入 a

$(info ------- Restart $(MAKE_RESTARTS))

all :

-include a


a : p
    touch a
    @echo -include b >> a

b : a
    touch b

一个解决方案是调用子 make 来构建 b。该子品牌将包括较新的 a,因此是正确的。我相信这样的事情会起作用(未经测试):

$(info ------- Restart $(MAKE_RESTARTS))
all :

include a
include b

a : p
        touch a

ifeq ($(filter real_b,$(MAKECMDGOALS)),)
b : a
        $(MAKE) real_b
endif

.PHONY: real_b
real_b:
        touch b

另一个解决方案是确保 ba 更新时 更新。也许是这样的(同样,未经测试):

$(info ------- Restart $(MAKE_RESTARTS))
all :

include a
include b

BUILT_A =

a : p
        touch a
        $(eval BUILT_A = true)

b : a
        $(if $(BUILT_A),,touch b)

(在配方中罕见地合法使用 eval!)在此版本中,如果构建了 a,则不会触及 b。这样在 make re-execs 本身之后它将包括 a 和包括 b,然后看到 a 是最新的但看到 b 是过时的(因为我们第一次跳过构建步骤)并重建 b:这次 b 将被更新,因为 a 在上一次传递中被更新,然后 make 将再次重新执行。