递归make会递归太多并且需要伪前提条件

时间:2012-05-04 15:39:47

标签: linux makefile

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

鉴于前面提到的两个文件,我希望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规则,运行食谱,然后返回链条
  7. 实际上,make卡在%.mk模式规则上并进入无限循环。当我明确告诉它在我的第一次递归调用中构建test时(我应该对应$(PROGRAM)目标),我不明白为什么它坚持要遵守模式规则。我在这里缺少什么?

1 个答案:

答案 0 :(得分:1)

问题0:
这是过度设计。你不需要在这里使用recursive。

问题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将在执行任何其他操作之前尝试重建该文件。如果该文件有一个规则(有),如果它成功(它确实如此),那么重新调用自己。

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

P.S。这是一个让人想起的淤泥。是否适合您的情况取决于具体情况:

生成文件:

# includes nothing

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

test.mk:

SOMEVAR = SomeValue
include makefile