我刚刚学习如何创建 makefile 并意识到规则先决条件中头文件和目标文件的顺序很重要,但我不明白为什么。
我研究过很多同学,也聊过很多,猜测很多,但没有人给出答案。
我知道在编译的预处理步骤中,来自头文件和源文件的代码被包含在目标文件中,所以如果我将目标文件和头文件作为先决条件传递,为什么这很重要?
我问是因为如果头文件丢失,我的 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
的“全部”目标时,它会hello.h
在 中列出的任何文件之前检查依赖项$(OBJ)
。由于没有构建它的规则,make
如果该文件不存在,则会失败。根据实现和配置,它可能会也可能不会尝试从$(OBJ)
.
另一方面,如果标头列在其他先决条件之后make
,则按顺序处理先决条件的a将尝试构建任何丢失或过时的目标文件,然后再检查标头。
我问是因为如果头文件丢失,我的 Makefile 不应该编译。
看上面。但也确实要明白,你当时依赖的是杂牌。您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 将重建目标文件,但同时,如果没有任何更改,则 make 将不执行任何操作,甚至不会重新链接主可执行文件。如果头文件丢失,则不会尝试构建任何目标文件,因此也不会构建主可执行文件。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句