Linux开发工具

1.Linux编译器-gcc/g++使用

1、背景知识

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

我们为什么能在Windows/Linux上进行C/C++/其他形式开发,我们系统中一定要提前或后续安装C/C++开发相关的头文件和库文件。C/C++开发环境不仅仅指的是vs,gcc,g++,更重要的是语言本身的头文件和库文件。安装vs等时,在安装的时候,选择对应的开发包时,同步也在下载C/C++的头文件和库文件。

2、gcc如何完成

格式:gcc 选项 要编译的文件 选项 目标文件

预处理(进行宏替换)

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

编译(生成汇编)

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

汇编(生成机器可识别码)

  • 汇编阶段是将编译阶段生成".s"文件转成目标文件
  • 可以使用"-c"看到汇编代码转化成".o"的二进制目标代码
  • 实例:gcc -c hello.i -o hello.o,hello.o可重定位目标二进制文件,简称目标文件,.obj文件,不可以独立运行,虽然已经是二进制了,需要经过链接(链接库)才能执行

链接(生成可执行文件或者库文件)

  • 在成功编译之后就进入了链接阶段
  • 实例:gcc hello.o -o hello,将可重定位目标二进制文件,和库进行链接形成可执行程序

在这里涉及到一个重要的概念:函数库

  • 我们的C程序中,并没有定义"printf"的函数实现,且在预编译中包含的"stdio.h"中也只有该函数的声明,而没有定义函数的实现,那么是在哪里实现printf函数的?
  • 答案是:系统把这些函数实现都做到了名为libc.so.6的库文件中去了,在没有特别指定时,gcc回到系统默认的搜索路径"user/lib"下进行查找,也就是链接到libc.soo.6库函数中去,这样就能实现函数"printf"了,而这也就是链接的作用。

函数库一般分为静态库和动态库两种

  • 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不需要库文件了。其后缀名一般为".a"
  • 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样就可以节省系统的开销。动态库一般后缀名为".so",如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。完成了链接之后,gcc就可以生成可执行文件,如下:gcc hello.o -o hello
  • gcc默认生成的二进制程序,是动态链接的,这点可以通过file命令验证

ldd命令是Linux系统中用于显示一个可执行文件或共享库所依赖的共享库(动态链接库)以及这些库的实际加载路径的工具。
Linux中,编译形成可执行程序,默认采用的就是动态链接--提供动态库

Linux中,如果要按照静态链接的方式,进行形成可执行程序,需要添加-static选项--提供静态库

动态库不能缺失,一旦对应的动态库缺失,影响的不知一个程序,可能导致很多程序都无法正常运行!

动VS静

优点:

  • 动态库因为是共享库,有效的节省资源(磁盘空间,内存空间,网络空间等)
  • 静态库不依赖库,程序可以独立运行

缺点:

  • 动态库一旦缺失,导致整个程序都无法运行
  • 体积大,比较消耗资源

gcc选项

  • -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件中
  • -S 编译到汇编语言不进行汇编和链接
  • -c 编译到目标代码
  • -o 输出到可执行文件
  • -static 对生成的文件采用静态链接
  • -g 生成调试信息,GNU调试器可利用该信息
  • -shared 此选项将尽量使用动态库,所以生成的文件比较小,但是需要系统有动态库
  • -O0
  • -O1
  • -O2
  • -O3 编译器的优化选项的四个级别,-O0表示没有优化,-O1为缺省值,-O3级别最高
  • -w 不生成任何警告信息
  • -Wall 生成所有警告信息

2.Linux调试器-gdb使用

1、背景

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

2、使用

gdb binFill

退出:ctrl+d / quit

