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 110x11callq 11的下一行位置。再看地址0x1acallq 1f0x1f也是下一行位置。因为这时不知函数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

看地址0x11950x119a就知道,链接后函数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选项。

原文地址:https://www.cnblogs.com/rookiezjz/p/14423702.html