5

这是我的生成文件:

all: first second

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

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

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

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

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

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

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

4

3 回答 3

7

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

为了让 make 认为一个文件过期并且需要更新(因此,为了让 make 运行与目标关联的配方),至少有两件事之一是真实的:要么是目标(即,文件或目录)不能存在,或者,如果确实存在,则其最后修改时间必须至少早于其先决条件之一。

在你的情况下,你有second,它存在,所以重建的第一个要求没有得到满足,并且没有先决条件,所以第二个要求没有得到满足......所以目标不被认为是过时的并且配方不被调用。

正如 bobbogo 建议的那样,您可以通过将目标声明为.PHONY. Make 将理解目标不代表文件系统中的工件,而只是用于组织构建的 makefile 中的假目标。

于 2013-05-01T13:28:37.310 回答
2

second无论文件(或目录)“第二”是否已经存在,您似乎都希望规则始终运行。您可以通过将其声明为.PHONY.

.PHONY: all
all: first second

.PHONY: second
second:
    @echo "==Building second=="
...
于 2013-05-01T12:59:32.130 回答
0

如果我正确理解您的问题陈述,那么您不是在调用echo,而是在调用$(MAKE) -Csecond。是时候阅读 Miller 的Recursive Make Considered Harmful了!虽然这些并不完全是传统品牌的固有问题,但用它们做得更好是困难和笨拙的。

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

makepp 还有很多。除了做 GNU make 能做的几乎所有事情,还有很多有用的东西,你甚至可以用一些 Perl 编程来扩展你的 makefile。

于 2013-05-01T15:56:04.083 回答