Linux编译与调试
环境:Ubuntu16.04
编译
对于C语言,gcc
- -v 查看gcc版本号
- -I 指定头文件目录,注意-I和之间没有空格(例:gcc main.c -I../include -o app)
- -c 只编译,生成.o文件,不进行链接
- -g 包含调试信息 -On n=0~3 编译优化,n越大优化得越多
- -Wall 提示更多警告信息
- -D 编译时定义宏,注意-D和之间没有空格
- -E 生成预处理文件
- -M 生成.c文件与头文件依赖关系以用于Makefile,包括系统库的头文件
- -MM 生成.c文件与头文件依赖关系以用于Makefile,不包括系统库的头文件
对于C++,编译命令:
g++ main.c -std=c++11 -o app
调试
gcc 1.c -g -o app
gdb app
注:如果想进行调试,必须加-g,否则会出现以下情况:
- 进入调试:gdb 可执行文件名字
- 退出调试:quit(q)
- 查看代码:list(l) 行号(注:list显示10行代码,从当前行开始,上下一共10行)
- 开始调试:start(停在main函数的第一行)
- 逐过程:next(n) (逐过程,有函数跳到函数里面去执行)
- 逐语句:step(s) (逐语句,把函数当成一条语句,不进入函数,继续执行下一条语句)
- 继续执行上一条命令:回车 (例如我们上一次执行s命令,按下回车,继续执行s命令)
- 查看变量值:p 变量名
- 持续监控变量:display 变量名
- 结束持续监控变量:undisplay 变量编号
- 开始调试:run(运行到第一个断点处,如果没有断点则直接运行到函数结尾)
- 下断点:break(b) 行号/函数名
- 查看断点信息:info breakpoints
- 继续运行到下一个断点处:continue(c)
- 临时禁用断点:disable 断点编号
- 取消禁用断点:enable 断点编号
makefile
makefile文件(项目管理工具),是GNU工具链的一部分。
一、优点:
- 重用性极强(一次编写终身受益),可以反复使用管理不同的项目
- 便捷的编译管理代码,不用每次书写复杂的编译命令
- 节省编译时间
- 编译时间分为:编译期(预编译、编译、汇编)+链接期(把所有的.o文件链接生成可执行文件)
- 编译期:源文件.c编译生成.o文件
- 第一次编译的时候不会节省编译时间,会保存所有生成的中间文件.o文件,下一次编译的时候只编译修改的源文件,重新生成.o文件,没有修改的源文件直接使用保存的.o文件,一起链接生成可执行文件。
- 怎么判断源文件是否被修改?比较源文件的修改时间和.o文件的生成时间,如果源文件的修改时间比.o文件的生成时间更新,说明生成.o文件以后源文件又被修改过,需要重新编译。
二、命名:必须以makefile或Makefile命名
三、注释:#
四、执行makefile文件:make
五、makefile三要素:
- 目标:完成编译,生成可执行文件,可执行文件的名字就是目标
- 依赖:源文件或者资源文件根据依赖生成日标要执行的命令
- 命令:根据依赖生成目标要执行的命令
目标:依赖
命令(命令前用Tab键)
makefile使用示例:
示例一:
执行make命令即可。
示例二:
makefile执行原理和注意事项:
- 自顶向下建立依赖关系
- 默认只有一个最终目标,可以有多个中间目标
makefile变量定义和使用
1、自定义变量
- 没有数据类型,默认都是字符串类型
- 变量名可以由字母、数字、下划线构成,不能以数字开头,为了与高级语言区分,一般都使用全大写
- 使用:$(变量名)
2、内置
- $@:表示目标名,随着目标名字的变化而变化
- $^:表示所有依赖项
- $<:表示第一个依赖项
示例三:
如上,当我们只修改了makefile文件,其余的没有进行修改时,会提示当前已是最新,这是我们只需要删除所有.o文件,重新执行make命令即可。
内置函数和内建语法:
- wildcard文件名处理函数:获取某个路径下的所有文件名
- SOURCEFILE=$(wildcard *.c)
#获取当前路径下所有.c文件的名字,存到变量SOURCEFILE中
#SOURCEFILE=main.c add.c sub.c des.c mul.c- patsubst字符串处理函数
DFILE=$(patsubst %.c,%.o,$(SOURCEFILE))
#使用patsubst把SOURCEFILE里面的所有.c文件名字变成.o文件
#DFILE=main.o add.o sub.o des.o mul.o
示例四:
示例三中代码可改写成以下形式:
常用变量
- TARGET=myapp#存储目标名字
- cc=gcc#用于存储编译器版本
- INCLUDE_PATH=../include#储头文件路径
- LIBRARY_PATH=../lib#存储库文件路径
- INSTALL_PATH=/usr/bin#存储安装路径
- CFLAGS=-I$(INCLUDE_PATH) -c -Wall#存储编译选项(或加-g...)
- CPPFLAGS=-D#预处理选项
示例五:
示例四中代码可改写成以下形式,提高makefile的复用性,后续只需要对宏进行修改即可。
功能目标:没有依赖,只有命令
- 删除
clean:
rm -rf $(DFILE) $(TARGET)
- 安装
install:
sudo cp $(TARGET) $(INSTALL_PATH)
- 卸载
uninstall:
sudo rm -rf $(INSTALL_PATH)/$(TARGET)
- 输出
output :
echo $(INSTALL PATH)/$(TARGET)
示例六:
执行clean功能:make clean
如有错误,欢迎交流指正!