Linux下的动静态库

目录

认识动静态库

如何制作动静态库?

静态库 

动态库

使用库

使用静态库

使用动态库

为什么动态链接是如此呢?


认识动静态库

我们在使用标准库的时候,需要有系统的头文件和系统的库文件,这个库文件是什么呢?
当.cpp文件被编译成.o文件时,
将自己的.o文件和头文件可以直接给别人就可以使用,这个.o文件其实就类似于库文件,库文件的本质就是一系列.o文件的打包。库文件分成两种,一种是动态库,一种是静态库。

如何制作动静态库?

静态库 

比如说要把下面四个文件做成静态库:

用makefile一键构建

1.首先将所有的源文件.c 使用gcc的 -c选项生成 .o文件

2.使用ar -rc命令打包文件

ar其实就是一个打包软件

其选项含义:

-r(replace)是如果目标文件有更新了,就替换原来的

-c(create)是创建静态库文件

-t 列出文件

-v显示文件的详细信息

注意:静态库的库名格式是以lib开头.a结尾

3.为了方便给他人使用,将库发布,其实就是进一步整理,使用makefile一次执行多行命令,建立库目录和头文件目录,然后将.a库文件和.h头文件分别放入即可。

整体makefile就像这样,以后就能一键生成静态库了:

mylib=libmylib.a #makefile下可以定义变量var,后面用$(var)使用
$(mylib):printTime.o add.o
	ar -rc -o $(mylib) $^

cc=g++
%.o:%.cc	#%.o表示所有.o文件,%.cc表示所有.cc文件, $<和$^都表示所有的依赖目标集
	$(cc) -c $< -std=c++11 

.PHONY:clean
clean:
	rm -rf $(mylib) ./*.o ./*.a mylib

.PHONY:output
output:
	mkdir -p mylib/include
	mkdir -p mylib/lib
	cp ./*.h mylib/include
	cp ./*.a mylib/lib
	

比如 一键生成的静态库,方便使用:

动态库

制作动态库同理,前两步略有不同。

1.将所有的源文件.c 使用gcc的 -c选项生成 .o文件,还要带上-fPIC表示产生与位置无关码的目标文件,因为静态链接是拷贝代码到调用处,具有绝对地址,而动态库是动态链接的可以理解为没有绝对地址。

2.使用gcc的 -shared选项将所有的.o文件生成.so动态库即可。


3.发布,同上

 于是整体makefile就像这样,以后就能一键生成动态库了:

mylib=libmylib.so #makefile下可以定义变量var,后面用$(var)使用
$(mylib):printTime.o add.o
	g++ -shared -o $(mylib) $^

cc=g++
%.o:%.cc	#%.o表示所有.o文件,%.cc表示所有.cc文件, $<和$^都表示所有的依赖目标集
	$(cc) -fPIC -c $< -std=c++11 

.PHONY:clean
clean:
	rm -rf $(mylib) ./*.o ./*.so mylib

.PHONY:output
output:
	mkdir -p mylib/include
	mkdir -p mylib/lib
	cp ./*.h mylib/include 
	cp ./*.so mylib/lib

比如 打包好的动态库,结构同静态库:

 

那么如何使用动静态库呢?

使用库

比如当前文件夹下只有刚才打包好的mylib文件夹,当前的.cc文件如何使用库呢?

使用静态库

因为当前文件夹下只有刚才打包好的mylib文件夹,所以编译直接报错

可以在“”中放入头文件的具体路径,比如:

或者将头文件放入系统头文件/usr/include/目录下系统头文件(usr/include/)路径,(注意需要root权限)比如:

gcc编译的时候gcc就会去在系统头文件目录下去查找

 但是库文件未安装,需要将库安装到系统库文件目录/lib64/下

但是gcc还是不认识库和头文件,因为默认gcc中是没有的,

需要以下步骤:

指定头文件搜索路径 :-I 头文件搜索路径

指定库文件搜索路径:-L 库文件搜索路径

指定链接的库文件:-l 库名(去掉lib和.a)

注意:选项与路径或库名可不加空格

也就是这样:

 于是编译就通过了,因为倘若我们的代码不成熟,拷贝进系统库中,会污染库,所以不建议拷贝入系统的库文件下,可以直接指定我们的相应的路径,也能编译通过,比如:

使用动态库

方法与使用静态库一样,同上带上三个选项-I -L -l  告诉编译器相关路径,但是生成的程序仍然不知道依赖的库,除非在.so当当前文件夹下面,使用静态库没有这个问题,因为可执行程序已经拷贝了代码,不依赖库。

所以运行程序时就会报错加载动态库错误:

 使用命令ldd就可以查看到对应动态链接的库找不到:

需要让进程找到动态库,主要有三种方法:

1.拷贝动态库到系统库路径下:

 2.导入环境变量,程序运行时会在环境变量中查找自己需要的动态库路径

(xshell退出环境变量会失效)  

在环境变量LD_LIBRARY_PATH中添加动态库的路径 ,比如:

 3.系统配置文件来做

在/etc/ld.so.conf.d下添加.conf文件,文件内容就是我们的动态库的绝对路径,

再使用sudo ldconfig命令让配置文件生效即可

4.其他方法:

在/lib64/下建立我们的动态库的软链接

如果系统库路径下有我们的软连接,编译选项只要-I 和 -l即可。

链接成功之后,把当前文件的软链接删掉,用ldd查看a.out的动态链接情况,可以看见已经链接上了,程序就能正常运行了:

 

为什么动态链接是如此呢?

因为程序运行时,有一部分代码需要跳转到动态库中运行,OS将代码加载到物理内存,页表把内存共享区与物理内存建立映射,运行代码时跳转到共享区即可,其他进程也使用这个动态库的时候只要页表建立映射即可,在物理内存动态库只有一份 ,所以进程在运行时如果要加载动态库,需要先找到动态库。而使用静态库时,静态库的代码在代码区已经拷贝了一份不需要再去查找静态库代码。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值