linux如何使用gcc生成静态库和动态库


1、静态库与动态库的区别:

       linux下库分为两种:静态库和动态库(也叫共享库)。

           静态库,在编译时,已经被载入到可执行程序中,静态库成为可执行文件的一部分,因此可可执行程序文件比较大。

          动态库,可执行程序在执行时才被引用到内存,因此可执行程序文件小。动态库,一个显著特点就是:当多个程序调用同个动态库时,内存中只有一个动态库实例

2、库命名规范

            a)静态库以
.a 为后缀,动态库以.so为后缀
            b)静态库名字一般是libxxx.a,其中xxx 是库的名字;动态库的名字一般是libxxx.so.major.minor 其中xxx是库名,majar 是主版本号,minor是副版本号
3、通过ldd查看程序所依赖的共享库


           
查看vim所依赖的共享库:ldd /usr/bin/vim 
4、程序查找动态库的路径


            /lib 和 /usr/lib 及 /etc/ld.so.conf配置的路径下
有了上面的简单介绍,下面,我们开始给出代码示例了:
1、库源文件:demo.c,

#include<stdio.h>  
  
int add(int a, int b)  
{  
        return a+b;  
}  
int sub(int a, int b)  
{  
        return a-b;  
}  
void showmsg(const char * msg){  
        printf("%s \n",msg);  
}  
void show(int num)  
{  
        printf("The result is %d \n",num);  
}  


2、库头文件: demo.h

#ifndef DEMO_H  
#define DEMO_H  
extern int add(int a, int b);  
extern int sub(int a, int b);  
extern void showmsg(const char* msg);  
extern void show(int num);  
#endif  


3、调用库源文件:main.c

#include "demo.h"  
  
int main(void){  
        int a = 3;  
        int b = 6;  
        showmsg("3+6:");  
        show(add(a,b));  
        showmsg("3-6:");  
        show(sub(a,b));  
        return 0;  
}  


4、编译源文件

[root@localhost demo]# gcc -c demo.c


[root@localhost demo]# gcc -c main.c  


5、编译可执行程序:

[root@localhost demo]# gcc -o demo demo.o main.o  


6、查看可执行文件demo并执行

[root@localhost demo]# ls -lh  
总计 28K  
-rwxr-xr-x 1 root root 5.2K 02-24 10:36 demo  
-rw-r--r-- 1 root root  212 02-24 10:06 demo.c  
-rw-r--r-- 1 root root  134 02-24 09:55 demo.h  
-rw-r--r-- 1 root root 1000 02-24 10:10 demo.o  
-rw-r--r-- 1 root root  142 02-24 10:07 main.c  
-rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o  


[root@localhost ~]# ./demo  
3+6:  
The result is 9  
3-6:  
The result is -3 


通过上面的基本,我们的可执行文件demo已经跑起来了,下面,我们主要介绍怎么把demo.c封装成库,供其他代码调用,以提高代码的可复用性

静态库:
主要通过ar 把demo.o打包成静态库并查看相关文件

[root@localhost demo]# ar rcs libdemo.a demo.o  


[root@localhost demo]# ls -lh  


-rw-r--r-- 1 root root  212 02-24 10:06 demo.c  
-rw-r--r-- 1 root root  134 02-24 09:55 demo.h  
-rw-r--r-- 1 root root 1000 02-24 10:10 demo.o  
-rw-r--r-- 1 root root 1.2K 02-24 10:40 libdemo.a  
-rw-r--r-- 1 root root  142 02-24 10:07 main.c  
-rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o  


ar命令类似于tar命令,起打包的作用。选项r表示将后面的文件列表添加到文件包,如果文件包不存在就创建,
如果文件包中已存在就替换。s是专用于生成静态库的,表示为静态库创建索引,这个索引被链接器使用。
引入静态库,编译可执行文件

[root@localhost demo]# gcc -o demo main.c -static -L . -l demo  


     注意:gcc生产目标可执行文件,用-l 指定静态库文件时,会自动在静态库名前加lib,在其后加.a 。因此,在引入libdemo.a 静态库时,只用写 demo 即可。-L . 告诉编辑器在当前目录查找函数库。(可以用nm查看目标代码,函数库和可执行程序中具有哪些函数)


查看生成文件demo,删除静态库libdemo.a ,并执行demo

