我在不同的目录中有一堆C文件,我的递归Makefile出现make: nothing to be done for 'all'
错误;然而,如果我调整依赖性,我可以让它工作......但我不明白为什么我必须这样做。
这是我原来的Makefile:
APP_DIRS=rescoco ressys resvm
.PHONY: all
all: $(APP_DIRS)
$(APP_DIRS):
$(MAKE) --directory $@
clean:
$(RM) *~
现在,如果我将我的行:.PHONY
更改为.PHONY: all $(APP_DIRS)
,那么它就可以了。
另一种可能性是,如果我将行更改为$(APP_DIRS):
到$(APP_DIRS): clean
,则构建正常。
(注意:删除.PHONY目标不会改变任何东西)
那么这里发生了什么? Makefile是否试图告诉我我没有正确列出依赖项?我在想make
会做类似的事情:
.PHONY
我首先必须构建all
all
我首先必须构建$(APP_DIRS)
$(APP_DIRS)
没有先决条件,因此执行该命令(这将导致递归make运行)。 显然我错了;但为什么?
仅供参考,如果重要,我的文件结构如下:
Makefile #top level makefile as seen above
/rescoco
rescoco.c
Makefile #builds rescoco src and moves archive to ../lib directory
/ressys
ressys.c
Makefile #same as above but for ressys
/resvm
resvm.c
Makefile #same as above but for resvm
/lib
我的构建命令只是make
。当我使用make -n
或make -n all
时,我根本没有输出:
:~/proj$ make -n all
make: Nothing to be done for 'all'.
:~/proj$
答案 0 :(得分:2)
首先你应该注意的事情:
所以你的Makefile实际上只告诉我们:
all
,我需要构建$(APP_DIRS)
。由于all
是PHONY目标,因此我将始终执行all
。$(APP_DIRS)
不是PHONY
目标,并且没有任何依赖关系。所以 *只有当 $(APP_DIRS)
不存在时(即文件或目录),我才会执行配方,否则我没有为此目标做任何事情。clean
没有先决条件而不是PHONY
,所以我希望只有在make(从命令行或其他Makefile)显式调用时才执行此规则。 clean
也不是PHONY
,所以我希望配方在执行后创建一个名为clean
的文件(对于你的情况不正确)因此将.PHONY
行更改为:
.PHONY: all $(APP_DIRS)
使Makefile继续执行$(APP_DIRS)的配方。
因此,如果您希望make始终遍历所有$(APP_DIRS)目录并再次调用make,则需要将$(APP_DIRS)
添加到.PHONY
,这会产生$(APP_DIRS)一个PHONY目标,并执行配方,而不管文件/目录的时间戳是否存在。
对于您的特定用例,我认为这是您应该使用的Makefile:
APP_DIRS=rescoco ressys resvm
.PHONY: all clean $(APP_DIRS)
all: $(APP_DIRS)
$(APP_DIRS):
$(MAKE) --directory $@
clean:
$(RM) *~
<强>奖金:强>
$(APP_DIRS):
更改为$(APP_DIRS): clean
意味着$(APP_DIRS)
取决于clean
目标。clean
未标记为PHONY,但make在当前目录中看不到名为clean
的文件。因此,它继续尝试执行clean
。clean
)的依赖关系,这使得Makefile执行构建$(APP_DIRS)的配方。这给我们带来了一个有趣的观察: - 任何依赖于PHONY目标的目标将始终重建(即将执行配方)。
采用这个简单的Makefile:
all: target1
target1: target2
@echo "$@"
@touch $@
target2: target3
@echo "$@"
@touch $@
target3:
@echo "$@"
.PHONY: all target3
第一次运行make
时,我看到了这个输出:
target3
target2
target1
在此之后,创建文件target1
和target2
。即便如此,如果我再次运行make
,我会看到输出:
target3
target2
target1
正如您所看到的,PHONY
依赖关系会向上传播而不是向下传播。 target2
只是因为target3
是PHONY而重建target1
,而target2
只是因为{{1}}重建而重建。
答案 1 :(得分:0)
您正在定义一个名为“APP_DIRS”的变量,其中包含目录列表。没关系。
然后你做
$(APP_DIRS): make blah blah,
基本上等同于rescoco ressys resvm: make blah blah
显然无效。
所以你需要假装你的$(APP_DIRS)是一个变量,而不是一个目标名称,这似乎是你正在使用它。
话虽如此,想想为什么.PHONY:所有$(APP_DIRS)都有效
答案 2 :(得分:0)
这是你可以做到的,如果你不想要它,只需删除通配符 make wildcard subdirectory targets