一、GCC
1、工作流程
源代码->预处理->汇编代码->目标代码->可执行程序
2、常用参数选项
GCC编译选项 | 说明 |
---|---|
-E | 预处理指定源文件,不编译 |
-S | 编译指定源文件,但不进行汇编 |
-c | 编译、汇编指定源文件,但是不进行链接 |
-o [file1]$[file2] / $[file2] -o [file1]$ | 将文件file2编译成可执行文件file1 |
-I directory | 指定include包含文件的搜索目录 |
-g | 在编译的时候生成调试信息,该程序可以被调试器调试 |
-D | 在编译的时候,指定一个宏 |
-w | 不生成任何警告信息 |
-Wall | 生成所有警告 |
-on | n的取值范围:0~3。编译器的优化选项的4个级别,-o0表示没有优化,-o1为缺省值,-o3优化级别最高 |
二、静态库的制作与使用
1、库文件
1、库文件是计算机上的一类文件,可以简单的把库文件看成―种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。库文件分为静态库和动态库。
2、库是特殊的一种程序,编写库的程序和编写一般的程序区别不大,只是库不能单独运行。
3、静态库与动态库的区别:
静态库:静态库在程序的链接阶段被复制到了程序中。
动态库:动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。
4、库文件的好处:
(1)代码保密;
(2)方便部署和分发。
2、静态库
1、命名规则:libxxx.a
lib—前缀(固定)
xxx—库名(自定义)
a—后缀(固定)
2、静态库的制作
(1)gcc获得.o文件
(2)将.o文件打包,使用ar工具:ar -rcs libxxx.a xxx.o xxx..o
-r:将文件插入备存文件中
-c:创建备存文件
-s:索引
3、静态库的使用
gcc main.c -o app -I include -l ./calc -L ./lib
-I:指定包含头文件的路径
-L:指定静态库的路径
-l:指定静态库的名称
三、动态库的制作和使用
1、动态库
命名规则
(1)Linux: libxxx.so
lib:前缀(固定)
xxx:库的名字(自定义)
.so:后缀(固定)
(2)Windows: libxxx.dll
2、动态库的制作
1、gcc得到.o文件,得到和位置无关的代码
gcc -c -fpic/-fPIC a.c b.c
2、得到动态库
gcc -shared a.o b.o -o libcalc.so
3、动态库的使用
1、使用方式
与静态库相似gcc main.c -o app -I include -l ./calc -L ./lib
2、工作原理
静态库:GCC进行链接时,会把静态库中代码打包到可执行程序中
动态库:GCC进行链接时,不会把动态库中代码打包到可执行程序中
程序启动之后,动态库会被动态加载到内存中,通过ldd(list dynamic dependencies)命令检查动态库依赖关系
定位共享库文件:当系统加载可执行代码时,知道其所依赖的库的名字,但还需要知道绝对路径。此时就需要系统的动态载入器来获取该绝对路径。对于elf格式的可执行程序,由ld_linux.so来完成,它先后搜索elf文件的DT_RPATH段->环境变量LD_LIBRARY_PATH->/etc/ld.so.cache文件列表->/lib/,/usr/lib目录找到库文件后将其加载到内存中。
3、配置环境变量
(1)临时配置
终端输入脚本:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库路径
$表示获取初始的LD_LIBRARY_PATH的内容
(2)永久配置
a、用户级
配置.bashrc
(1)vim .bashrc export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库路径 (2)source .bashrc
b、系统级
配置/etc/profile
(1)sudo vim /etc/profile export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库路径 (2)source /etc/profile
使用时需要配置环境变量
四、静态库与动态库的对比
静态库 | 动态库 | |
---|---|---|
优点 | 静态库北大包到应用程序中加载速度快 发布程序无需提供静态库,移植方便 | 可以实现进程间资源共享(共享库) 更新、部署、发布简单 可以控制何时加载动态库 |
缺点 | 消耗系统资源,浪费内存 更新、部署、发布麻烦 | 加载速度比静态库慢 发布程序时需要提供依赖的动态库 |
五、MakeFile
1、基础
(1)MakeFile文件定义了一系列的规则来指定那些文件需要先编译,哪些文件后编译,哪些文件需要重新编译
(2)作用:自动化编译。MakeFile一旦写好,只需要make命令,整个工程就能完全自动编译。
2、文件命名和规则
(1)文件命名:makefile或Makefile
(2)Makefile规则:一个Makefile文件中可以由一个或多个规则
目标 ...: 依赖 ... 命令(Shell命令) ...
目标:最终要生成的文件
依赖:生成目标所需的文件或目标
命令:通过执行命令对依赖操作生成目标(命令前必须Tab缩进)
3、工作原理
(1)命令在执行之间,需要先检查规则中的依赖是否存在
如果存在,执行命令;
如果不存在,向下检查其他规则,检查是否有一个规则是用来生产这个依赖的,若找到则指令命令。
(2)检查更新,在执行规则中的命令时,会比较目标和依赖文件的时间
如果依赖的时间比目标的时间晚,需要重新生成目标
如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行
4、变量
(1)自定义变量
变量名=变量值 var=hello
(2)预定义变量
变量名 | 作用 |
---|---|
AR | 归档维护程序的名称,默认值为ar |
CC | C编译器的名称,默认值为CC |
CXX | C++编译器的名称,默认值为g++ |
$@ | 目标的完整名称 |
$< | 第一个依赖文件的名称 |
$^ | 所有依赖文件 |
(3)获取变量的值
$(变量名)
5、模式匹配
%:通配符
6、函数
六、GDB调试
1、什么是GDB调试
1、定义:GDB是由GNU软件系统社区提供的调试工具,同GCC配套组成了一套完整的开发环境,GDB是Linux和许多类Unix系统中的标准开发环境
2、功能:
(1)启动程序,可以按自定义的要求运行程序;
(2)可以让程序在所指定的调置的断点处停住;
(3)当程序被停住时,可以检查此时程序中所发生的事;
(4)可以改变程序,将一个BUG产生的影响修正从而测试其他BUG。
2、准备工作
通常,在为调试而编译时,我们会关掉编译器的优化选项(-o),并打开调试选项(-g)。
另外,’-Wall'在尽量不影响程序行为的情况下选项打开 所有warning,也可以发现许多问题,避免一些不必