目录
这里以一个包含两个.h文件的静态库为例进行演示说明
其中首先我创建两个文件夹。在mklib中演示创建静态库,在uselib中演示调用静态库
一、静态库的创建
1.创建.h与.c文件
这四个用于演示的示例代码具体如下
mymath.h
#pragma once
#include<stdio.h>
extern int addToTarget(int from, int to);
mymath.c
#include "mymath.h"
int addToTarget(int from, int to)
{
int sum = 0;
for(int i = from; i <= to; i++)
{
sum += i;
}
return sum;
}
myprint.h
#pragma once
#include <stdio.h>
#include <time.h>
extern void Print(const char *str);
myprint.c
#include "myprint.h"
void Print(const char *str)
{
printf("%s[%d]\n", str, (int)time(NULL));
}
2.编写Makefile文件
具体内容如下
libhello.a: mymath.o myprint.o
ar -rc libhello.a mymath.o myprint.o
mymath.o:mymath.c
gcc -c mymath.c -o mymath.o
myprint.o:myprint.c
gcc -c myprint.c -o myprint.o
.PHONY:hello
hello:
mkdir -p hello/lib
mkdir -p hello/include
cp -rf *.h hello/include
cp -rf *.a hello/lib
.PHONY:clean
clean:
rm -rf *.o libhello.a hello
其中 ar
工具来创建静态库 libhello.a
,并将 mymath.o
和 myprint.o
这两个目标文件打包到这个静态库中。
具体来说:
ar
是用于创建和修改静态库的命令行工具。-rc
是ar
命令的选项,它表示 "create" 和 "replace",即创建一个新的静态库,如果同名的库文件已存在,则替换它。libhello.a
是要创建的静态库的名称。mymath.o
和myprint.o
是要打包进静态库的目标文件。
3.生成静态库
运行make与make hello指令
即静态库文件hello应包含两个文件夹lib与include,将全部.a文件放入lib文件夹中,将全部头文件放入include文件夹
此时可以看到已经生成了hello静态库
二、静态库的使用
首先将刚刚创建的库复制到uselib文件夹中进行演示
1.编写要调用静态库的主函数
main.c代码如下
#include "myprint.h"
#include "mymath.h"
int main()
{
Print("hello world");
int res = addToTarget(1,100);
printf("res: %d\n", res);
return 0;
}
2.调用静态库生成可执行程序
-I ../uselib/hello/include
选项指定了编译器在搜索头文件时要包含的目录,这里是../uselib/hello/include
,即头文件所在的目录。-L ../uselib/hello/lib
选项指定了编译器在搜索库文件时要包含的目录,这里是../uselib/hello/lib
,即静态库文件所在的目录。-lhello
选项指定了要链接的静态库,这里是hello
,编译器将在指定的目录中搜索libhello.a
静态库文件,并将其链接到可执行文件中。
3.运行程序
调用成功
三、动态库的创建
1.创建.h与.c文件
这一步与一中的1完全一样
2.编写Makefile文件
这里需要新的指令具体代码如下(这里为了与前面静态库做出区别,将hello文件夹改成了output)
1 .PHONY:all
2 all:libhello.so libhello.a
3
4 libhello.so:mymath_d.o myprint_d.o
5 gcc -shared mymath_d.o myprint_d.o -o libhello.so
6 mymath_d.o:mymath.c
7 gcc -fPIC -c mymath.c -o mymath_d.o
8 myprint_d.o:myprint.c
9 gcc -fPIC -c myprint.c -o myprint_d.o
10
11 libhello.a:mymath.o myprint.o
12 ar -rc libhello.a mymath.o myprint.o
13 mymath.o:mymath.c
14 gcc -c mymath.c -o mymath.o
15 myprint.o:myprint.c
16 gcc -c myprint.c -o myprint.o
17
18 .PHONY:output
19 output:
20 mkdir -p output/lib
21 mkdir -p output/include
22 cp -rf *.h output/include
23 cp -rf *.a output/lib
24 cp -rf *.so output/lib
25
26
27 .PHONY:clean
28 clean:
29 rm -rf *.o *.a *.so output
-fPIC
是一个编译选项,表示 "Position Independent Code",即生成位置无关的代码。位置无关代码可以在内存中的任何位置执行,因此通常用于动态链接库(shared library)的编译。-
gcc -shared mymath_d.o myprint_d.o -o libhello.so这个命令使用
gcc
编译器将两个位置无关的目标文件mymath_d.o
和myprint_d.o
编译成一个共享库libhello.so,
其中-shared
选项告诉编译器生成一个共享库。共享库是一种可以被动态链接到程序中的库,通常具有.so
扩展名。
3.生成静态库
首先运行make
可以看到生成了.so的动态共享库
再运行make output
最后得到如下结果
四、动态库的使用
1.编写要调用动态库的主函数
这里与二中的1完全一样,写出一个main.c
2.调用动态库生成可执行程序
与二中的2类似,将output移动到main.c的目录中
当前目录如下
使用如下指令生成可执行程序main.out
3.运行程序
与调用静态库不同,此时如果直接运行会出现如下找不到的情况
因此调用动态库还需要进行配置,这里提供三种方法
- 方法一:建立软链接方案
在系统路径下建立动态库的软链接,具体指令为
这里需要用绝对路径,同时需要sudo权限。可以用下面指令查看是否链接成功
链接成功后就可以直接运行main.out了
- 方法二:配置系统文件/etc/ld.so.conf.d/
第一种方法是配置系统文件的方法
首先在/etc/ld.so.conf.d/路径下创建一个.conf文件,这里命名为libsoTest.conf作为示例。
需要注意,这里需要sudo权限
创建成功后将动态库(.so文件)所在路径写入到刚刚创建的libsoTest.conf中
这里直接使用vim进行写入即可
接着运行ldconfig即可
最后就可以正常运行main.out
- 方法三:更改 LD_LIBRARY_PATH环境变量
将动态库(.so文件)所在路径写入到环境变量中,具体指令如下
可以使用echo检查是否添加成功
最后直接运行即可
但使用此方法需要注意,一旦退出当前系统(如exit或关闭xshell等)后重新登入时,需要重新将目录写进环境变量中,即该种方法是只写在内存中,因此这里推荐前两种方法。