为什么先决条件的顺序在makefile中很重要?

时间:2017-06-29 21:01:28

标签: c makefile

我刚刚学习如何创建makefile并意识到规则先决条件中的头文件和目标文件的顺序很重要,但我不明白为什么。

我和许多同学一起研究和交谈,并且有很多猜测,但没有人有答案。

我知道在编译的预处理步骤中,头文件和源文件中的代码都包含在目标文件中,所以如果我将目标文件和头文件作为先决条件传递,为什么这很重要?

我问,因为如果缺少头文件,我的Makefile就不应该编译。

以下是代码:

CC = gcc
SRC = main.c file1.c
OBJ = $(SRC:.c=.o)
NAME = my_executable
all: header.h $(OBJ)    
     $(CC) $(OBJ) -o $(NAME)

1 个答案:

答案 0 :(得分:7)

  

我[...]意识到了这个顺序   规则先决条件中的标题和目标文件很重要,但我确实如此   不明白为什么?

make的典型实现按照它们在Makefile中出现的顺序处理每个目标的依赖项。当这样的make构建您的示例Makefile的“所有”目标时,它会在hello.h中列出的任何文件之前检查$(OBJ)依赖关系。由于没有构建它的规则,如果该文件尚不存在,make将失败。根据实现和配置,它可能会或可能不会尝试从$(OBJ)构建先决条件。

另一方面,如果在其他先决条件之后列出标题,那么按顺序处理先决条件的make将尝试在检查标题之前构建缺少或过期的任何目标文件。

  

我问,因为我的Makefile不应该编译头文件   不见了。

见上文。但也确实理解你是在依靠kludge。您的Makefile存在缺陷,因为它无法正确表达项目的依赖关系。 all目标是合成的;它本身并不依赖于任何标题。我想这是$(OBJ)个文件中的部分或全部。因此,您应该表达那些依赖项。如果没有这样做,那么如果构建项目然后修改了标头,make将不会重建目标文件,尽管它会重新链接它们。

假设所有目标文件都依赖于标题,我会修改Makefile,如下所示:

CC = gcc
SRC = main.c file1.c
OBJ = $(SRC:.c=.o)
NAME = my_executable
all: $(NAME)

$(NAME): $(OBJ)    
     $(CC) $(OBJ) -o $@

$(OBJ): header.h

最后一行表示$(OBJ)中指定的每个目标都取决于header.h$(NAME)规则表明真实目标$(NAME)取决于所有对象。有了这个,如果header.h发生了变化,那么make将重建目标文件,但同时,如果 nothing 发生变化,那么make将不会做任何事情,甚至不会重新链接主可执行文件。如果缺少标题,则不会尝试构建任何目标文件,也不会构建主可执行文件。