文章目录
- 什么是动静态库
- 生成静态库
- 生成
- 发布
- 生成动态库
- 发布
- 使用库
- 使用静态库
- 查看系统头文件路径
- 查看系统库文件路径
- 使用库文件和头文件
- 指定路径搜索头文件
- 卸载库
- 使用动态库
- 动态库的运行搜索路径
什么是动静态库
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静
态库 - 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
- 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
- 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
- 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间
安装C语言静态库
yum install -y glibc -static
生成静态库
首先我们库里面是不需要包含main函数的!
链接:就是把所有的.o链接形成一个可执行程序!!!
如果我把我的所有的.o给别人,别人能链接使用吗??—> 当然是可以的!
测试程序
/mymath.h//
#pragma once
#include<stdio.h>
#include<assert.h>
//[from,to]-->累加-->result--->return
extern int addToVal(int from,int to);
/mymath.c//
#include"mymath.h"
int addToVal(int from,int to)
{
assert(from<=to);
int result=0;
for(int i=from;i<=to;i++)
{
result+=i;
}
return result;
}
/myprint.h//
#pragma once
#include<stdio.h>
#include<time.h>
extern void Print(const char* msg);
/myprint.c//
#include"myprint.h"
void Print(const char* msg)
{
printf("%s : %lld\n",msg,(long long)time(NULL));
}
生成
命令
ar -rc [文件]
(ar是gnu的归档工具,rc表示(replace and create))
libmymath.a:mymath.o myprint.o
ar -rc libmymath.a mymath.o myprint.o
mymath.o:mymath.c
gcc -c mymath.c -o mymath.o -std=c99
myprint.o:myprint.c
gcc -c myprint.c -o myprint.o -std=c99
.PHONY:clean
clean:
rm -f *.o *.a
发布
问题:我们在用库的时候需要什么东西呢??
答:库文件和头文件!!—>就可以给别人使用了
命令
.PHONY:static
static:
mkdir -p lib-static/lib;\
mkdir -p lib-static/include;\
cp *.a lib-static/lib;\
cp *.h lib-static/include
生成动态库
- shared: 表示生成共享库格式
- fPIC:产生位置无关码(position independent code)—>以后编译的源代码无论生成的.o文件在哪里都可以执行
- 库名规则:libxxx.so
libmymath.so:mymath.o myprint.o
gcc -shared -o libmath.so mymath.o myprint.o
mymath.o:mymath.c
gcc -fPIC -c mymath.c -o mymath.o -std=c99
myprint.o:myprint.c
gcc -fPIC -c myprint.c -o myprint.o -std=c99
.PHONY:clean
clean:
rm -rf *.o *.so
发布
.PHONY:dyl
dyl:
mkdir -p lib-dyl/lib;\
mkdir -p lib-dyl/include;\
cp *.so lib-dyl/lib;\
cp *.h lib-dyl/include
使用库
使用静态库
#include"mymath.h"
#include"myprint.h"
int main()
{
int start=0;
int end=100;
int result=addToVal(start,end);
printf("%d\n",result);
Print("hello world");
return 0;
}
首先我们先来回顾C语言头文件的搜索路径: “” <>
- “” 在当前路径下查找头文件
- <> 在系统头文件路径下查找头文件
- 指定路径头文件的搜索路径(-I(include) 你的头文件搜索路径 -L(link) 你的库路径 -l 具体哪一个库文件)
谁在头文件呢???—>编译器---->进程
查看系统头文件路径
ls /usr/include/
查看系统库文件路径
ls /lib64/
使用库文件和头文件
将自己的头文件和库文件,拷贝到系统路径下即可!!!(库的安装)
sudo cp lib-static/include/* /usr/include/
sudo cp lib-static/lib/* /usr/lib64/
gcc -l(指明我要链接的第三方库的名称)
但是不推荐这种做法,因为这种做法会污染系统的头文件和库文件!
指定路径搜索头文件
gcc mytest.c -o mytest -I ./lib-static/include/
卸载库
sudo rm /usr/include/mymath.h
sudo rm /usr/include/myprint.h
sudo rm /lib64/libmymath.a
使用动态库
第一种方法和静态库的使用一模一样:将自己的头文件和库文件,拷贝到系统路径下即可!!!
这里就不做演示了!
第二种指定路径包含头文件和库文件
编译的时候gcc所带的-I,-L,-l选项是给谁带的? ---->gcc
所以形成可执行程序后,与编译器gcc就没有任何关系了。
所以./mytest运行进程后,并没有告诉进程这个库链接在哪里!!
动态库的运行搜索路径
根据上面的问题,进程找不到对应的动态库!
- 那么静态库的时候,怎么没有这个问题呢?–>形成可执行程序之后,已经把需要的代码拷贝进我的代码中!运行时不依赖你的库!—>不需要运行时查找了
- 为什么动态库会有这个问题呢? 程序和动态库是分开加载的!
那么如何解决找不到动态库的问题呢??想办法让进城找到动态库即可!
- 动态库拷贝到系统路径下/lib64/ —>安装
- 通过导入环境变量的方式---->程序运行的时候,会在环境变量中查找自己需要的动态库路径(LD_LIBRARY_PATH)
- 系统配置文件来做
- 其他方式(添加软连接)