ubuntu下库的制作与使用

来源:互联网 发布:c 编程培训中心 编辑:程序博客网 时间:2024/05/21 10:37

静态库:程序在编译的时候,如果链接的是静态库,会把程序中需要调用的函数接口实现代码从静态库中拷贝到可执行程序文件中,生成的可执行文件体积大,程序在运行的时候,不需要库的支持。

动态库:程序在编译的时候,如果链接的是动态库,此时在可执行文件的头信息中记录动态库的名字,在程序运行的时候,操作系统会读取可执行文件的头信息,从而知道可执行文件在运行的时候,需要加载那些动态库。

注意:动态连接的时候,生成可执行文件体积小,但是程序在运行的时候,需要加载动态库。

库的格式:静态库  libname.a 动态库  libname.so

库的名字:如libjpeg.so 这个库的名字是jpeg

gcc 编译器的参数:-I(指定头文件路径)  指定编译器搜索头文件路径的路径,默认在/usr/include 目录下搜索;

        -L(指定库的路径) 指定编译器在链接库的时候,搜索的路径,默认在/usr/lib 和 /lib搜索;

        -l(指定库的名字)指定编译器链接时候链接的库的名字。

现在有test.h、test1.c、test2.c、test3.c、main.c四个文件,文件内容如下:

1 #ifndef __TEST_H__2 #define __TEST_H__4 #include <stdio.h>5 void test_1();6 void test_2();7 void test_3();8 #endiftest1.c 1 #include "test.h"2 void test_1()3 {4     printf("I am test_1\n");5 }test2.c 1 #include "test.h"2 3 void test_2()4 {5     printf("I am test_2\n");6 }test3.c 1 #include "test.h"2 3 void test_3()4 {5     printf("I am test_3\n");6 }

生成静态库:
(1)将xxx.c编译成xxx.o gcc-c xxx.c -o xxx.o这里使用gcc -c test?.c
(2)将xxx.o打包生成静态库 ar crs libxxx.a *.o这里使用ar crs libtest.a *.o
(3)使用静态库 gcc  xxx.c -L 库的路径  -l(小写的L)库的名字这里使用gcc -o main main.c -L. -ltest
然后运行和查看程序:

# ./main I am test_1I am test_2I am test_3# ldd mainlinux-vdso.so.1 =>  (0x00007fffec35b000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1868778000)/lib64/ld-linux-x86-64.so.2 (0x000055a159aef000)
此时如果删除libtest.a文件程序也是可以正常运行的,并且main可执行程序会比其他动态可执行文件大很多。
生成动态库:
(1)生成动态库 gcc -fPIC -shared test?.c -o libtest.so
(2)使用动态库 gcc -o main main.c -L. -ltest
但是此时如果使用ldd或者运行test程序的话,就会发现程序还是运行不了。
#ldd testlinux-vdso.so.1 => (0x00007ffea3b8a000)libtest.so => not foundlibc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f095aa14000)/lib64/ld-linux-x86-64.so.2 (0x00005564bf151000)
这个因为我们个人的so库,并不能被系统直接识别。
解决方法:

1、(1)vim /etc/ld.so.conf.d/test.conf(2)/root/so_test/(添加动态库目录)(3)ldconfig

2、执行export LD_LIBRARY_PATH=$(pwd)或export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库的路径,然后重新运行程序,但是每次都这样会显得很麻烦,将它写入用户主目录下.bashrc或者/etc/bash.bashrc中可以永久有效。

3、把库直接放到/lib/或者/usr/lib/目录下

操作系统默认加载动态库搜索路径:
(1)在LD_LIBRARY_PATH环境变量中包含的路径搜索
(2)在/usr/lib 和 /lib目录下搜索
编译时用到的参数:
-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。

-L.:表示要连接的库在当前目录中

-ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称,LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。

-shared:该选项指定生成动态连接库,让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号,不用该标志外部程序无法连接相当于一个可执行文件。

-I(指定头文件路径,大写的i)  指定编译器搜索头文件路径的路径,默认在/usr/include 目录下搜索。

-L(指定库的路径) 指定编译器在链接库的时候,搜索的路径,默认在/usr/lib 和 /lib搜索。

-l(指定库的名字,小写的L)指定编译器链接时候,库的名字。

相关的路径:配置文件/etc/ld.so.conf中指定的动态库搜索路径。
相关的环境变量:(1)LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径(2)LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径。

静态库的链接时搜索路径顺序:

1、ld会去找GCC命令中的参数-L

2、 再找gcc的环境变量LIBRARY_PATH

3、 再找内定目录 /lib /usr/lib /usr/local/lib

动态库的链接是搜索路径顺序:

1、编译目标代码时指定的动态库搜索路径;

2、环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

3、配置文件/etc/ld.so.conf中指定的动态库搜索路径;

4、默认的动态库搜索路径/lib;

5、默认的动态库搜索路径/usr/lib。

可能遇到的问题:如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到链接动态库的目的,如果没有root权限,可以通过环境变量LD_LIBRARY_PATH来达到相同的目的。调用动态库会经常碰到几个问题,有时,明明已经将库的头文件所在目录通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。
思考:
问题:如果动态和静态库同时在一个目录下存在,编译器默认链接的时候,是什么库呢?
回答:默认链接的是动态库,如果需要链接静态库,此时需要加上 -static 参数
问题:如果库的名字有版本号,编译如何识别呢?
回答:此时需要建立一个软连接连接到库,但是软连接文件的名称要符合库的命名规则(libxxx.a ,libxxx.so )


原创粉丝点击