-
makefile网址:跟我一起写Makefile — 跟我一起写Makefile 1.0 文档
-
本质
-
是一个工程管理文件
-
作用
-
简化编译流程
-
-
-
理论基础
-
gcc 分步编译(4步)
-
预处理->编译->汇编->链接
-
-
makefile
-
将.c文件生成二进制文件.o(汇编)
-
使用.o文件完成最后的链接过程
-
-
-
文件的作用
-
简化了编译流程,不需要将全部源文件重新编译
-
如果源文件发生修改,只需要重新编译发生修改的源文件即可,节省了编译时间
-
Makefile会检查文件的时间戳,如果有文件时间戳更新(改文件就会重新生成
-
-
make工具
-
读取make文件
-
默认执行第一个目标
-
只写一条规则,会自动推导前面的运行过程
-
-
当目录下有Makefile和makefile 两个文件时,默认读取小写字母开头的文件
-
make的标准使用格式:
-
make 目标
-
直接运行Makefile中指定目标的那条规则
-
-
make -f 指定文件
-
make -f 文件名 目标名
-
不读入默认文件,读入指定文件的指定目标
-
-
-
makefile文件是make工具的唯一读入文件
-
-
Makefile文件的书写
-
由规则,变量,条件编译及函数构成
-
-
规则的构成
-
由多条规则构成,每一条规则包含
-
目标:依赖 <Tab>编译指令
-
一般指令是依赖生成目标的过程
-
指令前不是Tab键而是四个空格则会报错
-
-
-
一条规则中一定要有一个目标,一条规则中可以有多个依赖
-
一条规则可以没有依赖,只执行某些指令
-
一条规则可以没有指令,只描述目标和依赖之间的关系
-
-
第一版Makefile
-
all:fun fun.o:fun.c gcc -c fun.c -o fun.o fun:fun.o main.o gcc fun.o main.o -o fun main.o:main.c gcc -c main.c -o main.o clean: rm *.o fun
-
如果依赖的时间戳比目标的时间戳更新,目标会重新生成
-
只写一条规则,Makefile会进行自动推导(Makefile在每次运行前,会自动生成文件依赖树)
-
-
-
make中的变量
-
变量赋值
-
=
-
递归赋值
-
变量名 = 变量的值 (Makefile中赋值运算符两侧可以有空格也可以没有空格)
-
获取变量的值为其最后一次赋值的结果
-
调用时不管是在最后一次赋值前还是后
-
-
-
-
:=
-
立即赋值
-
赋值为当前值
-
-
-
+=
-
追加赋值
-
连续赋值多次,且不覆盖
-
将这一次的值添加在之前值的后面,并用空格隔开
-
-
-
-
?=
-
条件赋值
-
只能被赋值一次,相当于常量,不可修改
-
-
-
使用变量的值:${}、$()、$
-
推荐使用$()和shell脚本做区分
-
-
-
-
第二版Makefile
-
引入变量
-
EXE=fun
-
保存可执行文件
-
-
OBJs+=fun.o
-
OBJs+=main.o
-
CC=gcc
-
Makefile中表示使用的编译器的自动变量
-
-
CFLAGS=-c -o
-
保存编译参数
-
-
-
EXE=FUN OBJs+= fun.o OBJs+=main.o CC=gcc CFLAGS=-c -o all:$(EXE) $(EXE):$(OBJs) $(CC) $(OBJs) -o $(EXE) fun.o:fun.c $(CC) $(CFLAGS) -c -o fun.o fun.c main.o:main.c $(CC) $(CFLAGS) -c -o main.o main.c clean: rm $(OBJs) $(EXE)
-
引入自动变量和通配符
-
自动变量
-
$@:所有的目标
-
$^:所有的依赖
-
$<:第一个依赖
-
针对于一条规则而言的, 不是针对整个Makefile文件
-
-
-
EXE=FUN OBJs+= fun.o OBJs+=main.o CC=gcc CFLAGS=-c -o all:$(EXE) $(EXE):$(OBJs) $(CC) $^ -o $@ %.o:%.c $(CC) $(CFLAGS) $@ $^ clean: rm $(OBJs) $(EXE)
-
-
-
第三版Makefile
-
引入通配符:
-
*:通配所有情况
-
%:是一种(字符串的)模式匹配,在Makefile中的作用是,有一个.o,就匹配一个同名的.c
-
%.o:%c
-
从上一条规则中,获取到需要两个.o文件,fun.o和main.o,使用%进行模式匹配,
-
%匹配相同的部分,有一个fun.o就能匹配到一个fun.c,有一个main.o就能匹配到一个main.c
-
-
-
EXE=FUN OBJs+= fun.o OBJs+=main.o CC=gcc CFLAGS=-c -o all:$(EXE) $(EXE):$(OBJs) $(CC) $^ -o $@ fun.o:fun.c $(CC) $(CFLAGS) $@ $^ main.o:main.c $(CC) $(CFLAGS) $@ $^ clean: rm $(OBJs) $(EXE)
-
-
伪目标
-
在makefile中有些目标并不需要生成文件,也没有文件依赖,往往把这样的目标定义为伪目标,为了防止因为同名文件而不能执行目标的情况发生
-
clean
-
直接将目标定义为伪目标 .PHONY : clean 将clean定义为伪目标
-
-
伪目标的作用
-
不会检查时间戳,直接执行规则中的内容
-
-
-
引入函数
-
make工具内置函数是帮助程序员查找文件信息的,所以要求在查找路径下,只有程序需要的.c文件,没有其他程序的.c文件
-
wildcard
-
根据给定的条件,获取指定的文件名(找文件名的功能)
-
$(wildcard 指定字符串的格式)
-
$(wildcard *.c)
-
找到当前路径下,所有.c文件的文件名
-
-
-
patsubst
-
模式匹配替换字符串
-
$(patsubst 源格式,目标格式,要替换的字符串)
-
$(patsubst %.c,%.o,1.c 2.c)
-
获取到1.c和2.c字符串,根据模式匹配,得到1.o和2.o中字符串
-
-
每一个参数之间以逗号作为分隔,要替换的字符串之间以空格作为分隔
-
-
-
第四版Makefile
-
引入内置函数
-
EXE=fun #保存可执行文件 FILES=$(wildcard *.c) #保存了所有.c文件的文件名 OBJs=$(patsubst %.c,%.o,$(FILES)) #使用patsubst将所有的.c字符串替换成.o字符串 CC=gcc #Makefile中表示使用的编译器的自动变量 CFLAGS=-c -o #保存编译参数 all:$(EXE) $(EXE):$(OBJs) $(CC) $^ -o $@ %.o:%.c $(CC) $(CFLAGS) $@ $^ .PHONY:clean #将clean定义为伪目标 clean: @rm $(OBJs) $(EXE) #@取消指令的回显
-
-
gdb调试工具
-
用于调试代码中的逻辑错误,而非语法错误
-
gdp调试流程
-
生成可以使用gdb调试的可执行文件
-
gcc -g xxx.c
-
生成的a.out文件可以使用gdb调试
-
-
进入gdb工具
-
gdb 可执行文件名
-
使用gdb工具开始调试可执行文件
-
-
-
查看源文件内容
-
l(list):查看.c文件的前10行,如果代码超出10行,再输入l
-
-
工具指令
-
b 行号
-
在指定行数打断点
-
-
r
-
让程序运行,会停在断点处
-
-
n
-
让程序向下执行一步 (如果碰到函数,不能进入函数内部)
-
-
s
-
让程序向下执行一步 (如果碰到函数,可以进入函数内部,继续执行)
-
-
p 变量名
-
打印变量的值
-
-
q
-
quit退出gdb工具
-
-
-
-
调试core文件
-
core何时生成:当程序出现重大错误时,会生成一个临时的镜像文件,保存程序状态(段错误)
-
由于系统的权限问题,不是每一次段错误都会生成core文件
-
ulimit -a 查看文件的权限
-
help ulimit
-
core file size如果为0该文件不会生成
-
ulimit -c unlimited 使用指令取消限制
-
若上面的指令不能执行,则执行以下指令
-
sudo bash -c "echo core > /proc/sys/kernel/core_pattern"
-
-
需要同时gdb 可执行文件和core文件
-
gdb a.out core
-
程序会停在发生错误的一行
-
-
-
调试正在运行的程序
-
需要在后台终端运行可执行文件
-
./a.out &
-
会终端回显进程号
-
ps -ajx | grep a.out
-
查找指定进程的进程号
-
-
-
gdb -p 进程号
-
-
-