递归制作是递归太多,需要一个虚拟先决条件



我有一个非常简单的Makefile,它没有做我期望它会做的事情。最终目标是它应该递归地调用自己,每次都包括适当的文件,从而生成特定于所包含内容的构建(我正在构建几个共享相同代码库的项目,但使用源文件的不同组合(。我从来没有真正处理过递归调用,所以我一定错过了一些明显的东西。目前,我只有一个.mk文件与我的 Makefile 位于同一文件夹中。这只是一个简单的单行代码,仅用于此测试的目的。它最终将包含各种每个项目的设置。

制作文件:

SHELL = /bin/sh
ifdef MYFILE
include $(MYFILE)
PROGRAM = $(basename $(MYFILE))
endif
all: $(wildcard *.mk)
dummy:
        @echo -- Entering dummy stub ... why do I need this?
%.mk: dummy
        @echo Calling $(MAKE) MYFILE=$@ $*
        $(MAKE) MYFILE=$@ $*
$(PROGRAM): objs
        @echo Time to link!
objs:
        @echo Building objs!

test.mk

SOMEVAR = SomeValue

我有以下两个问题:

问题1

如果我从模式规则中删除dummy先决条件,则永远不会调用模式规则(我收到可怕的"无所事事"错误(。有没有办法让我在 %.mk 规则下运行配方,而无需那个虚拟先决条件?

问题2

鉴于上述两个文件,我希望制作以下内容:

  1. make[1] 开始并命中all规则
  2. make[1] 跳转到%.mk模式规则
  3. make[1] 递归调用自身(调用看起来像make MYFILE=test.mk test(
  4. make[2] 启动,包含 test.mk 文件,并设置 PROGRAM 变量
  5. make[2] 跳转到 $(PROGRAM( 规则(因为我们被显式调用了该目标(
  6. make[2] 跳转到 OBJS 规则,运行配方,然后返回链

实际上,make卡在%.mk模式规则上并进入无限循环。我不明白为什么它坚持要达到模式规则,当我在我的第一个递归调用中明确告诉它构建test(这应该对应于$(PROGRAM)目标(时。我在这里错过了什么?

问题 0:
这是过度设计。您不需要在此处使用递归 Make。

问题1:
Make 不尝试重建test.mk(没有虚拟 preq(的原因是test.mk是最新的。更好的方法是切换到静态模式规则并使用 PHONY:

MKS = $(wildcard *.mk)
.PHONY: $(MKS)
$(MKS): %.mk:
    @echo Calling $(MAKE) MYFILE=$@ $*
    $(MAKE) MYFILE=$@ $*

更好的方法是不要使用真实文件的名称作为不会重建(甚至"接触"(该文件的规则的目标。

问题2:
在 make[2] 中,makefile 包含 test.mk 。如果生成文件包含另一个文件,则 Make 将在执行任何其他操作之前尝试重建该文件。如果该文件有规则(确实存在(,并且成功(确实如此(,则 Make 将重新调用自身。

您应该从头开始重新考虑此设计。有很多方法可以获取您正在寻找的行为,具体取决于具体情况(foo.mk中将定义多少变量?您是否真的想通过手动移动这些文件来管理构建?等等(。

附言:这是浮现在脑海中的一个问题。它是否适合您的情况取决于具体情况:

制作文件:

# includes nothing
%.mk: dummy
        @echo Calling $(MAKE) MYFILE=$@ -f $@ $*
        $(MAKE) MYFILE=$@ -f $@ $*

test.mk:

SOMEVAR = SomeValue
include makefile

最新更新