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

C 为什么先决条件的顺序在makefile中很重要?,c,makefile,C,Makefile,我刚刚学习如何创建makefile,并意识到在规则的先决条件中头文件和对象文件的顺序很重要,但我不明白为什么 我调查过我的许多同学,并与他们交谈过,当时有很多猜测,但没有人给出答案 我知道在编译的预处理步骤中,来自头文件和源文件的代码会包含在目标文件中,因此,如果我将目标文件和头文件作为prereq传递,那么这又有什么关系呢 我这样问是因为如果缺少头文件,我的Makefile不应该编译 代码如下: CC = gcc SRC = main.c file1.c OBJ = $(SRC:.c=.o)

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

我调查过我的许多同学,并与他们交谈过,当时有很多猜测,但没有人给出答案

我知道在编译的预处理步骤中,来自头文件和源文件的代码会包含在目标文件中,因此,如果我将目标文件和头文件作为prereq传递,那么这又有什么关系呢

我这样问是因为如果缺少头文件,我的Makefile不应该编译

代码如下:

CC = gcc
SRC = main.c file1.c
OBJ = $(SRC:.c=.o)
NAME = my_executable
all: header.h $(OBJ)    
     $(CC) $(OBJ) -o $(NAME)
我[…]意识到了 规则先决条件中的头文件和对象文件很重要,但我确实很重要 不明白为什么

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

另一方面,如果标题列在其他先决条件之后,则处理先决条件的
make
将尝试在检查标题之前构建任何丢失或过期的对象文件

我这样问是因为如果头文件 他失踪了

见上文。但也要明白,你是在依赖一个混帐。您的
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
$(名称)
规则表示真正的目标
$(名称)
取决于所有对象。这样,如果
header.h
changes,则make将重建目标文件,但同时,如果没有任何更改,则make将不做任何操作,甚至不会重新链接主可执行文件。如果缺少标头,则不会尝试构建任何对象文件,因此也不会构建主可执行文件

我[…]意识到了 规则先决条件中的头文件和对象文件很重要,但我确实很重要 不明白为什么

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

另一方面,如果标题列在其他先决条件之后,则处理先决条件的
make
将尝试在检查标题之前构建任何丢失或过期的对象文件

我这样问是因为如果头文件 他失踪了

见上文。但也要明白,你是在依赖一个混帐。您的
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
$(名称)
规则表示真正的目标
$(名称)
取决于所有对象。这样,如果
header.h
changes,则make将重建目标文件,但同时,如果没有任何更改,则make将不做任何操作,甚至不会重新链接主可执行文件。如果缺少标头,则不会尝试构建任何目标文件,因此也不会构建主可执行文件。

如果
header.h
不存在,并且
main.c
依赖于它,但是
main.o
不会将其列为依赖项,是的,顺序很重要–但是
main.o
应该将其作为依赖项,不是所有的。你的声明缺乏证据我不知道你想要知道什么,如果你的源文件.c包含头文件.h,并且它丢失了,那么编译是正确的;如果您想从需求中删除头文件,您必须从makefile中删除
header.h
,如下所示:all:$(OBJ)$(CC)$(OBJ)-o$(NAME)请编辑您的问题…如果行为取决于依赖项的顺序,则这是makefile中的错误。您可能一开始并没有注意到这一点,因为gmake通常会按左右顺序考虑依赖项,但事实会如此