我有一个非常简单的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
我有以下两个问题:
如果我从模式规则中删除dummy
先决条件,模式规则永远不会被调用(我得到了可怕的'无所事事'错误)。有没有办法可以让%.mk
规则下的配方运行而不需要虚假的先决条件?
鉴于前面提到的两个文件,我希望make能够做到以下几点:
all
规则%.mk
模式规则make MYFILE=test.mk test
)实际上,make卡在%.mk
模式规则上并进入无限循环。当我明确告诉它在我的第一次递归调用中构建test
时(我应该对应$(PROGRAM)
目标),我不明白为什么它坚持要遵守模式规则。我在这里缺少什么?
答案 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