Makefile概述
Makefile重要性
会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力

Makefile概述
Makefile 文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建哪些库文件以及如何创建这些库文件、如何最后产生我们想要的可执行文件
“自动化编译”:一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
提升编译效率:再次编译,只编译修改的文件
Makefile的基本语法
target... : prerequisites ...
command
target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。(任意的Shell命令)
以该项目为例
#一步编译.c -> exe
#test:fun.c main.c
# gcc fun.c main.c -o test
#两步编译.c -> .o -> exe
test:main.o fun.o
gcc main.o fun.o -o test
fun.o:fun.c
gcc -c fun.c -o fun.o
main.o:main.c
gcc -c main.c -o main.o
.PHONY:clean
clean:
rm *.o testMakefile和make的关系
make是一个命令工具,它解释Makefile 中的指令。
Makefile的变量
Makefile定义变量的目的
用来代替一个文本字符串:
系列文件的名字
传递给编译器的参数
需要运行的程序
需要查找源代码的目录
你需要输出信息的目录
你想做的其它事情。
自定义变量
x = a 变量在声明时需要给予初值
$(x)或${x} 取值
如果你要使用真实的 $ 字符,那么你需要用 $$ 来表示。
变量的赋值
#自定义变量
#X = a
# '='取最后一次X的值赋值给Y
#Y = $(X)
# := 覆盖式赋值
#Y := $(X)
# += 追加式赋值
#Y += c
# ?= 先判读之前是否定义赋值过
#Y ?= d
#X = b
#SRC = main.o fun.o
SRC = main.o
SRC += fun.o
#all伪目标,一般用来指定最终要生成的文件,尤其是多个目的的时候
all:test
#echo $(X)
#echo ${Y}
#两步编译.c -> .o -> exe
test:$(SRC)
gcc $(SRC) -o test
# @是为了隐藏命令的打印,直接输出命令的结果
#@echo $(X)
#@echo ${X}
fun.o:fun.c
gcc -c fun.c -o fun.o
main.o:main.c
gcc -c main.c -o main.o
.PHONY:clean
clean:
rm *.o teststar@star-HP13-Ubuntu:~/Codes/day10/code/Makefile1$ make
gcc -c main.c -o main.o
gcc -c fun.c -o fun.o
gcc main.o fun.o -o test
# @是为了隐藏命令的打印,直接输出命令的结果
#@echo
#@echo
#echo
#echo
自动变量
$* 不包含扩展名的目标文件名称
$+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$< 第一个依赖文件的名称
$? 所有时间戳比目标文件晚的的依赖文件,并以空格分开
$@ 目标文件的完整名称
$^ 所有不重复的目标依赖文件,以空格分开
#自动变量
SRC = main.o fun.o
all:test
#两步编译.c -> .o -> exe
test:$(SRC) main.o
gcc $^ -o $@
# $^ 不包含重复文件的所有依赖文件
echo $^
# $+ 包含重复文件的所有依赖文件
echo $+
# $< 第一个依赖文件
echo $<
# $? 更新的依赖文件
echo $?
#fun.o:fun.c
%.o:%.c
#gcc -c fun.c -o fun.o
gcc -c $< -o $@
# $*不包含后缀名的目标文件名
echo $*
# $@ 包含后缀名的目标文件名
echo $@
#main.o:main.c
# gcc -c $< -o $@
.PHONY:clean
clean:
rm *.o test
star@star-HP13-Ubuntu:~/Codes/day10/code/Makefile2$ make
#gcc -c fun.c -o fun.o
gcc -c main.c -o main.o
# main不包含后缀名的目标文件名
echo main
main
# main.o 包含后缀名的目标文件名
echo main.o
main.o
#gcc -c fun.c -o fun.o
gcc -c fun.c -o fun.o
# fun不包含后缀名的目标文件名
echo fun
fun
# fun.o 包含后缀名的目标文件名
echo fun.o
fun.o
gcc main.o fun.o -o test
# main.o fun.o 不包含重复文件的所有依赖文件
echo main.o fun.o
main.o fun.o
# main.o fun.o main.o 包含重复文件的所有依赖文件
echo main.o fun.o main.o
main.o fun.o main.o
# main.o 第一个依赖文件
echo main.o
main.o
# main.o fun.o 更新的依赖文件
echo main.o fun.o
main.o fun.o
隐含变量
AR 库文件维护程序的名称,默认值为ar。
AS 汇编程序的名称,默认值为as。
CC C编译器的名称,默认值为cc。
CPP C预编译器的名称,默认值为$(CC) –E。
CXX C++ 编译器的名称,默认值为g++。
RM 文件删除程序的名称,默认值为rm -f
ARFLAGS 库文件维护程序的选项,无默认值。
ASFLAGS 汇编程序的选项,无默认值。
CFLAGS C编译器的选项,无默认值。
LDFLAGS 链接器的选项,无默认值
CPPFLAGS C预编译的选项,无默认值。
CXXFLAGS C++编译器的选项,无默认值。
#自动变量
SRC = main.o fun.o
CFLAGS = -c -Wall -I /home/star/Codes/day10/code/Makefile3/include
LDFLAGS = -lm
all:test
echo $(CC)
echo $(CPP)
echo $(CXX)
echo $(CFLAGS)
echo $(LDFLAGS)
#两步编译.c -> .o -> exe
test:$(SRC) main.o
$(CC) $(LDFLAGS) $^ -o $@
%.o:%.c
$(CC) $(CFLAGS) $< -o $@
.PHONY:clean
clean:
$(RM) *.o test
star@star-HP13-Ubuntu:~/Codes/day10/code/Makefile3$ make
cc -c -Wall -I /home/star/Codes/day10/code/Makefile3/include main.c -o main.o
cc -lm main.o fun.o -o test
echo cc
cc
echo cc -E
cc -E
echo g++
g++
echo -c -Wall -I /home/star/Codes/day10/code/Makefile3/include
-c -Wall -I /home/star/Codes/day10/code/Makefile3/include
echo -lm
-lm