忽略不存在的先决条件

Oli*_*ver 4 makefile gnu-make

make 继续构建并说当我的依赖文件说对象依赖于已移动的头文件时,一切都是最新的.

如果运行make -d以捕获评估,我看到:

Considering target file `../build/out/src/manager.o'.
     Looking for an implicit rule for `../build/out/src/manager.o'.
     No implicit rule found for `../build/out/src/manager.o'.
      Pruning file `../product/build/config/product.conf'.
      Pruning file `../build/out/opt_cc.txt'.
      Considering target file `../mem/src/manager.c'.
       Looking for an implicit rule for `../mem/src/manager.c'.
       No implicit rule found for `../mem/src/manager.c'.
       Finished prerequisites of target file `../mem/src/manager.c'.
      No need to remake target `../mem/src/manager.c'.
      Pruning file `../mem/mem.h'.
     Finished prerequisites of target file `../build/out/src/manager.o'.
     Prerequisite `../product/build/config/product.conf' is older than target `../build/out/src/manager.o'.
     Prerequisite `../build/out/opt_cc.txt' is older than target `../build/out/src/manager.o'.
     Prerequisite `../mem/src/manager.c' is older than target `../build/out/src/manager.o'.
     Prerequisite `../mem/mem.h' of target `../build/out/src/manager.o' does not exist.
../build/out/src/manager.o'.
     Prerequisite `../mem/mem_in.h' is older than target `../build/out/src/manager.o'.
    No need to remake target `../build/out/src/manager.o'.
Run Code Online (Sandbox Code Playgroud)

因此,知道该文件是否需要且不存在,但不会尝试从规则创建或失败.

Prerequisite `../mem/mem.h' of target `../build/out/src/manager.o' does not exist.
Run Code Online (Sandbox Code Playgroud)

为什么会这样,我怎样才能不忽视这条规则?

Mad*_*ist 7

您很可能已经实现了一种自动依赖关系生成方法,通过在没有规则的情况下为该文件定义目标,告诉make基本上忽略这些文件(如果它们不存在).当我有这个makefile时:

foo: foo.h ; @echo make $@ from $^
Run Code Online (Sandbox Code Playgroud)

然后没有foo.h告诉我:

$ make
make: **** No rule to make target 'foo.h', needed by 'foo'.  Stop.
Run Code Online (Sandbox Code Playgroud)

但是,如果我有这个 makefile:

foo: foo.h ; @echo make $@ from $^
foo.h:
Run Code Online (Sandbox Code Playgroud)

现在make非常开心:

$ make
make foo from foo.h
Run Code Online (Sandbox Code Playgroud)

这是许多自动依赖生成实用程序所依赖的记录行为:如果查看生成的依赖关系makefile,您将看到每个头文件的其中一个空目标.

这个想法是,给定正确的依赖信息,永远不应该有一种方法来重命名或删除头文件而不修改一些其他源或头文件,这将导致目标文件无论如何重建(因此为下一个正确地重新创建依赖信息)时间).


owl*_*ler 5

我发现的解决方法是使用静态模式规则而不是模式规则。模式规则如下所示:

%.o : %.c
    *recipe here*
Run Code Online (Sandbox Code Playgroud)

静态模式规则仅适用于如下所示的目标文件的显式列表:

$(OBJECTS): %.o: %.c
    *recipe here*
Run Code Online (Sandbox Code Playgroud)

其中变量OBJECTS在 makefile 中较早地定义为目标文件列表(以空格分隔),例如:

OBJECTS := src/fileA.c src/fileB.c src/fileC.c
Run Code Online (Sandbox Code Playgroud)

请注意,您可以使用各种make实用程序函数来构建目标文件列表。例如$(wildcard pattern)$(addsuffix)、 等。

你没有显示你的 makefile 的相关部分,所以我不能确定这会解决你的情况。但是我得到了make忽略不存在的先决条件的相同症状,并且从make -d关于“先决条件不存在”的相同消息中得到了相同的消息,但随后make对创建先决条件没有任何作用。

请注意,它make包含大约 90 条内置隐式规则,其中大部分是模式规则。因此,即使您的 makefile 没有模式规则,这仍然可能会影响您。

我注意到了一些事情:

  1. 要求明确使先决条件有效。这表明make知道如何构建先决条件。

  2. 为特定文件添加显式目标语句(不使用模式规则)似乎可以解决问题。(但当然只针对那个目标……为 100 个目标中的每一个编写规则是行不通的)。

  3. 在我的研究中,我不断遇到关于make的行为如何不同的陈述,如果有明确的目标与否。

  4. 关闭隐式规则数据库make -r没有帮助。

我的猜测为什么这样做是因为静态模式规则是整个目标列表的显式目标语句的一种形式。

对于我正在调查的特定情况,目标文件已经存在,并且(不存在的)先决条件实际上不需要构建目标,它只在运行时需要。所以也许make不需要构建先决条件来构建目标是正确的。如果您只是要求构建目标,那么 make 将执行完成该目标所需的最少操作。

它似乎仍然是make. 但这可能只是我的误解,我不是make专家。

更新:(2016 年 3 月 16 日)。 我目前的理解是,make将这些前提文件视为中间文件,因此在目标文件已经存在时不关心创建它们。 Make将中间文件视为“二等公民”,它仅在需要创建“一等公民”时才创建它们,这些“一等公民”是在 makefile 中定义的显式目标,或作为参数make在命令行上请求的目标。

通过使用静态模式规则(而不是模式规则),这些文件现在被列为显式目标,因此不是中间文件,而是在必要时创建和更新的“一等公民”。

顺便说一句,这也解释了为什么.SECONDARY在没有先决条件的情况下使用没有帮助。这样做可以防止删除中间文件,但它们仍被视为中间文件,因此make除非需要它们来创建目标或目标,否则不会创建它们。