Linux编程环境编译链接
3.1 Linux C程序的编译执行
3.1.1 gcc常用指令
https://gcc.gnu.org/onlinedocs/gcc/#toc-GCC-Command-Options
构建相关:
- 看不懂没事,可以看下一个加粗部分"调试和优化相关的示例"
- -E:预处理,生成.i文件
- -S:预处理+编译,生成.s汇编语言文件
- -c:预处理+编译+汇编,生成.o目标文件
- -o:output,指定生成文件名
- -Idir:将dir目录添加到头文件搜索目录中
- -Ldir:将dir目录添加到库文件搜索目录中
- -lname:将libname.so或libname.a链接到可执行文件中
- 注意,linux默认使用动态链接,动态链接指的是将
动态库
链接到可执行程序
上,反则反之.
- 注意,linux默认使用动态链接,动态链接指的是将
- -Bstatic:仅链接过程中使用静态链接模式
- -static:全局静态链接模式
- -shared:制作动态库.
- 共享库会在具体的链接行为中将自己的特征信息传给被链接到的程序(即创建对动态库的依赖),在执行前(执行中)会启动加载器,根据连接时传入的特征信息找到动态库,并加载执行.
- -fPIC:生成位置独立代码(制作动态库的必要条件)
- -std=c99/-std=c11:执行标准
调试和优化相关: - -g:生成带有调试信息的可执行文件
- -O:编译期优化
- -Ox:x级优化,一般x=2,x=0是默认且不优化
- -Os:生成最短的代码
示例:
将库文件视为半成品(既有原料属性也有成品属性),用途是在加工(链接)过程中使用,帮助其他文件x合成文件x对应的库(或可执行程序).
制作静态\动态库,是制造两种不同格式的文件
静态链接是尝试将指定库的代码直接嵌入可执行文件
动态链接是将动态库的特征信息嵌入到可执行文件,运行时链接器再加载
可见:exe静态方式链接动态库,是尝试链接name.so对应的name.a,找不到则报错
还见:exe动态方式链接静态库,是不允许的,即运行时不可加载静态库,一种实现方式是exe动态方式链接某动态库,这需要提前在制作该动态库时就静态链接静态库,使其代码嵌入动态库
因此,建议:
制作静态库时,只链接(子)静态库
制作动态库时,可以链接(子)静态库也可以链接(子)动态库
制作库和链接的方法很多,但应遵循高内聚低耦合的链接思路,太复杂的编译选项通常会引入不必要的问题.
一般顺序:
编译工具 全局选项 主源文件 细分选项和其他文件 -o 目标文件
//制作静态库libadd.a
gcc -c -o add.o add.c
ar rc libadd.a add.o
//可执行文件静态链接静态库
gcc -o exe exe.c -Bstatic -L. -ladd
//位置独立代码的生成阶段
gcc -c -fPIC add.c -o add.o
//制作动态库
gcc -shared add.o -o libadd.so
//可执行文件动态链接动态库
gcc exe.c -L. -ladd -o exe
//需要将LD_LIBRARY_PATH暴露给加载器
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
//或者将动态库添加到以下文件夹中
/etc/ld.so.conf
nm工具基本用法(chatgpt4o)
nm [选项] 文件
常用选项
无选项:默认列出所有符号。
-a:显示所有符号,包括调试符号。
-g:仅显示全局(全局和外部)符号。
-u:仅显示未定义符号。
-r:按符号名称的逆序排列。
-n:按符号值排序。
-S:显示符号大小。
-l:显示符号定义的源代码行号(如果可用)。
-C:将 C++ 符号名解混淆(demangle)。
--help:显示帮助信息。
--version:显示版本信息。
符号类型说明
nm 的输出包括符号地址、符号类型和符号名称。常见的符号类型包括:
U:未定义符号。
T:代码段中的符号(函数)。
D:初始化的数据段中的符号。
B:未初始化的数据段(BSS)中的符号。
C:共用符号。
W:弱符号(可被同名的全局符号覆盖)。
V:弱对象符号。