0、从代码到可执行文件
C++和C语言类似,一个C++程序从源码到执行文件,有四个过程,预编译、编译、汇编、链接
- 预编译(预处理): (
.cpp -> .i
)
(1) 将所有的 #define
删除,并且展开所有的宏定义
(2) 处理所有的条件预编译指令,如 #if
、#ifdef
(3) 处理#include
预编译指令,将被包含的文件插入到该预编译指令的位置。
(4) 过滤所有的注释,如 //、/* */
(5) 添加行号和文件名标识。
- 编译:(
.s
)
(1) 词法分析:将源代码的字符序列分割成一系列的记号。
(2) 语法分析:对记号进行语法分析,产生语法树。
(3) 语义分析:判断表达式是否有意义。
(4) 代码优化:
(5) 目标代码生成:生成汇编代码。
(6) 目标代码优化:冗余指令删除、控制流优化、代数优化、机器特有指令的使用。
-
汇编:(
.o
) 将汇编代码转变成机器 可执行的指令(二进制)。 -
链接: 将不同的源文件产生的目标文件进行链接,从而形成一个可执行的程序。
1、库
库文件是计算机上的一类文件,可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。
- 库是特殊的一种程序,编写库的程序和编写一般的程序区别不大,只是库不能单独运行。
- 库文件有两种,静态库和动态库(共享库),区别是:
静态库在程序的链接阶段被复制到了程序中;
动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。
- 库的好处:1.代码保密 2.方便部署和分发
2、静态库
2.1 命名规则
- Linux :
libxxx.a
(库文件名)- lib : 前缀(固定)
- xxx : 库的名字,自己起
- .a : 后缀(固定)
- Windows :
libxxx.lib
2.2 静态库的制作
- gcc -c 获得 .o 文件
- 将 .o 文件打包,使用 ar 工具(archive)
ar rcs libxxx.a xxx.o xxx.o
r – 将文件插入备存文件中
c – 建立备存文件
s – 索引
2.3 静态库的使用
3、动态库(共享库)
3.1 命名规则
- Linux :
libxxx.so
(库文件名)- lib : 前缀(固定)
- xxx : 库的名字,自己起
- .so : 后缀(固定)
- 在Linux下是一个可执行文件
- Windows :
libxxx.dll
3.2 动态库的制作
- gcc 得到 .o 文件,得到和位置无关的代码
gcc -c –fpic a.c b.c
或gcc -c –fPIC a.c b.c
- gcc 得到动态库
gcc -shared a.o b.o -o libcalc.so
calc 文件夹 – 用来生成库文件,给library用
library 文件夹 – 实际要用的代码文件
3.3 动态库的使用
GCC 进行链接时,动态库的代码不会被打包到可执行程序中。
程序启动之后,动态库会被动态加载到内存中,通过 ldd (list dynamic dependencies)命令检查动态库依赖关系。
- 如何定位共享库文件呢?
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统的动态载入器来获取该绝对路径。对于 elf 格式的可执行程序,是由 ld-linux.so 来完成的,它先后搜索 elf 文件的 DT_RPATH段 ——> 环境变量LD_LIBRARY_PATH ——> /etc/ld.so.cache文件列表 ——> /lib/,/usr/lib目录
找到库文件后将其载入内存。
- 解决动态库无法载入的问题:
(1)LD_LIBRARY_PATH
1. 在终端配置环境变量(加入动态库位置)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/cyf/Linux/test06/library/lib
在终端配置环境变量是临时的,更换终端会失效。
2. 用户级别配置
在 home 目录下 vim .bashrc
打开进行配置
在末尾(按 o )插入export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/cyf/Linux/test06/library/lib
,保存退出。
. .bashrc
(或 source .bashrc
)更新配置,成功运行,换终端可运行。
3. 系统级别配置
sudo vim /etc/profile
打开配置文件;
在末尾(按 o )插入export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/cyf/Linux/test06/library/lib
,保存退出。
source /etc/profile
更新配置文件,成功运行。(发现在换终端后需要重新更新配置文件才能运行)
(2)/etc/ld.so.cache
sudo vim /etc/ld.so.conf
间接修改配置
(3)/lib/ , /usr/lib 目录
不推荐使用,这两个目录下包含系统库文件,存在误操作风险。
4、静态库与动态库的对比
4.1 程序编译成可执行文件过程
4.2 库文件制作过程、使用方法不同
4.3 优缺点
- 静态库
- 动态库