问题的原始版本在 中包含以下几行makefile
:
file.o: file.c header1.h header2.h
-gcc file.c header1.h header2.h
在修复之前,我的回答解决了问题的原始版本。
请注意,a.out
除非编译器反对编译头文件,否则编译行会生成可执行文件。你应该-c
在命令行中。
几个问题:
在 amakefile
中,目标文件何时需要重建?
答:当源文件或它包含的标题之一发生更改时。
附属Q:这个依赖线是什么意思:
file.o: file.c header1.h header2.h
附属 A:file.o
如果源文件或其包含的头文件之一发生更改,则需要重建。
如果你规定:header1.h
取决于header2.h
,header1.h
当你改变时会发生header2.h
什么?
答:没什么。header1.h
你本身不编译。改变的是目标文件。
如果您规定file.c
取决于header1.h
或header2.h
两者兼而有之,那么file.c
当您更改其中一个标头时会发生什么?
回答:又没有了。你没有改变file.c
;您再次重新编译目标文件。
因此,您的目标文件规则的依赖部分很好(在与自动依赖生成相关的限制范围内)。说源文件依赖于标头的规则没有任何意义。实际上,源文件并不直接依赖于头文件。(它间接依赖于它们,因为如果标头内容发生更改,使得有效代码不再是有效代码,则在源代码修复之前不会编译任何内容。但这有点偏离主题。)
对依赖项进行硬编码是有问题的;他们改变了。另一方面,自动生成依赖项是繁琐的。有 GCC 选项(如-M
, -MM
, -MF
, -MG
, -MP
, -MQ
, -MD
, -MMD
, -MT
, -H
- 如此丰富的选项告诉您这里有问题!)可以提供帮助,并且 GNUmake
有“条件包含”来包含依赖文件(如果它们存在),如果他们没有。这些可以提供帮助。查找makedepend
和mkdep
相关命令以获取其他自动化方式。
忽略自动依赖生成,您的 makefile 可能会显示:
FILES.o = file.o
file.x: ${FILES.o}
${CC} -o $@ ${CFLAGS} ${FILES.o}
file.o: file.c header1.h header2.h
make
将提供一个命令编译file.c
成file.o
.
当您的程序other.o
也可以使用时,您只需添加other.o
到宏FILES.o
(这就是它是复数名称的原因)。你也可以添加依赖信息。如果您也需要库,则可以在链接行中添加选项:
LDFLAGS = -L/usr/local/lib
LDLIBS = -llocal
FILES.o = file.o other1.o other2.o
file.x: ${FILES.o}
${CC} -o $@ ${CFLAGS} ${FILES.o} ${LDFLAGS} ${LDLIBS}
file.o: file.c header1.h header2.h
请注意,库应该在目标文件之后。在目标文件之前列出库很容易导致其他平台上的链接时失败,从而激怒那些试图构建您的软件的人。