Makefile:与子目录同名的规则被忽略

时间:2013-05-01 11:29:44

标签: makefile gnu-make

这是我的makefile:

all: first second

second:
    @echo "==Building second=="

first:
    @echo "==Building first=="

如果存在名为second的目录,则makefile将完全忽略具有相同名称的规则。如果没有,一切正常。

请注意,无论second文件夹是否为Makefile,都会发生这种情况。

我在组织项目时遇到了这个问题:我考虑创建一个通用的Makefile,然后在每个目录中调用Makefile ..所以对我来说,规则与文件夹的名称相同是很自然的。

解决方案很简单:更改Makefile中的规则名称...但这种行为似乎很奇怪:您对此有什么想法/见解,还有另一种可能的解决方案吗?

我在Ubuntu 12.04.2 LTS下使用Bash 4.2.25中的GNU Make 3.81。

3 个答案:

答案 0 :(得分:5)

如果您只是查找未运行规则的原因,那很简单:尝试构建目标。目标(默认情况下)由文件系统中的工件的存在表示。无论工件是文件还是目录(或者理论上是其他任何东西)都无关紧要。

为了让make考虑一个过时且需要更新的文件(因此,对于make来运行与目标相关的配方),两件事中至少有一件必须是真的:要么是目标(即文件或目录)不能存在,或者如果存在,则其上次修改时间必须早于至少一个先决条件。

在你的情况下你有second,这是存在的,所以重建的第一个要求不是我,而且没有先决条件,所以不满足第二个要求......所以不考虑目标过时了,没有调用配方。

正如bobbogo建议的那样,你可以通过声明目标是.PHONY来告诉make,应该始终重建目标,而不管其他什么。 Make会理解目标代表文件系统中的工件,而只是用于组织构建的makefile中的假目标。

答案 1 :(得分:2)

似乎您希望second规则始终运行,无论文件(或目录)“second”是否已存在。您可以通过将其声明为.PHONY的先决条件来制作第二种此类符号目标。

.PHONY: all
all: first second

.PHONY: second
second:
    @echo "==Building second=="
...

答案 2 :(得分:0)

如果我理解你的问题陈述,你不是在调用echo,而是$(MAKE) -Csecond。很高兴阅读米勒的Recursive Make Considered Harmful!虽然这些并不是传统制作的固有问题,但用它们做得更好会很难也很笨拙。

因此makepp已创建。您可以拥有大约相同的makefile,但不需要指定递归。如果目标目录具有makefile,则它们通常会自动加载到同一进程中。或者,如果您的目标生成到另一个目录,您必须告诉makepp要加载哪个makefile。无论哪种方式,一个进程都具有所有(自动检测到的!)依赖关系的概述。

makepp还有很多。除了做几乎所有GNU make之外,还有更多有用的东西,你甚至可以通过一些Perl编程扩展你的makefile。