我有一个简单的makefile,可以在Linux上使用p.c
将gcc
文件编译为可执行文件。
p.c
文件取决于a.h
文件。
我的makefile看起来像这样:
//makefile
CC = gcc
build: p.c a.h
$(CC) -o out p.c
clean:
rm -f *.exe
rebuild: clean build
答案 0 :(得分:6)
您的makefile不会生成它承诺生成的文件,即build
,clean
和rebuild
。由于这些目标不是文件,因此应将其标记为phony targets:
.PHONY: build clean rebuild
build
目标应为:
build : out
out : p.c a.h
$(CC) -o $@ p.c
答案 1 :(得分:2)
这部分
build: p.c a.h
$(CC) -o out p.c
说“我正在编译$(CC)-o out p.c,结果将是一个名为'build'的文件”。由于你骗了make
(这会创建out
文件),它会尝试再次构建'build'。
这里有Makefile编写器的教训:始终使用$@
变量(表示目标)来避免此错误:
out: p.c a.h
$(CC) -o $@ p.c
有关更多建议,请参阅Paul's Rules for Makefiles。
答案 2 :(得分:1)
学习者,这是使用变量存储可执行文件名称的示例。这样,您只需要在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中搜索所有位置他们被使用了。
答案 3 :(得分:0)
Makefile具有一般语法:
target : dependencies
commands to make target from dependencies
因此,您的Makefile期望使用build
目标创建名为build : p.c a.h
的文件。
由于每次调用时命令都不会实际生成此文件,因此必须重做命令。
(PS:Linux二进制文件没有.exe扩展名)
答案 4 :(得分:0)
如果您想避免始终重新编译源,那么您的目标应该依赖于对象文件,而不是源文件:
target.exe : p.o $(CC) -o $@ $?; p.o: p.c a.h $(CC) -c $@ $?;
典型的makefile通常没有每个目标文件的显式规则,也不会列出实现和头文件之间的显式依赖关系;你经常会看到像
这样的隐式规则%.o : %.c $(CC) -c $(CFLAGS) $?;
(其中$?
表示该目标的先决条件列表),或者,如果您的项目简单(一个源文件),您甚至不需要它;你通常可以逃脱
全部:目标 target:target.o
假设您有一个名为target.c
的文件,上面将使用默认编译器和CFLAGS选项构建target
。
同样,一个典型的makefile(至少根据我的经验)没有明确列出标头依赖关系;相反,它依赖于编译器选项来自动生成这些依赖关系列表(对于gcc,该选项是-M
)。有关示例,请参阅here。
答案 5 :(得分:0)
我了解到,“目标”和“输出文件”名称必须完全匹配,以使 make 能够识别是否不需要重新编译。因此,在Windows环境下(如我尝试过mingw32-make.exe
的 make ),应该是这样的:
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