✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????
???????? 追风赶月莫停留 ????????
????????????????????????????????????????????????????????????????
???????? 平芜尽处是春山????????
????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
????Linux开发环境配置
- ????Linux编译器--gcc/g++使用
- ????程序执行
- ????预处理
- ????编译
- ????汇编
- ????链接
- ????动态库和静态库
- ????Linux调试器--gdb使用
- ????背景
- ????相关指令
- ????自动化构建工具--make/Makefile
- ????背景
- ????应用实例
????Linux编译器–gcc/g++使用
前面我们已经完成了vim的配置,接下来我们就要正式学习如何编译代码了,无论是C语言还是c++、java等计算机语言,在vim下编译,都要先在安装该指令,前面我们介绍的是Linux为cenos7版本现在我们是在ubuntu中,两者大径相同安装指令也差不多。如:安装c++语言编译器
yum install -y gcc-c++ //cenos7版本下
apt install -y gcc-c++ //ubuntu版本下
在Linux中gcc/g++执行指令:
gcc + -o + 指定文件名 + 原文件名 //c执行指令
g++ + -o + 指定文件名 + 原文件名 //c++执行指令
????程序执行
如上图中,test.c是提前写好的C语言程序文件,当我们使用gcc执行指令时间,系统会给我们生成一个绿色标注的文件,这个就是可执行文件。
当我们运行该可执行文件,就会打印输出我们提前准备好的信息。
????预处理
预处理是g++编译过程的第一步,它主要处理源代码中的伪指令(以#开头的指令,如宏定义、条件编译指令、包含指令等)和特殊符号。经过预处理过程后,会生成一个没有宏定义,没有条件编译指令、没有特殊符号(除了编译器需要的#pragma指令)的输出文件(通过以 .i 作为文件拓展名)。
在程序进行中查看预处理的指令:
gcc + -E + 原.c文件名 + -o + 定义.的i文件名
当我们输入执行指令后,会生成.i的文件,.i 文件就是预处理代码在此文件中,如下图,并且程序运行预处理阶段会自动停下来。
????编译
该阶段是编译过程的第二个阶段,它将预处理后的代码转换成汇编语言。在这个阶段,编译器会进行词法分析、语法分析、语义分析以及优化等操作。最终,编译器会生成一个汇编语言文件(通常以 .s 作为文件拓展名)。
在程序中查看编译阶段的指令:
gcc -S 原有的 .i 文件 + -o + 新定义的 .s 文件名
当我们输入编译指令时,系统会生成 .s 为拓展名的文件,该文件是存储编译阶段的汇编代码,如下图
????汇编
该阶段是编译过程中的第三个阶段,它将编译阶段生成的汇编语言文件转换成二进制格式的目标文件,这个过程涉及到将汇编指令翻译成机器指令,并生成最终可以在计算机上执行的代码。
在程序中查看汇编阶段的指令:
gcc + -c + 原.s文件 + -o 新定义.o文件名
当我们输入汇编执行指令,系统会生成一个以 .o 作为拓展名的文件,它里面是将汇编代码转换成二进制形式,所以我们看到的是乱码形式,如下图。
????链接
该阶段是编译过程中的第四个阶段,也是最后一个阶段。它主要将编译阶段和汇编阶段生成的目标文件以及所需的库文件组合成一个可执行文件。在这个过程中,链接器会解决所有符号引用,并将所有相关的代码和数据合并到一个文件中,使其能够在计算机上运行。
在程序中查看链接阶段的指令:
gcc + 原.o文件名 + -o + 新定义文件名
当我们输入链接执行指令,系统会生成一个test标绿的文件,这就是可执行文件,可以运行,如下图
????动态库和静态库
动态库是动态链接的库,动态库又被称为共享库,这是因为动态库中的内容是被所有程序共享的,就类似于一个功能块的程序,谁需要谁就可以调用它。gcc进行函数库的链接时可以选择静态链接还是动态链接,但是在Linux中系统默认是动态链接。
file是可以查看该文件的链接情况,也可以使用 ldd+文件名 来查看,只不过file查看的信息更详细,如下图
上图中libc.so是动态链接的标志,其中lib是前缀, .so是后缀,去掉前缀和后缀,最后为c,可以看出该文件调用的是C语言共享库,及动态链接。
静态库是采用静态链接的方式;静态链接不同于动态链接共享的方式,如果调用静态库,会将自己所需要的代码拷贝至程序中,完成拷贝后,后续将不需要再调用静态库。
如果想采用静态库的链接形式编译程序,需要再编译时加上-static选项,当然前提得有静态库,没有的话可以通过
apt install -y glibc-static
该指令下载静态库,当然我们也可以利用ldd 来查看文件是否为静态链接,如下图。
在实际过程中,动态库和静态库各有各的优点和缺点。
静态库
- 优点:不依赖库,同类型平台中都可以直接运行使用。
- 缺点: 可执行程序体积比较大,比较浪费资源、内存、网络等资源。
动态库:
- 优点: 节省资源,不会出现太多的重复代码。
- 缺点: 对库的依赖性较强,一旦库丢失,所有使用这个库的程序都无法运行。
????Linux调试器–gdb使用
????背景
gdb是GNU开源组织发布的一个强大的命令行调试工具,它在Linux操作系统下主要用于调试,使用多种编程语言(如C、C++、Java、Python等)编写的程序。GDB是一个功能强大的程序调试工具,它可以帮助开发人员更快地定位和修复程序中的缺陷,提高代码质量和开发效率。
GDB具有众多功能:
启动程序:GDB可以启动被调试的程序,并按照用户自定义的方式运行程序。
设置断点:用户可以在程序中任何需要的地方设置断点,当程序运行到这些断点时,会自动暂停执行,以便用户进行调试。
查看程序状态:在程序暂停时,用户可以查看程序的运行状态,包括变量值、寄存器内容、内存值以及堆栈信息等。
单步执行:GDB支持逐语句和逐过程两种单步执行方式,用户可以选择进入函数内部进行详细调试,也可以选择直接调用函数而不进入其内部。
修改程序:在调试过程中,用户还可以修改程序中的变量值或执行顺序,以验证程序的正确性。
使用该调试工具时,需要提前下载好:
sudo apt install -y gdb
????相关指令
指令 | 含义 |
---|---|
l+行号 | 显示指定行之后的代码(gdb会自动记录最后一条指令) |
b+行号/函数名/file:行号 | 对指定位置打断点 |
info+行号 | 查看我们所打的断点 |
d+断电编号 | 删除断点 |
disable/enable+断电编号 | 使能(禁用/开启)断电 |
n | 逐过程,也就vs调试中的F10(类似于逐行语句调试) |
s | 逐语句,也就vs调试中的F11(类似于能进入函数调试) |
p+变量 | 显示变量的内容和地址(可以查看变量的大小) |
display+变量名/变量地址 | 常显示 |
undisplay+编号 | 取消常显示变量的内容和地址 |
c | 从一个断电到下一个断电(范围查找) |
bt | 查看调用堆栈 |
finish | 将一个函数运行结束,就停下来(范围查找) |
until+行号 | 在一个范围内,直接运行到指定行(范围查找) |
????自动化构建工具–make/Makefile
????背景
在Linux系统中,自动化构建项目是提高开发效率、减少重复劳动的关键环节。其中,make工具和其配置文件Makefile是实现这一目标的重要工具组合。
make是一个在Linux下广泛使用的自动化构建工具,它可以根据一个Makefile文件中的指令来自动执行编译、链接等操作,从而生成一个可执行文件或者库文件。make工具通过读取Makefile文件(或makefile,不区分大小写),并根据文件中的指令执行相应的命令,这些命令通常包括编译、链接等,用于生成最终的可执行文件或库文件。
Makefile是一个文本文件,它包含了一系列的规则(rules)、目标(targets)、依赖(dependencies)和命令(commands)。每个规则定义了一个目标文件(通常是编译或链接的结果),以及生成该目标文件所需的依赖文件和要执行的命令。
????应用实例
make指令要搭配文件Makefile使用,两者缺一不可。
我根据test.c文件对大家进行实例演示:
- 创建Makefile文件
- 对test.c文件进行Makefile代码编写
上述图中,代码的含义是test可执行文件依靠的是test.c文件,而下面那行代码就是".c"文件生成".o"的可执行文件。
- 执行make
上面几步就是一个简单Makefile文件代码的编写,在实际使用该工具时,不会那么简单,既然有生成该可执行文件,那有没有删除的呢?
上述图中我间接使用了".PHONY"来执行clean,".PHONY"是一个伪目标,是Makefile文件中的一个关键字,意思为某个对象生成伪目标,这样就能在不对的源文件进行修改,重复执行任务了。
Makefile文件对make指令来说,第一个执行目标往往是优先权,仅仅只会执行主目标,也就是从上往下数的第一个执行目标,剩下的目标要执行就需要使用伪目标。
还有另外一种实际使用情况,现在这里是仅生成一个可执行文件,当我们需要同时能生成多个可执行文件时,就需要使用Makefile文件的另一个关键字"all","all"的意思大家都知道是全部的含义,所以在这里就是让make能够同时执行全部的目标文件,并且目标文件为test和today,如下图:
关于本章知识点如果有不足或者遗漏,欢迎大家指正,谢谢!!!