我有一个简单的 makefile,可以在 Linux 上将文件编译为p.c
可执行文件。gcc
该p.c
文件依赖于一个a.h
文件。我的生成文件如下所示:
//makefile
CC = gcc
build: p.c a.h
$(CC) -o out p.c
clean:
rm -f *.exe
rebuild: clean build
您的 makefile 不会生成它承诺生成的文件,即build
,clean
和rebuild
. 由于这些目标不是文件,因此应将它们标记为虚假目标:
.PHONY: build clean rebuild
build
目标应该是:
build : out
out : p.c a.h
$(CC) -o $@ p.c
这部分
build: p.c a.h
$(CC) -o out p.c
说“我正在使用 $(CC) -o out pc 进行编译,结果将是一个名为 'build' 的文件”。由于您撒谎make
(这会创建out
文件),它将尝试再次构建“构建”。
这里给 Makefile 编写者一个教训:总是使用$@
变量(表示目标)来避免这个错误:
out: p.c a.h
$(CC) -o $@ p.c
如需更多建议,请参阅Paul 的 Makefile 规则。
学习者,这里有一个使用变量来存储可执行文件名称的例子。这样您只需要在 Makefile 开头的一个地方指定它:
EXECUTABLE = out
.PHONY: build clean rebuild
build: $(EXECUTABLE)
$(EXECUTABLE): p.c a.h
$(CC) -o $@ p.c
clean:
rm -f $(EXECUTABLE)
rebuild: clean build
通常你也会在变量中列出你的.c
和.h
文件,这样你就可以轻松地从你的构建中添加/删除文件,而不必在你的 Makefile 中搜索它们使用的所有位置。
Makefile 具有一般语法:
target : dependencies
commands to make target from dependencies
build
因此,您的 Makefile 期望使用目标创建一个名为的文件build : p.c a.h
。由于命令实际上并没有在每次调用 make 时都生成此文件,因此必须重做命令。
(PS:Linux 二进制文件没有 .exe 扩展名)
如果你想避免总是重新编译源,那么你的目标应该依赖于目标文件,而不是源文件:
目标.exe:宝 $(CC) -o $@ $?; po:电脑啊 $(CC) -c $@ $?;
典型的 makefile 通常没有每个目标文件的显式规则,也通常不会列出实现和头文件之间的显式依赖关系;你通常会看到一个隐含的规则,比如
%.o : %.c $(CC) -c $(CFLAGS) $?;
(其中$?
表示该目标的先决条件列表),或者,如果您的项目非常简单(一个源文件),您甚至不需要它;你通常可以逃脱
全部:目标目标:target.o
假设您有一个名为 的文件target.c
,上面将target
使用默认编译器和 CFLAGS 选项构建。
同样,典型的 makefile(至少在我的经验中)没有明确列出头文件依赖项。相反,它依赖于编译器选项来自动生成这些依赖项列表(对于 gcc,该选项是-M
)。有关示例,请参见此处。
我知道“目标”和“输出文件”名称必须完全匹配才能使制作能够识别是否不需要重新编译。所以在 Windows 环境的情况下(我已经尝试过mingw32-make.exe
)它应该是这样的:
build.exe: p.c a.h
gcc -o build.exe p.c
或者
build.exe: p.c a.h
gcc -o build p.c # .exe is added automatically to generated file
调用make时,此代码将始终导致重新编译:
build: p.c a.h
gcc -o build p.c # target is "build" and it is not the same as "build.exe" which is the output of compilation