目录
前言
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 .libPart2.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> 版本控制:外部通过宏控制,实现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逻辑:如果code.c存在,执行gcc指令生成code可执行程序。
Part7. 结语
这篇文章我们认识到了Linux编译与动静态库的相关知识,接下来,小编还会带来更多Linux相关的知识,敬请期待~
最后,祝大家可以:春风得意马蹄疾,一日看尽长安花!
最后的最后,要是觉得本文还可以的话,可以点点赞,关注小编一波,谢谢大家!~