gcc工作流程
预编译 ->编译->汇编->链接
流程介绍
预编译
阶段操作
- 展开头文件
- 替换宏
- 消除注释
结果:生成.i结尾
的预处理文件
编译
阶段操作
源代码翻译成汇编代码
结果:生成.s结尾
的汇编文件
汇编
阶段操作
将汇编文件翻译为二进制文件
结果:生成.c结尾
的二进制文件
链接
阶段操作
将多个二进制文件与所需要的库连接起来
结果:生成可执行
的二进制文件
gcc工作流程动图展示
可以通过一条语句直接生成二进制可执行文件
gcc xxx.c -o xxx //自动完成 预编译->编译->汇编->链接
gcc xxx.c //生成a.out 因为没有指定生成名
gcc常用参数
参数 | 作用呢 |
---|---|
-E | 预处理指定文件,但不编译 |
-S | 编译指定源文件但不汇编 |
-c | 编译汇编指定源文件,但不链接 |
-o [file1] [file2] 或[file2] -o [file1] | 将file2编译成file1 (-o后跟生成文件) |
-I(大写i) | 指定include包含文件的搜索目录,使用场景:include包含的文件不在当前目录下,需要指定搜索目录 |
-g | 生成调试信息 ,使用场景:gdb调试 |
-D | 编译的时候指定一个宏, 使用场景: 控制日志输出 |
-w | 不生成任何警告信息 |
-Wall | 生成所有警告信息 |
-On | n取值为1-3,表示编译器的优化级别,0表示没有优化,3优化级别最高 |
-l | 编译时指定使用库, 使用场景:使用静态库/动态库 |
-L | 指定搜索库路径 |
-fPIC/fpic | 生成与位置无关的代码 |
-shared | 生成共享目标文件 |
-std | 指定C标准 ,windows一般默认为c99,linux默认GNU C,使用方法 -std=c99 |
动态库和静态库
本质:一个程序
作用:
- 便于传输
- 保护知识产权
静态库
Linux静态库命名格式:libxxx.a
Windows静态库命名格式:libxxx.lib
静态库生成方式:
- 将源文件转化为.o文件(汇编文件)
gcc -c xxx.c ....
- 创建静态库
ar rcs 静态库的名字(libxxx.a) 原材料(.o文件)
- 发布
头文件 (告诉用户如何使用) +静态库 (底层实现)
使用语法
gcc xxx.c -o xxx -L [库所在目录] -l [库名字(掐头去尾)]
//掐头去尾指 若静态库名字为libxxx.a,则-l xxx即可
动态库
动态库特点:
- 动态库有执行权限
- 动态库地址不定,加载到动态库加载区,使用的是相对地址
Linux静态库命名格式:libxxx.so
Windows静态库命名格式:libxxx.dll
动态库的生成方式
- 将源文件转化为.o文件(汇编文件)
gcc -c -fpic xxx.c...
- 生成动态库
gcc -shared [汇编文件] -o [动态库名]
- 发布
头文件 (告诉用户如何使用) +静态库 (底层实现)
使用语法
gcc xxx.c -L [库所在目录] -l [库名字(掐头去尾)] -o xxx
//掐头去尾指 若静态库名字为libxxx.so,则-l xxx即可
动态库最终生成的可执行程序中不包含动态库的代码,使用的时候才加载,所以动态连接器会有一个搜索库的操作。
查看程序是否能搜索到动态库
ldd xxx
当动态连接器搜索不到动态库时有如下解决方法
动态链接器搜索次序:
LD_LIBRARY_PATH
环境变量/etc/ld.so.cache
/lib
、/usr/lib
解决方法1
LD_LIBRARY_PATH=[动态库绝对路径]:$LD_LIBRARY_PATH
但是这种是临时的,不长久
长久的方法:
修改 用户级别 ~./bashrc 或者 系统级别的配置文件 /etc/profile
在配置文件后添加
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:[动态库绝对路径]
.~/.bashrc //让当前终端重新加载配置信息
解决方法2
通过修改ld.so.conf
来间接修改 /etc/ld.so.cache
sudo vim /etc/ld.so.conf
#添加动态库的绝对路径
sudo ldconfig #ld.so.conf的数据更新到 /etc/ld.so.cache中
解决方法3
将动态库的软连接放到 /lib
目录或/usr/lib
目录
#直接拷贝
sudo cp /xxx/xxx/libxxx.so /usr/lib
#创建软连接(推荐)
sudo ln -s /xxx/xxx/libxxx.so /usr/lib/libxxx.so
动态库与静态库总结
静态库
优点 | 缺点 |
---|---|
打包加载速度快 | 相同库文件可能在内存中被加载多次,浪费资源 |
发布程序无需提供库文件 | 程序迭代麻烦 |
动态库
优点 | 缺点 |
---|---|
资源共享 | 加载速度慢 |
程序迭代升级简单 | 发布程序需要提供依赖的库 |
控制何时加载动态库 |
静态库使用场景:
源文件量小
动态库使用场景
源文件量大