【Hello Linux】动态库和静态库(下)

简介: 【Hello Linux】动态库和静态库(下)

静态库的打包和使用

我们下面使用静态库打包和使用的例子让大家更加深入的理解静态库

我们使用下面的四个文件来演示

add.h

1 #pragma once 
  2                                                   
  3 extern int myadd(int x , int y);

add.c

1 #include "add.h"  
  2   
  3 int myadd(int x , int y)  
  4 {  
  5   return x + y;                                   
  6 } 

sub.h

1 #pragma once 
  2 
  3 extern int mysub(int x , int y);  

sub.c

1 #include "sub.h"
  2 
  3 int mysub(int x , int y)
  4 {
  5   return x-y;                                     
  6 }

打包

第一步 生成二进制文件

第二步 将所有目标文件打包为静态库

ar命令是gnu的归档工具 常用于将目标文件打包为静态库

下面是命令选项

  • -r(replace):若静态库文件当中的目标文件有更新 则用新的目标文件替换旧的目标文件
  • -c(create):建立静态库文件
  • -t:列出静态库中的文件
  • -v(verbose):显示详细的信息

我们可以使用下面的指令将一个或多个目标文件打包为静态库

ar -rc libst.a add.o sub.o

我们可以使用下面的指令查看一个静态库中的文件

ar -tv libst.a

第三步 将头文件和生成的动态库组织起来

与我们使用时一样

我们可以将所有的头文件放到 /include 文件夹中

将所有的静态库文件放到 /lib 文件夹中

接着将这两个目录放到 /mylib

这样子我们就可以将我们的mylib给别人使用了

使用

我们首先写出一个源文件 main.c

