Linux环境基础开发工具的使用(下)

文章目录

  • Linux编译器 - gcc/g++
    • gcc/g++如何使用
    • 预处理阶段
    • 编译阶段
    • 汇编阶段
    • 链接阶段
    • gcc选项汇总
    • 静态库与动态库
    • gdb命令汇总
  • Linux项目自动化构建工具 - make/Makefile
    • make/Makefile的意义
    • 使用make/makefile
    • 原理

Linux编译器 - gcc/g++

  • 背景知识

我们知道一个代码写完要变为可执行程序需要经过以下四个步骤

  1. 预处理(进行宏替换)
  2. 编译(生成汇编)
  3. 汇编(生成机器可识别代码)
  4. 连接(生成可执行文件或库文件)

我们知道在Linux系统不区分文件后缀,因此文本文件可以设置后缀为txt来告诉用户这是一个文本文件,但是对于Linux下的各种程序是区分后缀的,而gcc和g++它们是要看文件后缀的!

gcc/g++如何使用

  • gcc只可以编译C语言
  • g++C和C++都可以编译

语法:gcc [选项] 要编译的文件 [选项] [目标文件]
gcc code.c -o code

-o 将处理结果输出到指定文件,该选项后需紧跟输出文件名。(后面会谈到常用选项对应的作用)

Linux环境基础开发工具的使用(下)_第1张图片

预处理阶段

  • 作用
  • 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
  • 预处理指令是以#号开头的代码行。
  • 实例: gcc –E code.c –o code.i
  • 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
  • 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序

Linux环境基础开发工具的使用(下)_第2张图片

编译阶段

  • 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。
  • 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码
  • gcc –S code.i –o code.s

Linux环境基础开发工具的使用(下)_第3张图片

汇编阶段

  • 汇编阶段是把编译阶段生成的“.s”文件转成目标文件
  • 读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了
  • gcc -c code.s -o code.o

Linux环境基础开发工具的使用(下)_第4张图片

链接阶段

  • 在成功编译之后,就进入了链接阶段。
  • gcc code.o -o code
  • 链接后生成的也是二进制文件。
    注意
  1. gcc/g++不带-E、-S、-c选项时,就默认生成预处理、编译、汇编、链接全过程后的文件。
  2. 若不用-o选项指定生成文件的文件名,则默认生成的可执行文件名为a.out。

gcc选项汇总

  • -E 只进行预处理,这个不生成文件,你需要把他重定向到一个输出文件里面(否则将把预处理后的结果打印到屏幕上)。
  • -S 编译到汇编语言,不进行汇编和链接,即只进行预处理和编译。
  • -c 编译到目标代码
  • -o 将处理结果输出到指定文件,该选项后需紧跟输出文件名。
  • -static 此选项对生成的文件采用静态链接。
  • -g 生成调试信息(若不携带该选项则默认生成release版本)。
  • -shared 此选项将尽量使用动态库,生成文件较小。
  • -w 不生成任何警告信息。
  • Wall 生成所有警告信息。
  • -O0/-O1/-O2/-O3 编译器优化选项的四个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高。

静态库与动态库

  • 静态库是指编译链接时,把库文件的代码全部加入到可执行文件当中,因此生成的文件比较大,但在运行时也就不再需要库文件了,静态库一般以.a为后缀。
  • 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件当中,而是在程序运行时由链接文件加载库,这样可以节省系统的开销,动态库一般以.so为后缀。
    动态链接:
     优点:省空间(磁盘的空间,内存的空间),bin体积小,加载速度快。
     缺点:依赖动态库,程序可移植性较差。
    静态链接:
     优点:不依赖第三方库,程序的可移植性较高。
     缺点:浪费空间。
    **加粗样式**
    我们也可以在最后加上 -static
    Linux环境基础开发工具的使用(下)_第5张图片
    这也证明了动态链接比较节省空间,而静态链接比较浪费空间。

小tips:如果出现下面这种情况
在这里插入图片描述
//安装指令
sudo yum install glibc -static //c静态库
sudo yum install libstdc++ -static //c++静态库

  • 程序的发布方式有两种,debug模式和release模式
  • Linux gcc/g++出来的二进制程序,默认是release模式
  • 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上-g 选项

在Linux当中gcc/g++默认生成的可执行程序是release版本的,是不可被调试的。如果想生成debug版本,就需要在使用gcc/g++生成可执行程序时加上-g选项。
在这里插入图片描述
gdb使用语法 gdb + 文件名
Linux环境基础开发工具的使用(下)_第6张图片

