gcc参数 & makefile语法 & gdb调试

本文详细介绍了GCC的常用编辑参数,包括查看版本、指定头文件路径、生成.o文件、编译优化等。接着讲解了如何生成静态库和动态库,并给出了示例。接着探讨了Makefile的编写,包括依赖检查、变量引用、通配符使用、函数应用等不同版本的构建。最后,详细阐述了GDB调试技巧,包括设置断点、查看源码、查看变量值等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 //查看当前所处的位置

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值