1 #include <stdio.h>
E>  2 #include <add.h>
E>  3 #include <sub.h>
    4 
    5 
    6 
    7 int main()
    8 {
    9   int x = 10;                                                                                            
   10   int y = 20;
E> 11   int z1 = myadd(x , y);
E> 12   int z2 = mysub(x , y);
   13   printf ("myadd :: %d\n" , z1);
   14   printf ("mysub :: %d\n" , z2);
   15   return 0;
   16 

我们发现 这个源文件中其实报了四个错误 这是因为我们c语言程序在查到头文件的时候只会查找同级的头文件还有系统配置的头文件

而我们当前目录下只有两个文件 main.c 和 mylib

不过我们不必担心 编译之后的程序肯定是可以正常运行的

使用方式一: 使用选项

gcc编译时我们需要使用的三个选项如下

  • -I:指定头文件搜索路径
  • -L:指定库文件搜索路径
  • -l:指明需要链接库文件路径下的哪一个库

所以说我们只需要敲出下面的指令他就可以

gcc -o main main.c -I ./mylib/include/ -L ./mylib/lib/ -l st

这段指令的意思是使用main.c源程序编译 指定某个头文件 指定某个库文件 指定st这个库

编译生成一个名为main的可执行文件

这个时候我们就可以运行我们的程序了

使用方式二: 把头文件和库文件拷贝到系统路径下

编译器之所以能够找到c的头文件和库文件是因为它们被放在默认的路径中

当我们开始编译的时候编译器就会默认去那里寻找

而头文件的默认路径在这里

/usr/include/

而库文件的默认路径在这里

/lib64/

所以说我们只需要将自己的头文件和库文件拷贝到这两个地方就可以了

我们使用下面两个指令来拷贝

cp ./mylib/include/* /usr/include/
cp ./mylib/lib/libst.a /lib64/

之后我们再看main文件代码

我们发现这次代码并没有报错

但是我们这里发现gcc编译的时候报错了 这是因为gcc编译的时候默认找的是c库 而我们添加的库并不是c库

所以说我们编译的时候还需要指定依赖的库文件

注意: 我十分不建议将自己写的库文件拷贝到系统路径中 这样子会污染原本的库文件

动态库的打包和使用

我们还是使用这四个库文件来演示动态库的打包和使用

打包

第一步 生成对应的目标文件

让所有源文件生成对应的目标文件

动态库与静态库汇编指令中不同的是 动态库的汇编指令中需要加上-fPIC选项

-fPIC选项的意义是生成和位置无关码

它是一个很复杂的概念 涉及到很多的专业知识 这里就不过多赘述 对于它我们只需要了解两点

  1. -fPIC作用于编译阶段 告诉编译器产生与位置无关的代码 之后代码被加载到内存的任何位置都可以运行
  2. -fPIC选项并不是必须要加的 如果不加动态库必须要在加载到用户程序的地址空间时重定向所有表目

第二步 打包动态库

与生成静态库时使用ar命令打包不同 我们只需要使用gcc的-shared选项即可

指令如下

gcc -shared -o libdy.so add.o sub.o

第三步 将头文件和生成的动态库组织起来

和生成的静态库一样

我们可以将所有的头文件放到 /include 文件夹中

将所有的静态库文件放到 /lib 文件夹中

接着将这两个目录放到 /mylib

这样子我们就可以将我们的mylib给别人使用了

使用

我们还是使用静态库的源文件main.c来演示动态库的使用

1 #include <stdio.h>
E>  2 #include <add.h>
E>  3 #include <sub.h>
    4 
    5 
    6 
    7 int main()
    8 {
    9   int x = 10;
   10   int y = 20;
E> 11   int z1 = myadd(x , y);
E> 12   int z2 = mysub(x , y);
   13   printf ("myadd :: %d\n" , z1);
   14   printf ("mysub :: %d\n" , z2);
   15   return 0;                                                            
   16 }

动态库的编译方法和静态库的编译方法一模一样

我们可以使用指令或者是将库文件和头文件放到系统目录中

我们这里使用指令为例

我们敲出下面的指令就可以编译

我们发现这样子就生成了我们的可执行程序了

但是和静态库的使用不一样 使用动态库的文件在成为可执行文件的时候还不能直接运行

我们再使用ldd指令 查看这个可执行文件所依赖的动态库

我们发现系统找不到这个动态库在哪里

这是因为 我们使用-I,-L,-l这三个选项都是在编译期间告诉编译器我们使用的头文件和库文件在哪里以及是谁 但是当生成的可执行程序生成后就与编译器没有关系了

所以说如果我们想要执行这个程序 还需要想办法告诉操作系统这个库文件的地址

这里有三种方式可以做到

方式一 拷贝到系统路径下

我们直接将该动态库拷贝到系统的库文件目录下 这样子操作系统就能够找到了

指令如下

cp ./mlib/dylib/libdy.so /lib64

这样子就可以顺利运行了

方式二 更改环境变量

LD_LIBRARY_PATH是程序运行动态查找库时所要搜索的路径 我们只需将动态库所在的目录路径添加到LD_LIBRARY_PATH环境变量当中即可

使用指令如下

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/shy/linux/lesson11~20/lesson13/code4/mlib/dylib/

之后我们再查询a.out的动态库 可以发现

我们可以发现动态库的路径变为了我们设置的路径

当然现在也可以继续运行了

方式三 配置/etc/ld.so.conf.d/

我们可以通过配置/etc/ld.so.conf.d/的方式解决该问题

首先我们自己需要写一个以.conf后缀的文件

将我们库文件所在的路径放到这个文件当中

之后将这个配置文件放到 /etc/ld.so.conf.d/ 目录中

之后使用指令更新配置文件

ldconfig

这样子我们就可以运行我们的文件了

投票

相关文章
|
11天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
36 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
2月前
|
Linux
linux 交叉编译libpng,libjpeg库
linux 交叉编译libpng,libjpeg库
23 1
|
2月前
|
Linux 编译器 Android开发
linux交叉编译nss3,nspr库精讲
linux交叉编译nss3,nspr库精讲
38 1
|
2月前
|
缓存 Shell Linux
【Shell 命令集合 链接器(linker)工具】Linux ld命令 将目标文件与库链接为可执行文件或库文件
【Shell 命令集合 链接器(linker)工具】Linux ld命令 将目标文件与库链接为可执行文件或库文件
39 0
|
7天前
|
Linux 编译器 vr&ar
【库函数】Linux下动态库.so和静态库.a的生成和使用
【库函数】Linux下动态库.so和静态库.a的生成和使用
8 1
|
13天前
|
Linux 网络安全 开发工具
【GitLab私有仓库】在Linux上用Gitlab搭建自己的私有库并配置cpolar内网穿透
【GitLab私有仓库】在Linux上用Gitlab搭建自己的私有库并配置cpolar内网穿透
|
2月前
|
存储 安全 Ubuntu
【Linux 应用开发 】Linux环境下动态链接库路径(RPATH)的调整策略
【Linux 应用开发 】Linux环境下动态链接库路径(RPATH)的调整策略
72 1
|
2月前
|
Shell Linux vr&ar
【Shell 命令集合 备份压缩 】⭐⭐⭐Linux 修改备存/静态库 文件 ar命令 使用指南
【Shell 命令集合 备份压缩 】⭐⭐⭐Linux 修改备存/静态库 文件 ar命令 使用指南
32 0
|
2月前
|
缓存 算法 Linux
深入理解Linux动态库加载:路径、问题与解决方案
深入理解Linux动态库加载:路径、问题与解决方案
98 0
|
2月前
|
Linux 编译器 网络安全
linux 交叉编译libcurl库
linux 交叉编译libcurl库
41 1