gcc编辑参数:
-v/–version: 查看gcc的版本信息
-I: 指定编译时的头文件路径
-L: 指定库文件路径
-c: 将汇编文件生成二进制文件,即生成.o中间文件
-o: 生成指定的目标文件, 注:-o与-c不可一起使用
-D: 编译时定义宏并传入到程序中
-g: 编译时需要在目标文件中生成调试信息,则gdb调试时需要用到
-Wall: 显示编译过程中产生的警告信息
-On: 优化代码,n是优化级别:1、2、3,最高是3
示例:gcc -I./include -DDEBUG=1 -Wall -O3 add.c dlv.c mul.c main.c -o app
生成静态库
生成.o文件:gcc -c -I/include add.c dlv.c mul.c
将.o文件打包成静态库libcalc.a:ar -rsc libcalc.a add.o dlv.o mul.o
引用静态库:gcc -I./include main.c -L./ -lcalc -o app
生成动态库
生成.o文件:gcc -c -fPIC -I./include add.c dlv.c mul.c
生成.so动态库:gcc -shared -I./include add.o dlv.o mul.o -o libcalc.so
引用动态库:gcc -I./include main.c -lcalc -o app
在执行程序时需要将动态库的路径设置到系统环境变量中,或将动态库复制到可访问的路径中。
makeflie
makefile文件的规则如:
# 以‘#’号开头表示注释
#可以定义变量
dir = /home/test
#目标: 依赖条件
# 执行命令 #执行命令前面必须以tab键开头
#如:
app: main.o #app即为目标,main.o为依赖条件
gcc main.o -o app #执行的命令
有如下源码:
root@root-virtual-machine:~/gcc_test/libTest$ tree
.
├── add.c
├── dlv.c
├── include
│ └── head.h
├── main.c
└── mul.c
构建makefile版本1如下:
app: add.o dlv.o mul.o main.o
gcc -I./include add.o dlv.o mul.o main.o -o app
add.o: add.c
gcc -c -I./include add.c
dlv.o: dlv.o
gcc -c -I./include dlv.c
mul.o: mul.c
gcc -c -I./include mul.c
main.o: main.c
gcc -c -I./include main.c
在makefile文件中,会检测依赖是否存在,不存在则会向下搜索,基原理是:
-
检测依赖是否存在:
- 依赖不存在,则向下搜索规则,如果有规则是用来生成所查找的依赖的则执行规则下的命令,如搜索到的规则中还存在依赖,则递归执行,直到返回所需的依赖,找不到则提示错误
- 依赖存在,则判断依赖是否需要更新(在makefile中只重新编译生成有更新的源文件)
- 更新原则:当前规则目标的时间 > 依赖的时间,则不更新新立即返回,否则断续执行下面的命令生成新依赖(即当前规则的目标)
构建makefile版本2
引用变量,减少冗余字符:
target =app inc = -I./include obj = add.o dlv.o mul.o main.o $(target): $(obj) gcc $(inc) $(obj) -o app add.o: add.c gcc -c $(inc) add.c dlv.o: dlv.c gcc -c $(inc) dlv.c mul.o: mul.c gcc -c $(inc) mul.c main.o: main.c gcc -c $(inc) main.c
构建makefile版本3
引入通配符及makefile中的固定的变量
-
makefile自带的变量:
- CPPFLAGS
- CC
-
自动变量:(自动变量只能在规则中使用)
- $@:规则中的目标
- $<:规则中的第一个依赖
- $^:规则中所有的依赖
target =app
inc = -I./include
obj = add.o dlv.o mul.o main.o
$(target): $(obj)
gcc $(inc) $^ -o $@
%.o: %.c
gcc -c $(inc) $<
构建makefile版本4
引入makefile中的函数,所有的函数都是有返回值的,所以一般都是用变量来承接函数的返回值
- wildcard:查找指定目录下指定类型的文件,如
- src = $(wildcard ./*.c)
- patsubst:匹配替换,如
- obj = ( p a t s u b s t (patsubst %.c, %.o, %(src)) #即把从 (patsubst(src)中返回的字符吅中的 %.c 替换为%.o
inc = -I./include
src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src))
$(target): $(obj)
gcc $(inc) $^ -o $@
%.o: %.c
gcc -c $(inc) $<
构建makefile版本5
-
在执行make时,如不带参数,则默认执行从makefile文件第一行开始遇到的第一个目标,如需要执行指定的目标则可以在,make 时加上目标名,如
- make test //则会执行test下面的命令
-
为方便每次编译前清除原有.o文件、执行文件,可以编写一个清理项目的规则,如
-
clean:
rm -f $(obj) $(target)
-
-
在执行make + 目标时,如目标名称与当前目录中的某个文件或文件夹相同时,会执行失败,因此可以声明伪目标.PHONY(伪目标的声明字符是固定,即(.PHONY)),并将目标作为伪目标的依赖,如
- .PHONY: clean
-
如果目标下面有多条执行命令,为了避免在执行某条命令时失败,导致后面的命令无法执行,则可以在命令前面添加 ”-“ 符号,如
-
clean:
#删除一个不存在的文件会报错,这样后面的命令就无法执行,而加上”-“后就可以正常执行了
-rm aaa
rm -f $(obj) $(target)
-
target =app
inc = -I./include
src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src))
$(target): $(obj)
gcc $(inc) $^ -o $@
%.o: %.c
gcc -c $(inc) $<
test:
ls -l /home
.PHONY: clean
clean:
-rm aa
rm -f $(obj) $(target)
gdb调试
在编译时加上 -g 子命令,则会在执行文件生成可用于调试的信息,然后才能使用gdb进行调试。
加上-g后会保留函数名和变量名
启动gdb
1) gdb app //启动后进入gdb的交互命令界面
set args aaa bbb ccc //set args 表示给程序传递参数
start //运行一行,
r //run, 表示运行,当遇到第一个断点时停顿
c //跳往下一个断点
l //即list的缩写,也可以用list,用于显示源码信息
l n //命令显示源码, n表示文件的行号
l 文件名:n //表示显示指定的源文件的第n行
l test.c:15 //表示显示test.c的第15行
l 文件名:函数名 //表示显示指定的源文件中某个函数
l test.c:add //表示显示指定文件中的add函数
set listsize n //设置每次显示的总行数,n表示总行数
show listsize //查看当前每次显示的总行数大小
b n //或break,设置断点,n 表示行数
i b //或info, 查看设置过的断点
d n //或del,表示删除某个行的断点,n为行数
d n n+n //表示删除某个区间中的断点,n 到 n+n行之间的断点
d n-(n+n) //表示删除n及n+n这两个位置上的断点
dis n //表示禁用某个断点,n表示断点所在的行数
ena n //表示启用某个断点,n表示断点所在的行数
b n if 变量==var //设置条件断点
p 变量 //查看变量当前的值
ptype 变量 //打印变量类型
next - n // 向下单步调试,遇到函数时,不会进入函数体
step -s //向下单步调试,遇到函数时,会进入到函数体内
finish //从函数中退出,但必须保证后面已经没有断点了
display 变量名 //自动显示变量的值
undisplay n //取消自动显示,n表示编号
display arr[i] //在循环中连接查看数组的元素的值
set var 变量名 = 5 //设置循环中变量的值
until //跳出循环,但循环内部有断点时,需要先将断点取消或禁用
step //查看当前所处的位置