【Linux】动态 / 静态库的生成与使用

文章介绍了Linux系统中静态库和动态库的区别,以及如何生成和使用它们。在静态库部分,展示了如何通过Makefile创建静态库,并打包.o文件。动态库部分则涉及到了-fPIC选项和shared参数,以及运行时动态链接所需的LD_LIBRARY_PATH环境变量设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态 / 静态库的概念

Linux系统中,动态库和静态库是编程中常见的两种库文件类型,它们用于在程序开发中共享代码和功能:

静态库

静态库是指 包含了预编译的目标代码的归档文件 ,通常以.a为扩展名。 静态库中的代码在编译时被链接到程序中,因此它们的内容会被完整地复制到生成的可执行文件中。

  • 特点

    • 包含了编译后的目标代码。
    • 在编译时会将库中的代码复制到最终的可执行文件中。
    • 可以直接在程序编译时使用。
    • 静态库会增加最终可执行文件的体积。
  • 使用方法

    • 在编译链接程序时,需要通过命令行或者构建工具明确指定要链接的静态库文件。

动态库

动态库是一种在运行时被加载的共享库,通常以.so为扩展名。与静态库不同,动态库的代码并不在编译时被复制到程序中,而是在程序运行时动态加载到内存中。

  • 特点

    • 包含共享的目标代码,在程序运行时被加载到内存中。
    • 多个程序可以共享同一个动态库的实例,节省内存。
    • 可以在库更新时不需要重新编译程序。
    • 动态库文件相对较小,不会增加可执行文件的体积。
  • 使用方法

    • 在编译链接程序时,需要指定要链接的动态库文件,同时在运行时需要确保系统能够找到这些动态库文件。

库文件的命名:

libXXX.so / libXXX.a

库的真实名称:去掉 lib前缀 ,去掉.a- .so-(且包含)后缀,剩余的为库名称

总结

  • 静态库 在编译时被链接到程序中,使得程序独立运行,但可能导致可执行文件体积增大。
  • 动态库 在程序运行时被加载,可以被多个程序共享,减少了内存占用,但需要确保系统能够找到动态库文件。


静态库

生成

在这里插入图片描述

  1. 这里创建一个主文件夹 library 在文件夹内部创建一个my_lib文件夹,用来放所写的库函数,这里用add, sub两个函数

在这里插入图片描述

库文件的命名:

add,sub分别是两个简单的加减函数:

在这里插入图片描述
在这里插入图片描述


  1. library 进行其余代码的编写:

编写makefile文件

在这里插入图片描述

src=mytest.c ./my_lib/add.c ./my_lib/sub.c
obj=mytest.o ./my_lib/add.o ./my_lib/sub.o
    
mytest:$(obj)    
    gcc -o $@ $~    
%.o:%.c    
    gcc -c $<    
    
.PHONY:clean    
clean:    
    rm -f *.o mytest 

此时我们有以下文件

在这里插入图片描述


  1. 通过将.o文件打包形成静态库

进入my_lib文件夹写Makefile

在这里插入图片描述

lib_mymath.a:add.o sub.o    
    ar -rc $@ $^    
%.o:%.c
    gcc -c $<

在这里插入图片描述

此时 lib_mymath.a 就是一个 静态库

静态库的本质:将所有的.o文件打包形成库


  1. 为了保证库的保密性
    再次完善Makefile:
    在这里插入图片描述
lib_mymath.a:add.o sub.o    
    ar -rc $@ $^    
%.o:%.c    
    gcc -c $<    
    
.PHONY:clean    
clean:    
    rm -f *.o lib_mymath.a output

.PHONY:output
output:    
    mkdir output    
    cp -rf *.h output     
    cp lib_mymath.a output    

重新make,再进行output操作

在这里插入图片描述
在这里插入图片描述
此时查看output中的文件:

在这里插入图片描述



使用

创建一个 caller 文件夹(在my_lib中,与output同级目录),为调用库的调用者:

output 给调用者(移动到caller文件夹里),更名为caller_lib

caller下写一段测试代码:

#include "add.h"    
#include "sub.h"    
      
void test()    
{    
    int x = 20;    
    int y = 10;    
    int r1 = my_add(x, y);    
    int r2 = my_sub(x, y);    
    
    printf("add : %d\n", r1);   
	printf("sub : %d\n", r2);    
}    
    
int main()    
{    
    test();    
    return 0;    
}  

运行后会发现:

在这里插入图片描述
报错,程序找不到 add.h ,因为系统默认只在统计目录下找头文件,而 add.h / sub.h 都在 caller_lib 文件夹中,所以找不到,这里引入一个指令:

gcc test.c -I./caller_lib -L./caller_lib -l_mymath

这里进行解释:

在这里插入图片描述

为什么库名称为 _mymath ?
注意 这里指定的是库的真实名称,及去掉前后缀的名称。

此时执行操作,运行a.out文件,发现正常生成结果,则库的使用没有问题。

在这里插入图片描述


可以将该指令写入caller 的 makefile文件中

在这里插入图片描述

不再进行后续演示




动态库

生成

  1. 先执行 make clean 命令,清除之前的部分文件

更改 my_lib 中的 Makefile 文件

在这里插入图片描述

 # 动态库实现    
# 形成一个动态链接的共享库    
lib_mymath.o:add.o sub.o                                                               
    gcc -shared -o $@ $^    
    
#产生 .o 目标文件,程序内部的地址方案:与位置无关,库文件可以在内存的任何位置加载,而且不影响和其他程序的关联性
%.o:%.c    
    gcc -fPIC -c $<    
    
.PHONY:clean    
clean:    
    rm -f lib_mymath.so *.o    
    
.PHONY: lib    
lib:    
    mkdir lib    
    cp *.h lib    
    cp lib_mymath.so lib    

并 更改 callermakefile 文件

在这里插入图片描述

mytest:test.c    
    gcc -o $@ $^ -I./caller_lib -L./caller_lib -l_mymath    
        
.PHONY:clean    
clean:    
    rm -f mytest    

使用

执行 caller 中的 makefile 文件 发现报错

在这里插入图片描述

原因如下:

  • 静态库编译时需要,运行时直接拷贝
  • 动态库编译和运行时都需要

这里引入一个新指令

  • LIBRARY_PATH 可以用于指定非标准位置的库文件,以便编译器能够正确地链接程序。

在这里插入图片描述
解释:

  1. 这个命令将环境变量 LD_LIBRARY_PATH 设置为 /home/aiyimu/myLinux/libiary/static/my_lib/caller/caller_lib,并将其导出,使得在当前终端中启动的所有子进程都能够访问这个环境变量。
  2. LD_LIBRARY_PATH 环境变量用于指定系统动态链接库查找的路径。

此时再次执行 make 命令

在这里插入图片描述

执行生成的 mytest

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值