本文的目的是测试各种类型库的编译后的使用效果,包括库又链接其他库的编译方法,使用方法,依赖性等。
太长不看版:请跳至文章最后的总结对比表。
一、内容包含:
①静态库libbb.a依赖静态库libaa.a的测试;
②静态库libbb.a依赖动态库libaa.so的测试;
③动态库libbb.so依赖静态库libaa.a的测试;
④动态库libbb.so依赖动态库libaa.so的测试;
aalib.h
#ifndef AALIB_H
#define AALIB_H
#include "stdio.h"
void helloAA();
#endif
aalib.cpp
#include "aalib.h"
void helloAA()
{
printf(" lib AAAAAAAAAAAAA\n ");
}
bblib.h
#ifndef BBLIB_H
#define BBLIB_H
void helloBB();
void helloAB();
#endif
bblib.cpp
#include "bblib.h"
#include "aalib.h"
void helloBB()
{
printf(" lib BBBBBBBBBBBBBBBB \n");
}
void helloAB()
{
printf(" *a*******************\n");
helloAA();
helloBB();
printf(" *b*******************\n");
}
main.cpp
#include "bblib.h"
int main()
{
helloBB();
helloAB();
}
二、测试过程
①静态库libbb.a依赖静态库libaa.a的测试
现在生成了静态库libaa.a和libbb.a,可以通过nm命令来查看生产的.o文件和静态链接库的内容
└──╼ $nm libaa.a
libaa.o:
0000000000000000 T helloAA
U printf
┌─[zhaoky@zhaoky]─[~/Desktop/kaiyue]
└──╼ $nm libbb.a
libbb.o:
U helloAA
0000000000000011 T helloAB
0000000000000000 T helloBB
U puts
下面测试静态库的使用方法:
可以看到链接静态库的话要指定静态库依赖的静态库,否则编译不过去!由此可见轻易不要链接静态库,因为你也许不知道你要用的静态库还依赖着哪些库…
那么将所依赖的静态库编译进静态库呢?试试
可以看到,使用命令ar rcs libbb.a bblib.o libaa.a并没有起到作用,亦即libaa.a并没有被编译进libbb.a,因此编译可执行程序时还需要链接libaa.a。
改用下面这种方式编译,可行:
即编译静态库libbb.a时不要链接libaa.a而是用aalib.o文件,亦即编译静态库链接静态库时不能直接链接静态库,而是用形成该静态库的那些.o文件,可以使用 ar -x libaa.a来获取静态库的所有.o文件(注意:所有.o文件的顺序要对,被依赖的要放后面)。
②静态库libbb.a依赖动态库libaa.so的测试
第一行命令:gcc -o libaa.so -shared -fPIC aalib.cpp
等价于:gcc -c -shared -fPIC aalib.cpp 加 gcc -o libaa.so -shared -fPIC aalib.o 这两条(注意编译.o时要加选项-shared -fPIC,否则无法生存.so)
可以看到,编译可执行程序时只链接静态库不链接动态库编译不过去!运行时也需要动态库libaa.so支持
那么将动态库编译进静态库中呢?
那么使用nm命令来进行查看其中的内容部分,结果如下,从静态库中可以看到其中是可以看到
└──╼ $nm libaa.so
0000000000004028 b completed.7325
w __cxa_finalize@@GLIBC_2.2.5
0000000000001050 t deregister_tm_clones
00000000000010c0 t __do_global_dtors_aux
0000000000003e18 t __do_global_dtors_aux_fini_array_entry
0000000000004020 d __dso_handle
0000000000003e20 d _DYNAMIC
0000000000001120 t _fini
0000000000001100 t frame_dummy
0000000000003e10 t __frame_dummy_init_array_entry
00000000000020b8 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000002018 r __GNU_EH_FRAME_HDR
0000000000001105 T helloAA
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U printf@@GLIBC_2.2.5
0000000000001080 t register_tm_clones
0000000000004028 d __TMC_END__
┌─[zhaoky@zhaoky]─[~/Desktop/kaiyue]
└──╼ $nm libbb.a
libbb.o:
U helloAA
0000000000000011 T helloAB
0000000000000000 T helloBB
U puts
解释:
─[zhaoky@zhaoky]─[~/Desktop/kaiyue]
└──╼ $nm libbb.a
libbb.o:
U helloAA
0000000000000011 T helloAB
0000000000000000 T helloBB
U puts
libaa.so:
0000000000004028 b completed.7325
w __cxa_finalize@@GLIBC_2.2.5
0000000000001050 t deregister_tm_clones
00000000000010c0 t __do_global_dtors_aux
0000000000003e18 t __do_global_dtors_aux_fini_array_entry
0000000000004020 d __dso_handle
0000000000003e20 d _DYNAMIC
0000000000001120 t _fini
0000000000001100 t frame_dummy
0000000000003e10 t __frame_dummy_init_array_entry
00000000000020b8 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000002018 r __GNU_EH_FRAME_HDR
0000000000001105 T helloAA
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U printf@@GLIBC_2.2.5
0000000000001080 t register_tm_clones
0000000000004028 d __TMC_END__
可以看到,虽然编译静态库libbb.a的时候链接了动态库libaa.so,编译可执行程序只链接静态库libbb.a也能编译过去,但是在执行时还是要libaa.so动态库支持。
③动态库libbb.so依赖静态库libaa.a的测试
可以看到编译libbb.so时链接静态库出错,提示静态库需要使用-fPIC选项来编译,那就按照提示的来修改编译命令:
静态库所需的.o文件使用-shared -fPIC编译,然后在编译动态库的时候链接静态库好用了。并且编译可执行文件时不用链接被依赖的静态库。
来看一下这个动态库libbb.so依赖哪些库:
可以看到没有依赖libaa.a这个静态库。
解释:
└──╼ $nm libaa.a
a.o:
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T helloAA
U printf
┌─[zhaoky@zhaoky]─[~/Desktop/kaiyue]
└──╼ $nm libbb.so
0000000000004040 b completed.7325
w __cxa_finalize@@GLIBC_2.2.5
0000000000001080 t deregister_tm_clones
00000000000010f0 t __do_global_dtors_aux
0000000000003e18 t __do_global_dtors_aux_fini_array_entry
0000000000004038 d __dso_handle
0000000000003e20 d _DYNAMIC
0000000000001194 t _fini
0000000000001130 t frame_dummy
0000000000003e10 t __frame_dummy_init_array_entry
0000000000002148 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
000000000000205c r __GNU_EH_FRAME_HDR
000000000000117b T helloAA
0000000000001148 T helloAB
0000000000001135 T helloBB
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U printf@@GLIBC_2.2.5
U puts@@GLIBC_2.2.5
00000000000010b0 t register_tm_clones
0000000000004040 d __TMC_END__
从动态链接库中可以看到,在动态库中已经有静库的代码
④动态库libbb.so依赖动态库libaa.so的测试
动态库链接动态库成功,并且编译可执行文件时也不用链接被依赖的库,但是运行时还是要两个动态库支持。
解释:
──╼ $nm libaa.so
0000000000004028 b completed.7325
w __cxa_finalize@@GLIBC_2.2.5
0000000000001050 t deregister_tm_clones
00000000000010c0 t __do_global_dtors_aux
0000000000003e18 t __do_global_dtors_aux_fini_array_entry
0000000000004020 d __dso_handle
0000000000003e20 d _DYNAMIC
0000000000001120 t _fini
0000000000001100 t frame_dummy
0000000000003e10 t __frame_dummy_init_array_entry
00000000000020b8 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000002018 r __GNU_EH_FRAME_HDR
0000000000001105 T helloAA
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U printf@@GLIBC_2.2.5
0000000000001080 t register_tm_clones
0000000000004028 d __TMC_END__
┌─[zhaoky@zhaoky]─[~/Desktop/kaiyue]
└──╼ $nm libbb.so
0000000000004038 b completed.7325
w __cxa_finalize@@GLIBC_2.2.5
0000000000001070 t deregister_tm_clones
00000000000010e0 t __do_global_dtors_aux
0000000000003e08 t __do_global_dtors_aux_fini_array_entry
0000000000004030 d __dso_handle
0000000000003e10 d _DYNAMIC
000000000000116c t _fini
0000000000001120 t frame_dummy
0000000000003e00 t __frame_dummy_init_array_entry
0000000000002110 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000002048 r __GNU_EH_FRAME_HDR
U helloAA
0000000000001138 T helloAB
0000000000001125 T helloBB
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U puts@@GLIBC_2.2.5
00000000000010a0 t register_tm_clones
0000000000004038 d __TMC_END__
从libbb.so中可以看到其中已经获得了两个函数
注意:
接库libbb.a的时候用到被依赖库的.o文件 ,注意些个.o文件的依赖顺序也很重要,不能错,被依赖的要放后面。另外:编译好的动态库要指定路径,否则运行时找不到动态库的位置。