【Linux】 编译与动静态库相关

目录

前言

Part1. GCC四个编译阶段

Part1.1. 预处理

Part1.2. 编译

Part1.3. 汇编

Part2. 静态库与动态库

Part2.1. 动态库

Part2.2. 静态库

Part2.3. gcc静态链接参数

Part3. 条件编译

Part4. /etc/sudoers 权限配置

Part5. 目标文件 .o

Part6. Make与Makefile

Part7. 结语

前言
在Linux中对于编译以及动静态库的理解是非常重要的,因此来跟随小编的视角来看看吧。

let's go!!!!!!!!

Part1. GCC四个编译阶段
Part1.1. 预处理
gcc -E x.c -o y.i
对x.c执行预处理,输出预处理结果保存到y.i。
完成:头文件展开、宏替换、条件编译处理、删除注释。

Part1.2. 编译
gcc -S x.c -o y.s
将C代码翻译成汇编代码,汇编结果保存到y.s。

Part1.3. 汇编
gcc -c x.c -o y.o
汇编完成,生成.o目标文件,内容为二进制机器指令,但还不能直接运行,缺少链接步骤。
完整流程:先生成.o目标文件,再通过链接生成可执行程序exe。
完整命令:gcc x.o -o exe。
使用 ldd 可执行程序,可以查看程序依赖哪些共享库。

Part2. 静态库与动态库
后缀区分
库类型 Linux Windows
动态库 .so .dll
静态库 .a .lib

Part2.1. 动态库
程序运行时才去库文件中寻找对应函数执行。执行printf这类库函数时,根据地址跳转至库中对应函数执行。

• 动态链接:编译链接阶段,仅做标记,记录库函数符号;程序运行时才跳转到库函数真实地址。

• 优点:内存占用小;多个程序可以共享内存中同一份库,内存中只加载一份。

• 缺点:依赖系统库文件,如果库丢失,程序直接无法运行。

Part2.2. 静态库
编译链接阶段,把库里面的代码拷贝、合并进我们自己的可执行程序内部。

• 优点:不依赖外部库文件,移植方便;程序可以独立运行。

• 缺点:可执行文件体积会显著变大;多个程序会各自拷贝一份库代码,内存冗余。

Part2.3. gcc静态链接参数
gcc x.c -o y -static
加上‑static,使用静态库链接,生成的可执行文件体积会明显增大。

使用file 可执行文件名,可以查看该程序是动态链接还是静态链接。

P.S. ldd命令无法查看静态链接程序的依赖,静态程序已经把库打包进自身。

Part3. 条件编译
条件编译发生在预处理阶段,本质就是修改源代码文本。
根据宏定义,选择性保留/裁剪一部分代码。

#ifdef X
// 如果 X 被 #define 定义过,这部分代码才参与编译
#endif
//gcc命令行定义宏
# 定义宏E
gcc x.c -o y -DE

# 定义宏Z,赋值100
gcc x.c -o y -DZ=100
用码道免费领 1 个月 Token
cpp
运行
实际使用场景

<1> 版本控制:外部通过宏控制,实现VIP版本、普通用户版本。预处理阶段直接裁掉对应代码,不会编译进最终程序。

<2> 跨平台开发:一套代码同时在Linux、Windows运行。通过条件编译识别当前操作系统,调用对应平台API。

<3> 调试开关:通过宏打开/关闭调试打印。

p.s. 条件编译是预处理完成,代码裁剪发生在编译之前。

Part4. /etc/sudoers 权限配置
修改/etc/sudoers,可以配置普通用户sudo权限 ,实现普通用户拥有管理员能力。
Part5. 目标文件 .o
<1> 将.c源文件编译生成.o目标文件,可以保护源码不直接暴露
<2> .o存放机器指令,多个.o可以打包成库文件。
Part6. Make与Makefile
• make:工具程序

• Makefile:配置脚本文件,描述编译依赖关系与编译命令。

Makefile基础格式

//目标: 依赖文件
//编译命令
//示例:
code: code.c
gcc -o code code.c
用码道免费领 1 个月 Token
cpp
运行
逻辑:如果code.c存在,执行gcc指令生成code可执行程序。

Part7. 结语
这篇文章我们认识到了Linux编译与动静态库的相关知识,接下来,小编还会带来更多Linux相关的知识,敬请期待~
最后,祝大家可以:春风得意马蹄疾,一日看尽长安花!

最后的最后,要是觉得本文还可以的话,可以点点赞,关注小编一波,谢谢大家!~

上一篇 MegaRaid
下一篇 如何设计一个高可用的MySQL方案?