静态库是以.a结尾,程序在编译链接的时候将代码直接拷贝进自己的代码中,程序运行起来就不用使用静态库了,由于静态库将库中的代码全部拷贝进来,所以程序会变得很大
库中没有main函数(为了方便别人使用自己的库,因为一个项目里面不能有两个main函数)
1、创建一个add.cpp,add.h,sub.cpp,sub.h文件
2、在文件中写入代码
3、将add.cpp,sub.cpp生成.o文件
-c是生成二进制文件,.o为二进制文件
4、将add.o,sub.o打包生成.a文件
ar是gnu的归档工具(archive,归档),-r为replace -c为create
libmath.a 是要生成的静态库,静态库必须以lib开头.a结尾
add.o sub.o 是要打包的文件
5、将动态库进行打包
我们用一个目录在linux下模拟打包
将add.h,sub.h放入output/include中,将libmath.a放入output/lib中
然后我们可以将这个文件发给别人来进行使用
6,我们可以写一个makefile来更方便的执行这个过程
创建一个main.cpp的文件,来使用静态库
方式一:
gcc/g++中
头文件的默认搜索路径是:/usr/include
库默认搜索路径:/lib64 or /usr/lib64(两个都可以,动静态库都在里面)
拷贝库到系统的默认路径下,叫做库的安装
所以我们可以将我们的库文件拷贝到目录下(需要root权限)
然后使用命令生成可执行程序
-l是链接的意思,链接的时候要去掉静调库的lib前缀和.a后缀
注意:不推荐将自己写的库放入系统目录下,因为可能会和第三方库冲突
方式二:
直接指定静态库的位置,本次使用的是相对寻址
-I(include) 头文件的位置
-L(library) 库的位置
-l(link) 要链接的库,去掉lib前缀和.a后缀
注意:
-l 默认链接的是动态库
假如库只有静态库,就会使用静态库,其他能以动态的会以动态库链接
假如要全部静态链接,需要加-static
动态库是以.so结尾,程序在运行的时候才会去寻找库的地址进行链接,减少了库的大小
库中没有main函数(为了方便别人使用自己的库,因为一个项目里面不能有两个main函数)
我们先来看看进程地址空间,在栈和堆中间有一个区域是共享区,来存放动态库的,假如有多个进程使用这个动态库,那么多个进程只要在运行时候使用这一份动态库就可以了
第一二步和制作静态库相同
3、将add.cpp,sub.cpp变成.o文件
我们发现不同的是,g++命令多了个-fPIC,-fPIC的意思是生成一个与路径无关的文件,意思是使用相对寻址
4、使用g++带上-shared(生成共享库)选项就可以对动态库进行打包
5、和制作静态库一样进行发布
6、写一个makefile文件进行快捷操作
libmymath.so:add.o sub.o
g++ -shared -o libmymath.so add.o sub.o
add.o:add.cpp
g++ -fPIC -c -o $@ $^
sub.o:sub.cpp
g++ -fPIC -c -o $@ $^
.PHONY:out
out:
mkdir -p output/include
mkdir -p output/lib
cp *.h output/include
cp *.so output/lib
.PHONY:clean
clean:
rm -rf output *.o *.so
假如我们直接去使用
用ldd命令显示test程序(ldd打印程序的动态依赖关系),发现找不到mymath动态库
为什么我们指定了地址也找不到呢?
因为我们指定地址是向编译器g++指定,而程序动态库在运行时候被查找,我们的操作系统还不知道地址,所以找不到
方式一:
和静态库的方式一一样,将库的头文件放入系统默认搜索路径中,库文件放入系统默认搜索路径中
方式二:
使用export导入环境变量
动态库的环境变量是LD_LIBRARY_PATH,里面保存的是动态库的环境变量
然后用exprt添加环境变量,需要用:分开,不然会覆盖之前的环境变量
注意:我们直接添加环境变量是内存级的环境变量,假如我们重启系统之后,test程序又找不到动态库了
假如我们想要重启系统后还可以继续使用,需要添加系统级别的环境变量
系统级别的环境变量添加在:/etc/ld.so.conf.d路径下
我们只需要在这个路径下添加一个.conf结尾的文件,然后将动态库的绝对路径添加进去
之后再ldconfig就可以重新加载配置文件了
因为我们在系统层面操作,所以需要root权限
方式三:
通过软连接在/lib64下创建一个软连接链接动态库需要使用绝对路径
使用ldd test发现,文件链接的是软连接