该文目的是基本理清一个在linux在c++静态库与动态库的编译和使用
一个非常基础的一节,简单的整合了一下目前已有的文章
前提准备:
文件:
touch SoDemoTest.h one.cpp two.cpp three.cpp main.cpp
代码
/* SoDemoTest.h */
#ifndef _SO_DEMO_TEST_HEADER_
#define _SO_DEMO_TEST_HEADER_
#include <iostream>
using namespace std;
void one();
void two();
void three();
#endif
/* one.cpp */
#include "SoDemoTest.h"
void one(){
cout << "call one() function" << endl;
}
/* two.cpp */
#include "SoDemoTest.h"
void two(){
cout << "call two() function" << endl;
}
/* three.cpp */
#include "SoDemoTest.h"
void three(){
cout << "call three() function" << endl;
}
/* main.cpp */
#include "SoDemoTest.h"
int main(){
one();
two();
three();
return 0;
}
开始尝试:
动态库编译
编译生成动态库 : g++ one.cpp two.cpp three.cpp -fPIC -shared -o libtest.so
编译链接动态库 : g++ main.cpp -L. -ltest -o main
(此时进入分歧1,后面进行阐述,如若只为了编译链接成功可以不看)
将动态库放入库目录 : sudo cp liblibtest.so /usr/lib/
测试运行 : ./main
此时就可以正确运行啦~
参数命令解释
-shared :指定生成动态链接库
-fPIC: 表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时事通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码共享的目的。
-o 为生成文件重命名,否则默认为a.out
-L :表示要链接的库所在的目录。-L. 表示要链接的库在当前目录, -L/usr/lib 表示要连接的库在/usr/lib下。目录在/usr/lib时,系统会自动搜索这个目录,可以不用指明
-l (L的小写):表示需要链接库的名称,注意不是库文件名称,比如库文件为 libtest.so,那么库名称为test,也因此推荐对库文件的命名规则为libxxx.so,因为这也是-l默认识别文件名称格式,在编译选项中也可以直接用-lxxx就行了
回顾分歧1
文件成功链接动态库生成可执行文件后,如果我们不把动态库放入库目录,一般都会出现意外情况,比如我们查看链接情况,输入命令ldd main
后
可以很清楚看到这里第二行出现 libtest.so=>not found
因为这个程序不知道去哪找这个动态库,它只会去那些默认的地方找动态库,比如在/usr/lib
目录中。可以简单想想看,如果不修改系统寻找动态库目录的环境变量(比如LD_LIBRARY_PATH
)或者增添动态库文件搜索路径/etc/ld.so.conf
,又或不把我们生成的so文件导入到默认目录中,程序也能正常运行的话,那不就跟链接静态库一样了么。。。
静态库编译
编译生成目标文件 : g++ -c one.cpp two.cpp three.cpp main.cpp
创建静态库 : ar cqs libtest.a one.o two.o three.o
目标文件与静态库链接 : g++ main.o -L. -ltest -o static_main
(main.o也可以换成main.py)
测试运行 : ./static_main
此时就可以正确运行啦~
参数命令解释
-c : g++将源文件变为目标文件,在流程上目标文件是由汇编代码经过汇编器得来,其中汇编代码一般是由编译器得来,目标文件只要再经过连接器ld就能变为可执行文件了
参考资料
surgewong : gcc/g++ 链接库的编译与链接
逆光倾城 : Linux程序运行找不到动态库.so文件的三种解决办法
GCC 参数详解