[root@localhost demo]# ls -lh  
总计 568K  
-rwxr-xr-x 1 root root 537K 02-24 10:44 demo  
-rw-r--r-- 1 root root  212 02-24 10:06 demo.c  
-rw-r--r-- 1 root root  134 02-24 09:55 demo.h  
-rw-r--r-- 1 root root 1000 02-24 10:10 demo.o  
-rw-r--r-- 1 root root 1.2K 02-24 10:40 libdemo.a  
-rw-r--r-- 1 root root  142 02-24 10:07 main.c  
-rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o  


[root@localhost demo]# rm -rf libdemo.a  


[root@localhost demo]# ./demo  
3+6:  
The result is 9  
3-6:  
The result is -3  


通过上面的演示,我们可以很清楚地看到,引导引入静态库之后,可执行程序就不依赖原有静态库了,这是因为,可执行程序中已经包含了静态库。

动态库:
通过gcc生产静态库libdemo.so文件并查看相关文件

[root@localhost demo]# gcc -shared -fPIC -o libdemo.so demo.o  


[root@localhost demo]# ls -lh  
总计 28K  
-rw-r--r-- 1 root root  212 02-24 10:06 demo.c  
-rw-r--r-- 1 root root  134 02-24 09:55 demo.h  
-rw-r--r-- 1 root root 1000 02-24 10:10 demo.o  
-rwxr-xr-x 1 root root 4.3K 02-24 10:50 libdemo.so  
-rw-r--r-- 1 root root  142 02-24 10:07 main.c  
-rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o  


-f后面跟一些编译选项,PIC表示与位置无关代码【position independent code】
引入动态库libdemo.so,生成可执行文件demo并执行

[root@localhost demo]# gcc -o demo main.c -L . -l demo  


注意:-l demo 表示链接libdemo.so ,-L . 表示函数库可能在当前目录

[root@localhost demo]# ls -lh  
总计 36K  
-rwxr-xr-x 1 root root 5.4K 02-24 10:52 demo  
-rw-r--r-- 1 root root  212 02-24 10:06 demo.c  
-rw-r--r-- 1 root root  134 02-24 09:55 demo.h  
-rw-r--r-- 1 root root 1000 02-24 10:10 demo.o  
-rwxr-xr-x 1 root root 4.3K 02-24 10:50 libdemo.so  
-rw-r--r-- 1 root root  142 02-24 10:07 main.c  
-rw-r--r-- 1 root root 1.1K 02-24 10:36 main.o  


[root@localhost demo]# ./demo  
./demo: error while loading shared libraries: libdemo.so: cannot open shared object file: No such file

为什么,无法成功执行呢?查看可执行程序demo所依赖的动态库

[root@localhost demo]# ldd demo  
        linux-gate.so.1 =>  (0x0022b000)  
        libdemo.so => not found  
        libc.so.6 => /lib/libc.so.6 (0x0022c000)  
        /lib/ld-linux.so.2 (0x0019c000)  


从提示中,我们可以很清楚地看到,是libdemo.so 没有找到。怎么可以让可执行文件找到该动态库呢?

[root@localhost demo]# mv libdemo.so /usr/lib  
[root@localhost demo]# ./demo  
3+6:  
The result is 9  
3-6:  
The result is -3  

b)设置加载库环境变量LD_LIBRARY_PATH并执行  

[root@localhost demo]# export LD_LIBRARY_PATH=$(pwd)  
[root@localhost demo]# ./demo  
3+6:  
The result is 9  
3-6:  
The result is -3  


c)通过ldconfig 将指定目录下的动态库添加到系统共享中,也就是在缓存文件/etc/ld.so.cache中追加指定目录下的共享库

[root@localhost demo]# ldconfig /root/code/c/demo  
[root@localhost demo]# ./demo  
3+6:  
The result is 9  
3-6:  
The result is -3  

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

1. ld会去找GCC命令中的参数-L
2. 再找gcc的环境变量LIBRARY_PATH
3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

动态链接时、执行时搜索路径顺序:

1.  编译目标代码时指定的动态库搜索路径;
2.  环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3.  配置文件/etc/ld.so.conf中指定的动态库搜索路径;
4. 默认的动态库搜索路径/lib;
5. 默认的动态库搜索路径/usr/lib。

附带几个参考资料网址:
gcc中文手册:http://www.shanghai.ws/gnu/gcc_1.htm
gcc官网手册:http://gcc.gnu.org/onlinedocs/




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值