gdb命令汇总

调试

  • run/r:运行代码
  • next/n:逐过程调试。
  • step/s:逐语句调试。
  • until 行号:跳转至指定行。
  • finish:执行完当前正在调用的函数后停下来(不能是主函数)。
  • continue/c:运行到下一个断点处。

显示

  • list/l n:显示从第n行开始的源代码,每次显示10行,若n未给出则默认从上次的位置往下显示.。
  • list/l 函数名:显示该函数的源代码。
  • print/p 变量:打印变量的值。
  • print/p &变量:打印变量的地址。
  • print/p 表达式:打印表达式的值,通过表达式可以修改变量的值。
  • display 变量:将变量加入常显示(每次停下来都显示它的值)。
  • display &变量:将变量的地址加入常显示。
  • undisplay 编号:取消指定编号变量的常显示。
  • bt:查看各级函数调用及参数。
  • info/i locals:查看当前栈帧当中局部变量的值。

断点

  • break/b n:在第n行设置断点。
  • break/b 函数名:在某函数体内第一行设置断点。
  • info breakpoint/b:查看已打断点信息。
  • delete/d 编号:删除指定编号的断点。
  • disable 编号:禁用指定编号的断点。
  • enable 编号:启用指定编号的断点。

退出

  • quit/q:退出gdb。

Linux项目自动化构建工具 - make/Makefile

make/Makefile的意义

  • 一个工程的源文件不计其数,按照其类型、功能、模块分别放在若干个目录当中,Makefile定义了一系列的规则来指定:哪些文件需要先编译,哪些文件需要后编译,甚至于进行更复杂的功能操作。
  • Makefile带来的好处就是“自动化编译”,一旦写好,只需一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make是一条命令,Makefile是一个文件,两个搭配使用,完成项目自动化构建。

使用make/makefile

依赖关系

文件A的变更会影响到文件B,那么就称文件B依赖于文件A。
eg:code.o文件是由code.c文件通过预处理、编译以及汇编之后生成的文件,所以code.c文件的改变会影响code.o,所以说code.o文件依赖于code.c文件。

  • 多个源文件如何编译???在这里插入图片描述
  1. 直接gcc多个源文件进行编译 ,一步到位
  2. 先用每个源文件各自生成自己的二进制文件,然后再将这些二进制文件通过链接生成可执行程序。gcc -cLinux环境基础开发工具的使用(下)_第7张图片
    若是直接使用源文件生成可执行程序,那么其中一个源文件进行了修改,再生成可执行程序的时候就需要将所以的源文件重新进行编译链接。
    而若是先用每个源文件各自生成自己的二进制文件,那么其中一个源文件进行了修改,就只需重新编译生成该源文件的二进制文件,然后再将这些二进制文件通过链接生成可执行程序即可。
    编译链接的时候不需要加上头文件,因为编译器通过源文件的内容可以知道所需的头文件名字,而通过头文件的包含方式(“尖括号”包含和“双引号”包含),编译器可以知道应该从何处去寻找所需头文件。

Linux环境基础开发工具的使用(下)_第8张图片
注: 一般将这种clean的目标文件设置为伪目标,用.PHONY修饰,伪目标的特性是:总是被执行。
Linux环境基础开发工具的使用(下)_第9张图片

原理

  • make会在当前目录下找名字为“Makefile”或“makefile”的文件。
  • 如果找到,它会找文件当中的第一个目标文件,在上面的例子中,它会找到mytest这个文件,并把这个文件作为最终的目标文件。
  • 如果mytest文件不存在,或是mytest所依赖的后面的test.o文件和main.o文件的文件修改时间比mytest文件新,那么它就会执行后面的依赖方法来生成mytest文件。
  • 如果mytest所依赖的test.o文件不存在,那么make会在Makefile文件中寻找目标为test.o文件的依赖关系,如果找到则再根据其依赖方法生成test.o文件(类似于堆栈的过程)。
  • 当然,你的test.c文件和main.c文件是存在的,于是make会生成test.o文件和main.o文件,然后再用test.o文件和main.o文件生成最终的mytest文件。
  • make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
  • 在寻找的过程中,如果出现错误,例如最后被依赖的文件找不到,那么make就会直接退出,并报错。

你可能感兴趣的:(linux,服务器)