目录
导读
1. make/Makefile
1.1 引入
1.2 概念
1.3 语法规则
1.4 示例
2. Linux调试器-gdb
2.1 引入
2.2 概念
2.3 使用
我们在上次讲了Linux编辑器gcc\g++的使用,今天我们就来进一步的学习如何调试,以及makefile这个强大的工具。
会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的 规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂 的功能操作
在Linux中,make
是一个常用的构建工具,用于自动化构建和管理程序的编译过程。
make
工具通过读取一个叫做Makefile
的文件来执行编译和链接等操作。
Makefile
中包含了一系列的规则和指令,用于描述如何将源代码转换为可执行程序。
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一 种在工程方面的编译方法。
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
Makefile语法规则包括目标、依赖关系和命令。
1. 目标(Target):指定要构建的文件或操作的名称。目标是make
工具的主要执行对象。
target: dependencies
command
2. 依赖(Dependencies):规定目标所依赖的文件或操作。依赖关系用于确定何时需要重新构建目标。可以有多个依赖项,用空格分隔。
target: dependency1 dependency2
command
3. 命令(Commands):描述了如何生成目标的命令。命令必须以制表符开始,并且在同一行上。可以有多个命令,每个命令占一行。
target: dependencies
command1
command2
4. 变量(Variables):可以在Makefile
中定义变量,用于存储常用的参数和选项。变量可以通过$(variable_name)
来引用。
variable_name = value
5. 注释(Comments):使用#
符号来添加注释。注释可以出现在任意位置,并且会被忽略。
# This is a comment
6. 伪目标(Phony Targets):有些目标不是实际的文件,而是用于执行特定操作的伪目标。可以使用.PHONY
声明伪目标。
.PHONY: target
7. 默认目标(Default Target):Makefile
可以指定一个默认的目标,当没有明确指定目标时,会执行默认目标。使用.DEFAULT_GOAL
指定默认目标。
.DEFAULT_GOAL := target
编写一个简单程序:
[zhy@centos7 ~]$ vim test.c
[zhy@centos7 ~]$ cat test.c
#include
int main()
{
printf("hello world\n");
return 0;
}
编写makefile文件:
其中 test 是的目标文件,也是我们的最终生成的可执行文件。
依赖文件就是 test.c源文件,然后使用我们的gcc命令,重建目标文件。
[zhy@centos7 ~]$ vim makefile
[zhy@centos7 ~]$ cat makefile
test: test.c
gcc -o test test.c
执行make命令:
执行make命令后,makefile文件里的 gcc -o test test.c 命令被执行,生成一个test可执行文件。
[zhy@centos7 ~]$ ls
111 a.out install.sh makefile test.c
[zhy@centos7 ~]$ make
gcc -o test test.c
[zhy@centos7 ~]$ ls
111 a.out install.sh makefile test test.c
[zhy@centos7 ~]$ ./test
hello world
继续编辑makefile文件:
clean
是一个伪目标,用于清理生成的目标文件和可执行文件。它的命令是删除test文件。.PHONY
声明了clean
是一个伪目标,防止与同名文件冲突。[zhy@centos7 ~]$ vim makefile
[zhy@centos7 ~]$ cat makefile
test: test.c
gcc -o test test.c
# 定义伪目标和命令
clean:
rm -f test
.PHONY: clean
再次执行make命令:
要清理生成的文件,可以执行make clean
命令。
[zhy@centos7 ~]$ ls
111 a.out install.sh makefile test test.c
[zhy@centos7 ~]$ make clean
rm -f test
[zhy@centos7 ~]$ ls
111 a.out install.sh makefile test.c
定义变量:
使用CC定义了编译器和编译选项的变量。
[zhy@centos7 ~]$ vim makefile
[zhy@centos7 ~]$ cat makefile
# 定义变量
CC = gcc
CFLAGS = -Wall -g
test: test.c
$(CC) -o test test.c
# 定义伪目标和命令
clean:
rm -f test
.PHONY: clean
我们在写编写C语言代码时难免会遇到一些解决不了的bug,这时我们会选择去进行调试,看看到底是哪一部分出现了错误,从而进一步的解决问题。
相对的,我们在Linux中编写程序时也可以进行调试。
GDB是一种强大的命令行调试器,可用于调试C、C++和其他编程语言的程序。
DB具有许多功能,包括设置断点、单步执行、查看变量值、查看内存内容、追踪函数调用等。它还支持多线程和多进程调试,可以与各种编译器和调试器一起使用。
程序的发布方式有两种,debug模式和release模式
Linux gcc/g++出来的二进制程序,默认是release模式
要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项
基本命令:
list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
list/l 函数名:列出某个函数的源代码。
continue(或c):从当前位置开始连续而非单步执行程序。
run(或r):从开始连续而非单步执行程序。
n 或 next:单条执行。
s或step:进入函数调用。
break(b) 行号:在某一行设置断点。
break 函数名:在某个函数开头设置断点。
info break :查看断点信息。
finish:执行到当前函数返回,然后挺下来等待命令。
print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数。
p 变量:打印变量值。
set var:修改变量的值。
delete breakpoints:删除所有断点。
delete breakpoints n:删除序号为n的断点。
disable breakpoints:禁用断点。
enable breakpoints:启用断点。
info(或i) breakpoints:参看当前设置了哪些断点。
display 变量名:跟踪查看一个变量,每次停下来都显示它的值。
undisplay:取消对先前设置的那些变量的跟踪。
until X行号:跳至X行。
breaktrace(或bt):查看各级函数调用及参数。
info(i) locals:查看当前栈帧局部变量的值。
quit:退出gdb。
示例:
编写一段代码:
[zhy@centos7 ~]$ vim project.c
[zhy@centos7 ~]$ cat project.c
#include
int main() {
int num1 = 5;
int num2 = 0;
int result;
result = num1 / num2;
printf("The result is: %d\n", result);
return 0;
}
将程序编译为可调试的可执行文件:
gcc -g project.c -o project
启动gdb调试器:
这将启动gdb,并显示(gdb)提示符。
gdb project
显示源代码:
list
设置断点:
这将在main
函数的开头设置一个断点。
break main
运行程序:
程序将开始执行,并在达到断点处停止。
run
单步执行:
这将单步执行程序,进入main
函数。
step
检查变量的值:
print num1
继续执行程序:
continue
检查错误:
continue命令之后会继续执行,程序会在除以0的地方崩溃。在运行到该语句时,gdb会停止并显示相关信息。