调试命令:

  • list / l 行号:显示源代码,接着上次的位置往下列,每次列10行
  • list / l 函数名:列出某个函数的源代码
  • r / run:运行程序
  • break(b) 行号:在某一行设置断点:
  • n / next:单条执行(逐过程进行):
  • s / step:进入函数调用(逐语句进行):
  • break 函数名:在某个函数开头设置断点
  • info break(b):查看断点信息
    1.Num:断点编号。
    2.Type:断点类型(普通断点)。
    3.Disp:断点处置方式(keep 表示断点会一直保留,即使程序重新启动)。
    4.Enb:是否启用(y 表示启用)。
    5.Address:断点对应的内存地址。
    6.What:断点的具体位置。
  • finish:执行到当前函数返回,然后停下来等待命令(可以查看问题出现在哪个函数)
  • print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
  • set var:修改变量的值,快速到达某次循环
  • continue(c):从当前位置开始连续而非单步执行(直接到下一个断点)
  • run(r):从开始连续而非单步执行
  • delete breakpoints:删除所有断点
  • delete breakpoint n:删除序号为n的断点
  • disable breakpoints:禁用断点
  • enable breakpoint:启动断点
  • info breakpoints(i b):查看当前设置了哪些断点
  • display 变量名:跟踪查看一个变量,每次停下来都显示它的值
  • undisplay:取消对先前设置的哪些变量的跟踪
  • until x行号:跳至x行(可以跳出循环)
  • breaktrace(bt):查看各级函数调用及参数
  • info(i) locals:查看当前栈帧局部变量的值
  • quit(q):退出gdb

3.Linux项目自动化构建工具-make/makefile

1、背景

  • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
  • makefile带来的好处就是------"自动化编译",一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

2、实例

依赖关系

  • 上面的文件hello,它依赖hello.o
  • hello.o,它依赖hello.s
  • hello.s,它依赖hello.i
  • hello.i,它依赖hello.c

依赖方法

  • gcc hello.* -option hello.*,就是与之对应的依赖关系

3、原理

  • make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,
    1. make会在当前目录下找名字叫"Makefile"或"makefile"的文件。
      2.对于不生成实际文件的目标(如 allclean),使用 .PHONY 明确声明。all 是伪目标,不生成实际文件,它的作用是触发 hello 的构建。 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到"hello"这个文件,
      并把这个文件作为最终的目标文件。
      3.如果hello文件不存在,或是hello所依赖的后面的hello.o文件的文件修改时间要比hello这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成hello这个文件。
    2. 如果hello所依赖的hello.o文件不存在,那么make会在当前文件中找目标为hello.o文件的依赖性,如果找到则再根据那一个规则生成hello.o文件。(这有点像一个堆栈的过程)
    3. 当然,你的C文件和H文件是存在的啦,于是make会生成 hello.o 文件,然后再用 hello.o 文件声明make的终极任务,也就是执行文件hello了。
    4. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
    5. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
    6. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
  • makefile 的核心:目标、依赖、命令。

不改变代码,只可以make一次

  • 因为提供编译效率
  • 怎么做到:一定是源文件形成可执行文件,先有源文件,才有可执行文件,一般而言,源文件的最近修改时间是比可执行文件要老的。
    如果我们更改了源文件,历史上曾经还有可执行文件,那么源文件的最近修改时间一定比可执行程序要新!
    只需要比较可执行程序的最近修改时间 和 源文件的最近可修改时间:
    .exe 新于 .c 源文件是老的,不需要重新编译
    .exe 老于 .c 源文件是新的,需要重新编译

4、项目清理

  • 像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令------"make clean",以此来清除所有的目标文件,以便重编译。
  • 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。
相关推荐
vx-bot5556662 分钟前
企业微信接口在自动化运维与智能运维中的架构实践
运维·自动化·企业微信
day day day ...7 分钟前
easyExcel和poi分别处理不同标准的excel
java·服务器·excel
阿常呓语10 分钟前
ls 命令详解
linux·运维·服务器·ls
qinyia12 分钟前
在Ubuntu 22.04.5 LTS上安装MySQL 8并设置root密码的完整协作流程
mysql·ubuntu·adb
桌面运维家13 分钟前
vDisk一键部署怎么应用?自动化脚本使用指南
运维·自动化
倔强的石头10618 分钟前
【Linux指南】基础IO系列(一)Linux 文件本质揭秘 —— 从 “磁盘文件” 到 “一切皆文件”
linux·运维·服务器
robitmind19 分钟前
操作input子系统,用模拟按键输入解锁ubuntu锁屏
linux·运维·ubuntu
Code小翊19 分钟前
re标准库模块一天学完
运维·服务器·网络
2023自学中19 分钟前
imx6ull , 4.3寸800*480屏幕,触摸芯片型号 gt9147,显示触摸点的坐标数据
linux·嵌入式硬件
Warren9821 分钟前
Allure 常用装饰器:实战用法 + 最佳实践(接口自动化)
运维·服务器·git·python·单元测试·自动化·pytest