0

我有一个非常简单的 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!

测试.mk

SOMEVAR = SomeValue

我有以下两个问题:

问题 1

如果我dummy从我的模式规则中删除先决条件,则模式规则永远不会被调用(我得到可怕的 'Nothing to be done for all' 错误)。有没有一种方法可以让规则下的食谱在%.mk不需要那个虚拟的先决条件的情况下运行?

问题 2

鉴于上述两个文件,我希望 make 执行以下操作:

  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)目标)时,我不明白为什么它坚持要达到模式规则。我在这里想念什么?

4

1 回答 1

1

问题 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. 如果 makefile 包含另一个文件,Make 将在执行任何其他操作之前尝试重建该文件。如果该文件有规则(存在)并且如果成功(确实如此),则 Make 然后重新调用自身。

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

PS这是一个让我想起的kludge。是否适合您的情况取决于具体情况:

生成文件:

# includes nothing

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

测试.mk:

SOMEVAR = SomeValue
include makefile
于 2012-05-04T16:20:10.007 回答