c/c++ 之静态库
静态库
静态库的链接过程
#include <cstdio>
void foo();
extern int b; //foo函数和b的定义都在libh.a里
int main() {
foo();
int a = b;
foo();
return b;
}
编译成目标文件:g++ a.cc -g -c -o a.o
反汇编查看汇编代码:objdump -dS a.o
0000000000000000 <main>:
#include <cstdio>
void foo();
extern int b;
int main() {
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 48 83 ec 10 sub $0x10,%rsp
foo();
c: e8 00 00 00 00 callq 11 <main+0x11>
int a = b;
11: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 17 <main+0x17>
17: 89 45 fc mov %eax,-0x4(%rbp)
foo();
1a: e8 00 00 00 00 callq 1f <main+0x1f>
return b;
1f: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 25 <main+0x25>
}
25: c9 leaveq
26: c3 retq
先看两次调用foo()函数,汇编代码地址0xc的位置:callq 11,0x11是callq 11的下一行位置。再看地址0x1a:callq 1f,0x1f也是下一行位置。因为这时不知函数foo()的定义在哪,所以暂时用callq指令的下一个指令的位置代替。
再看引用变量b的时候:mov 0x0(%rip),也是用下一个指令的地址代替还没有找到定义的b。
再看与库链接后的汇编代码:
0000000000001189 <main>:
#include <cstdio>
void foo();
extern int b;
int main() {
1189: f3 0f 1e fa endbr64
118d: 55 push %rbp
118e: 48 89 e5 mov %rsp,%rbp
1191: 48 83 ec 10 sub $0x10,%rsp
foo();
1195: e8 16 00 00 00 callq 11b0 <_Z3foov>
int a = b;
119a: 8b 05 70 2e 00 00 mov 0x2e70(%rip),%eax # 4010 <b>
11a0: 89 45 fc mov %eax,-0x4(%rbp)
foo();
11a3: e8 08 00 00 00 callq 11b0 <_Z3foov>
return b;
11a8: 8b 05 62 2e 00 00 mov 0x2e62(%rip),%eax # 4010 <b>
}
11ae: c9 leaveq
11af: c3 retq
00000000000011b0 <_Z3foov>:
11b0: f3 0f 1e fa endbr64
11b4: 55 push %rbp
11b5: 48 89 e5 mov %rsp,%rbp
11b8: 48 8d 35 46 0e 00 00 lea 0xe46(%rip),%rsi
看地址0x1195和0x119a就知道,链接后函数foo()的地址在0x11b0,变量b的地址在0x4010的位置。
编译成目标文件(未链接)
g++ -c a.cc b.cc c.cc d.cc
#生成 a.o b.o c.o d.o
将目标文件打包为静态库
ar rs libxxx.a a.o b.o c.o d.o
#选项'r'表示将后边的文件列表添加到文件包,如果不存在就创建它,如果文件包中已有同名文件就替换成新的。
#选项's'是专用于生成静态库的,表示为静态库创建索引,这个索引被链接器使用。
#库名以lib开头
将库和主程序编译链接在一起
g++ main.cc -L. -lxxx -I. -o main
#'-L' 后接静态库的目录
#'-l' 后接静态库名称(去掉lib和.a。如:libxxx.a就写xxx)
#'-I' 后接头文件目录
查找路径
g++ -print-search-dirs #查看
install: /usr/lib/gcc/i486-linux-gnu/4.3.2/
programs: =/usr/lib/gcc/i486-linux-gnu/4.3.2/:/usr/lib/gcc/i486-linux-gnu/4.3.2/
libraries: =/usr/lib/gcc/i486-linux-gnu/4.3.2/:/usr/lib/gcc/i486-linux-gnu/4.3.2/
编译器会在这些路径和-L指定的路径中查找-l指定的库,比如-lxxx编译器会先查找有没有libxxx.so,如果有就链接它,如果没有就查找静态库。所以编译器是优先考虑共享库的,如果希望只链接静态库,可以指定-static选项。

浙公网安备 33010602011771号