Linux下静态库、动态库的创建和使用

Linux下静态库、动态库的创建和使用

Linux库文件名由:前缀lib、库名和后缀3部分组成,静态库通常以.a作为后缀,动态库以.so作为后缀,

Linux下把动态库叫做共享库,so即shared object的缩写。

静态库是程序编译链接时使用,动态库是程序运行时使用


预备知识:

a)  2个重要的环境变量:

LIBRARY_PATH : 库文件(静态库或者动态库)搜索路径,编译器链接时,需要去这些路径搜索相应的库,当然系统默认的库文件搜索路径是/usr/lib和/lib。 

LD_LIBRARY_PATH :动态库文件搜索路径,程序运行时,需要去这些路径搜索相应的动态库,程序运行时,默认的搜索动态库的路径也是/usr/lib和/lib。


b)  2个重要的系统文件:
/etc/ld.so.conf :里面可以加上动态库的搜索路径,绝对路径,(/usr/lib和/lib默认包含其中)
/etc/ld.so.cache :保存/etc/ld.so.conf里所有路径的所有的动态库文件的缓存,保存了已排好序的动态链接库名字列表,有一个命令:ldconfig  会根据/etc/ld.so.conf生成或者更新/etc/ld.so.cache,执行这个命令需要root权限。关于这个cache文件里面具体实现哪些东西,笔者也不是很清楚,待后续研究

程序在运行时,如果都要搜索/etc/ld.so.conf里目录下库文件,效率会很低,因此Linux采用了类似高速缓存制,程序先去查找缓存文件/etc/ld.so.cache ,因此当/usr/lib或者/lib下放入新的动态库后,也要执行sudo ldconfig 重新生成缓存文件,否则程序无法运行,报错提示,找不到共享库。当往/etc/ld.so.conf里添加目录时,或者后来在这些目录下添加新的库,都需要执行sudo ldconfig生成新的缓存文件。

==================================================================================


假设有如下文件:mylib.h mylib.c  depend.h depend.c 


一、创建静态库

      gcc -c mylib.c -o mylib.o

        gcc -c depend.c -o depend.o

        ar rcs libmylib.a  mylib.o depend.o


       ar 其实就是将*.o文件打包归档而已,主要参数说明:
       r --- 在库中加入成员文件,若存在,则替换
       c --- 创建一个静态库
       s --- 无论ar命令是否修改了库的内容,都强制重新生成库符号表
       d --- 从库中删除成员文件


二、使用静态库(3种方法)
       1、把库文件放入/usr/lib或者/lib目录下
                     编译: gcc main.c -o main -lmylib

       2、链接时指定库的目录,假设库文件放在/home/user/lib/下
                      编译: gcc main.c -o main -L/home/user/lib -lmylib 

       3、修改环境变量     将库文件所在目录/home/user/lib/加入到LIBRARY_PATH         

            执行shell:  export  LIBRARY_PATH=/home/user/lib/:$LIBRARY_PATH                                                                          编译:gcc main.c -o main -lmylib


三、创建动态库(2种方法)
       1、  gcc -fpic -c mylib.c  -o mylib.o
              gcc -fpic -c depend.c -o depend.o
              gcc -shared -o libmylib.so mylib.o depend.o 


       2、gcc -fpic -shared mylib.c depend.c -o libmylib.so
  
四、使用动态库(4种方法)
          假设libmylib.so库文件在/home/user/lib/下,以下4种方法:
   
       1、把动态库放入 /usr/lib或者/lib下,然后执行sudo ldconfig
          编译:gcc main.c -o main -lmylib
 
       2、修改环境变量 
             export LD_LIBRARY_PATH=/home/user/lib/:$LIBRARY_PATH
             gcc main.c -o main -lmylib ,注意这种方式,不能编译通过,因为LD_LIBRARY_PATH只和运行时有关,
            所以正确的做法是:

            编译:gcc main.c -o main -L/home/user/lib -lmylib 

            或者 

             将/home/user/lib加入到LIBRARY_PATH中,然后可以编译: gcc main.c -o main -lmylib
 
       3、将/home/user/lib/加入到/etc/ld.so.conf中,执行sudo ldconfig
            编译:gcc main.c -o main -lmylib
 
       4、在编译时,设置动态库运行时寻找路径
            gcc main.c -o main -Wl,-rpath=/home/user/lib ,注意这样编译是通不过的,-Wl,-rpath= 指定程序

            在运行时,搜索动态库会第一个搜索这个指定目录,然后是LD_LIBRARY_PATH,再是/etc/ld.so.conf

            中的路径。

            正确的做法:
                 编译:gcc main.c -o main -L/home/user/lib -lmylib -Wl,-rpath=/home/user/lib
 
  结论 :程序运行时,动态库搜索路径顺序:1、编译时-Wl,rpath=指定的路径 2、LD_LIBRARY_PATH                                    3、/etc/ld.so.cache,即/etc/ld.so.conf中的路径。
 
  根据笔者的实践经验,笔者推荐使用第4种方法,原因如下:

         1、对于方法1,诚然简单方便,易于批量部署,但是假如我使用动态库在目标机器也存在,比如                                        libcurl.so,boost库,如果我使用的libcurl.so比目标机器上的libcurl.so库版本高,那么就等于升

           级了目标机器的libcurl.so库文件,虽然Linux约定了动态库版本兼容的规则,但是对于随意升级

          目标机器上的的库文件,有时候会造成一些问题,显然污染了系统文件的纯洁。

        2、对方法2和方法3都需要修改配置文件,比较麻烦,不易于批量部署,而且也容易污染系统文件

    的纯洁。

         3、方法4的库文件路径可以自己定义,与系统库文件隔离了,解决了方法1,2,3存在的问题。
 
 
 

然而在实践过程中,使用方法4会出现一些莫名其妙的问题。

           比如我的程序依赖这个库libcurl.so.4.3.0(一个有名的开源库),并且放在/home/user/lib下,

           编译:gcc main.c -o main -L/home/user/lib -lcurl -Wl,-rpath=/home/user/lib
           这种编译根本通不过,为何?显然 -lcurl 意思是链接到libcurl.so这个文件,而我的库文件是libcurl.4.3.0,当                然链接不到,无法编译。

           应该这样编译:gcc main.c -o main /home/user/lib/libcurl.so.4.3.0  -Wl,-rpath=/home/user/lib 
           可以编译通过,但是程序无法运行。

           为什么会出现这种问题呢?该如何解决呢?请参见下一篇博客《再谈Linux下的动态库》。



以上内容是笔者在工作中,使用动态库、静态库的个人总结,今作记录于此,由于笔者的水平有限,出错在所难免,恳请读者拍砖指正,谢谢阅读。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值