动态库、静态库编译测试:含静态库链接动态库、静态库,动态库链接静态库、动态库
本文的目的是测试各种类型库的编译后的使用效果,包括库又链接其他库的编译方法,使用方法,依赖性等。
太长不看版:请跳至文章最后的总结对比表。
一。内容包含:
①静态库libbb.a依赖静态库libaa.a的测试;
②静态库libbb.a依赖动态库libaa.so的测试;
③动态库libbb.so依赖静态库libaa.a的测试;
④动态库libbb.so依赖动态库libaa.so的测试;
所用到的文件列表:
aalib.cpp aalib.h bblib.cpp bblib.h main.cpp
二。源代码:
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,下面测试静态库的使用方法:
可以看到链接静态库的话要指定静态库依赖的静态库,否则编译不过去!由此可见轻易不要链接静态库,因为你也许不知道你要用的静态库还依赖着哪些库.......
那么将所依赖的静态库编译进静态库呢?试试
可以看到,使用命令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支持
那么将动态库编译进静态库中呢?试试
可以看到,虽然编译静态库libbb.a的时候链接了动态库libaa.so,编译可执行程序只链接静态库libbb.a也能编译过去,但是在执行时还是要libaa.so动态库支持。
③动态库libbb.so依赖静态库libaa.a的测试
可以看到编译libbb.so时链接静态库出错,提示静态库需要使用-fPIC选项来编译,那就按照提示的来修改编译命令:
静态库所需的.o文件使用-shared -fPIC编译,然后在编译动态库的时候链接静态库好用了。并且编译可执行文件时不用链接被依赖的静态库。
来看一下这个动态库libbb.so依赖哪些库:
可以看到没有依赖libaa.a这个静态库。
④动态库libbb.so依赖动态库libaa.so的测试
动态库链接动态库成功,并且编译可执行文件时也不用链接被依赖的库,但是运行时还是要两个动态库支持。
四。总结
被依赖的库aa | 编译库aa的命令 | 直接库bb | 编译库bb的命令 | 编译可执行程序的命令 | 编译时是否需要库aa | 运行时是否需要库aa |
libaa.a |
gcc -c aalib.cpp ar rcs libaa.a aalib.o |
libbb.a | gcc -c bblib.cpp ar rcs libbb.a bblib.o | gcc -o out main.cpp libbb.a libaa.a | 需要 | 不需要 |
libaa.a | gcc -c aalib.cpp ar rcs libaa.a aalib.o | libbb.a | gcc -c bblib.cpp ar rcs libbb.a bblib.o aalib.o | gcc -o out main.cpp libbb.a | 不需要 | 不需要 |
libaa.so | gcc -o libaa.so -shared -fPIC aalib.cpp | libbb.a | gcc -c bblib.cpp ar rcs libbb.a bblib.o libaa.so | gcc -o out main.cpp libbb.a | 不需要 | 需要 |
libaa.a | gcc -c aalib.cpp ar rcs libaa.a aalib.o | libbb.so | gcc -o libbb.so -shared -fPIC bblib.cpp libaa.a | 编译libbb.so就出错,无法编译成动态库 | ||
libaa.a | gcc -c -shared -fPIC aalib.cpp ar rcs libaa.a aalib.o | libbb.so | gcc -o libbb.so -shared -fPIC bblib.cpp libaa.a | gcc -o out main.cpp -L./ -lbb | 不需要 | 不需要 |
libaa.so | gcc -o libaa.so -shared -fPIC aalib.cpp | libbb.so | gcc -o libbb.so -shared -fPIC bblib.cpp -L./ -laa | gcc -o out main.cpp -L./ -lbb | 不需要 | 需要 |
其他说明:链接静态库时要注意顺序,使用第二行的方法编译直接库libbb.a的时候用到被依赖库的.o文件,注意些个.o文件的依赖顺序也很重要,不能错,被依赖的要放后面。另外:编译好的动态库要指定路径,否则运行时找不到动态库的位置。
五。结论
由于本测试的初衷是找出一种方法使得编译可执行程序时不链接那些被依赖的库,因此第二行和第五行的组合可以作为备选方案。