静态库和动态库的生成
一.什么是静态库和动态库
1.静态库
静态库
是程序在编译链接时把库的代码链接到可执行文件
中去。程序运行的时候不需要依赖库
。它以.a
结尾。
2.动态库
动态库是在程序运行起来的时候
才去链接动态库的代码
,多个程序可以共享使用
库的代码。它以.so
结尾。
动态函数库
同共享函数库
是一个东西(在linux上叫共享对象库
, 文件后缀是.so
,windows上叫动态加载函数库, 文件后缀是.dll
)
3.Linux中命名系统中共享库的规则
二.动态库和静态库的优缺点及区别
1.静态库的优点及缺点
优点:
可移植性较强
,一旦可执行程序编译成功不需要依赖静态库
缺点:
- 每一份程序都需要将静态库的
代码链接进去
,生成的可执行程序较大
,浪费空间
2.动态库的优点及缺点
优点:
- 在程序
运行起来,才链接库
,生成的可执行代码较小
,节约内存
- 可以
被多个程序共享
(虚拟内存机制
)
缺点:
可移植性差
。一旦库丢失
了,所有用到它的程序都会崩溃
3.区别
- 它们都是
对二进制文件(.o)
进行打包 动态链接
的可执行文件只需要包含函数入口地址的一个表
,而静态链接
需要外部函数的所有机器码
动态库
可以被多个进程共享
(采用虚拟内存机制),而静态库不行
三.生成并使用静态库和动态库
1.生成静态库
以下边的一个简单例子来生成静态库:
//sum.h
#ifndef __SUM_H__
#define __SUM_H__
int sum(int x,int y);
#endif
//sub.h
#ifndef __SUB_H__
#define __SUB_H__
int sub(int x,int y);
#endif
//sum.c
#include "sum.h"
int sum(int x,int y)
{
return x+y;
}
//sub.c
#include "sub.h"
int sub(int x,int y)
{
return x-y;
}
//main.c
#include<stdio.h>
#include"sum.h"
#include"sub.h"
int main()
{
printf("10+20=%d\n", sum(10,20));
printf("10-20=%d\n", sub(10,20));
}
-
第一步,我们
写好如下程序
-
第二步,
生成二进制文件(.o)
gcc -c sum.c -o sum.o(只用编译器和汇编器,不用连接)
-
第三步,将
.o
文件通过ar
工具打包成静态库
ar -rc libmymath.a sub.o sum.o(-r:打包,-c:创建)
-
第四步,
查看静态库中的目录文件
ar -tv libmymath.a(-t:列出静态库中的文件,-v:详细信息)
-
第五步,
使用静态库
gcc main.c -L. -lmymath(-L:指定库路径,-l:指定库名,把lib和后缀删掉)
在实际使用中
,我们会把头文件和静态库给别人,防止源代码泄露
。我们可以新建一个文件夹,结构如下。lib
下放的是静态库
,而include
下放的头文件
。
在使用时,只需要加上-I + 头文件所在的路劲
即可编译成功。
gcc main.c -L ./staticlib/lib -lmymath -I ./staticlib/include
对于库搜索路径可以有三种方式:
- 用
-L
指定库目录路径 - 用环境变量
LIBRARY_PATH
指定库目录路径 - 把库放入系统指定搜索目录
/uer/lib
Makefile可以这么写:
libmymath.a:sub.o sum.o
ar -rc libmymath.a sub.o sum.o
sub.o:sub.c
gcc -c sub.c -o sub.o
sum.o:sum.c
gcc -c sum.c -o sum.o
.PHONY:clean
clean:
rm -rf sub.o sum.o
2.生成动态库
依然以静态库中的代码为例子:
-
第一步,
编写以下代码:
-
第二步,
编译生成二进制文件(.o)
gcc -fPIC -c sub.c sum.c
,-fPIC参数会产生与位置无关代码,.so
要求PIC码已达到动态链接的目的
,否则,无法实现动态链接
。
-
第三步,
生成动态库
gcc -shared -o libmymath.so *.o
,加上-shared
参数表示生成共享库的格式
-
第四步,
使用动态库
编译选项:-l:代表链接动态库,只要去掉lib和后缀即可
、-L:链接库所在的路径
gcc -L. -lmymath main.c
要想运行动态库
,可以直接加上-L
选项,后边加上链接库所在的路径即可。也可以通过以下两种方法:
- 把动态库拷贝到系统默认搜索路径,
usr/lib
- 把动态库的路径加入到环境变量
LD_LIBRARY_PATH
中
同样,我们也可以把头文件和库放在一个目录中,供别人使用,防止源码泄露: