[Linux]动静态库

动静态库

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库,但是,多个程序使用相同的静态库时,每个程序都会包含一份库的代码,可能会导致可执行文件体积较大。

动态库(.so):是在程序运行时被加载的库。当一个程序链接了动态库,在程序启动时,操作系统的动态链接器会加载所需的动态库到内存中。多个程序可以共享同一个动态库的代码段,这有助于减少内存的占用。

库的本质就是.o文件的集合。我们有如下的两个源文件,如果我们不想给对方我们的源代码,那么就可以给对方提供.o文件(可重定位二进制目标文件),和头文件。对方就可以用它的代码来链接我们的.o文件,使用我们提供的方法。(.o文件提供方法,.h文件说明都有什么方法)

将多个文.o件打包形成一个文件,这其实就是库。根据打包方式的不同,就可以分为静态库和动态库。

静态库

通过ar [选项] [静态库文件名] [目标文件列表]命令创建或更新静态库。

  • -r:将目标文件插入到静态库中。如果静态库中已经存在同名的目标文件,则替换它。
  • -c:创建静态库文件时,不显示创建过程的详细信息。如果静态库不存在,则创建它;如果已经存在,则更新它 。

如上就通过ar命令形成了一个静态库文件。但是这个文件并不能直接链接形成可执行文件,因为这个文件并没有包含头文件。我们之所以能够在系统上运行我们的程序,是因为C语言已经给我们提供了对应的头文件和库文件。

如上,我们已经将头文件和.a文件打包,此时只需要将这个包发给别人就可以了。

使用静态库

  1. 第一种方法

    此时打包好的库文件和源文件在同一个目录下,当我们使用gcc进行编译的时候,它仍然报错,提示头文件找不到。但是我们不是已经有头文件了吗?那是因为在搜索头文件的时候,编译器会在当前路径下搜索或在系统默认指定路径下搜索。当前路径是指和源代码处在同一级的路径,而这里.h文件的路径太深了。

    想要成功的编译链接形成一个可执行文件。我们还需要三个选项,分别是-I-L-l

    • -I:指明头文件的位置。
    • -L:指明库文件的位置。
    • -l:指明库名称。(库名称是指去掉前缀和后缀所剩下的部分,如libmymath.a去掉前后缀后只剩下mamath

    此时就成功形成了可执行文件。我们在来看一下下面这张图:

    这里不对啊!我明明是静态库,但是为什么显示的是动态链接呢?这是由于gcc默认是动态链接的,当你编译链接形成可执行文件时,你不仅仅使用了你自己的静态库,你还用了C语言提供的动态库,只要使用了动态库,那么gcc就会选择默认的动态链接,尽管你提供的是静态库。

  2. 第二种方法

    第二种方法就是直接将头文件和库文件放到对应的系统指定的路径下。头文件放到/usr/include目录下,库文件放到/usr/lib64目录下。但是编译的时候仍然要加上-l选项,也就是指定库的名称。(这种方法并不推荐)

动态库

创建动态库

使用 gcc 编译器并带上 -fPIC(Position-Independent Code,位置无关代码)选项将源文件编译成目标文件(.o 文件)。

gcc -fPIC -c my_sub.c
gcc -fPIC -c my_add.c

接着,使用 gcc 编译器的 -shared 选项,基于之前生成的目标文件来创建动态库。

gcc -shared -o libmymath.so my_add.o my_sub.o

如此,就创建了一个动态库。

使用动态库

与静态库一样,要使用这个动态库,就要将头文件和这个库同时给其他人。将动态库与自己的程序编译链接形成可执行文件的方法与静态库一样。

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

但是当你运行形成的可执行文件的时候,会发现他报错了,显示这个库找不到。我们不是已经将头文件和库文件的位置都告诉它了吗,为什么还是找不到呢?

这是因为你只将库的路径告诉了gcc,所以gcc编译链接的时候没问题。但是我们现在是在执行程序,执行的时候已经和gcc没有关系了,之和操作系统有关。而对于操作系统你并没有指明库的路径。

指明路径

给操作系统指明库的路径有以下几种方法。

  1. 将路径添加到LD_LIBRARY_PATH环境变量中。

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wzh/studyCode/my_lib/test/mylib
    

    此时再运行程序就可以正常执行了。但是这个方法只是临时的,一旦退出,下次想要正常运行就要重复这个操作。

  2. 将库添加到usr/lib64目录下。

    这个方法是永久有效的,但是不推荐。

  3. 更改/etc/ld.so.conf.d/下的配置文件。

    首先在/etc/ld.so.conf.d/下创建一个文件,然后再将库所在的路径写入到该文件中(当然不创建也可以,随便将库路径写入到该目录下的任意文件中)。最后还要执行sudo ldconfig这条命令,配置文件才能生效。

    如此,这个路径就永久有效了。

  4. 建立软链接

    在和执行文件同级的目录下建立一个库文件的软链接(也可以将这个链接直接建立在/usr/lib64目录下)。如下

    ln -s  /home/wzh/studyCode/my_lib/test/mylib/lib/libmymath.so libmymath.so
    

    像这样,程序同样可以正常运行。

posted @   羡鱼OvO  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
点击右上角即可分享
微信分享提示