Haohao Notes

DREAM OF TECHNICAL ACHIEVEMENT

0%

Linux 生成静态链接库与动态链接库

所谓的库就是一种可执行代码的二进制形式,可以被操作系统载入内存执行。

静态库和动态库

静态库 .a

文件的命名方式:“libxxx.a”,库名前加“lib”,后缀是“.a”,库名是“xxx”

链接时间:静态库的代码是在编译过程中被载入到程序中的

链接方式:静态库的链接是将整个函数库的所有数据都合成进了目标代码,优点是编译后的执行程序不需要外部的函数库支持,因为所使用的函数已经被编进去了;缺点是如果所使用的静态库发生更新改变,则需要重新编译生成静态库。

动态库 .so

文件命名方式:“libxxx.so”,库名前加“lib”,后缀是“.so”,库名是“xxx”

链接时间:动态库在编译时并没有被编译进目标代码,而是当你的程序执行到相关函数的时候才调用该函数库里的相应函数。缺点是函数库并没有整合进程序,所以程序的运行环境必须提供相应的库;优点是动态库的改变不影响程序。

二者的区别:同一个程序分别使用静态库和动态库生成两个可执行文件时,静态库链接所生成的那个可执行文件要比动态库链接所生成的可执行文件占用的空间大。

gcc常用参数

参数 说明
0 指定目标
c 生成二进制汇编文件
W 警告all
g gdb调试
E,S 预处理和汇编
D debug调试
I 指定包含路径
L 指定库路径
l 指定库名,libxxx.a,libxxx.so

文件准备

1
2
3
4
5
6
7
8
9
10
[root@centos-linux static link library]# tree
.
├── include
│   └── head.h // 头文件
├── lib
│   ├── add.c // 加法
│   └── sub.c // 减法
└── main.c

2 directories, 4 files

head.h

1
2
int add (int a, int b);
int sub (int a, int b);

add.c

1
2
3
4
5
6
#include "head.h"

int add(int a, int b)
{
return a+b;
}

sub.c

1
2
3
4
5
6
#include "head.h"

int sub(int a, int b)
{
return a-b;
}

main.c

1
2
3
4
5
6
7
#include <stdio.h>
#include "head.h"

int main(void)
{
printf("%d",add(1,2));
}

静态库生成

  1. 使用如下命令,将.c文件生成.o的汇编文件
1
2
3
4
[root@centos-linux lib]# gcc -c *.c -I ../include/
[root@centos-linux lib]# ls
add.c add.o sub.c sub.o
[root@centos-linux lib]#
  1. 由.o文件生成.a的静态库文件,静态库的名字问libCalc.a

ar rcs libCalc.a *.o

执行完毕后可以通过目录看到多了一个libCalc.a的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@centos-linux static link library]# tree
.
├── include
│   └── head.h
├── lib
│   ├── add.c
│   ├── add.o
│   ├── libCalc.a
│   ├── sub.c
│   └── sub.o
└── main.c

2 directories, 7 files

nm查看文件链接符号

1
2
3
4
5
6
7
[root@centos-linux lib]# nm libCalc.a

add.o:
0000000000000000 T add

sub.o:
0000000000000000 T sub
  1. 使用静态库进行静态链接,生成可执行文件app

gcc main.c -o app -I include/ -L lib/ -lCalc

1
2
3
4
5
[root@centos-linux static link library]# gcc main.c -o app -I include/ -L lib/ -lCalc
[root@centos-linux static link library]# ls
app include lib main.c
[root@centos-linux static link library]# ./app
3

动态库生成

  1. 使用如下命令,将.c文件生成.o的汇编文件
1
2
3
4
[root@centos-linux lib]# gcc -c *.c -I ../include/
[root@centos-linux lib]# ls
add.c add.o sub.c sub.o
[root@centos-linux lib]#
  1. 生成动态库

gcc -fPIC -shared -o libCalc.so *.o

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@centos-linux lib]# gcc -fPIC -shared -o libCalc.so *.o  
[root@centos-linux static link library]# tree
.
├── app
├── include
│   └── head.h
├── lib
│   ├── add.c
│   ├── add.o
│   ├── libCalc.so
│   ├── sub.c
│   └── sub.o
└── main.c

2 directories, 8 files
  1. 链接生成可执行文件

gcc main.c -o app -I include/ -L lib/ -lCalc

1
[root@centos-linux static link library]# gcc main.c -o app -I include/ -L lib/ -lCalc

生成的可执行文件是app,./app执行可执行文件时报如下错

1
2
[root@centos-linux static link library]# ./app 
./app: error while loading shared libraries: libCalc.so: cannot open shared object file: No such file or directory

因为执行程序找不到libCalc.so

用:ldd app命令查看libCalc.so库,发现其找不到

找不到lib库解决方案

方案一

原因是在 /etc/ld.so.conf 文件中设置了动态链接库了寻找路径

1
2
3
4
[root@centos-linux lib]# vi /etc/ld.so.conf
include ld.so.conf.d/*.conf
#加上自己编译的lib目录
/root/CppCode/static link library/lib

可以看到有很多路径设置文件,在ld.so.conf文件中添加libCalc.so的路径

然后执行:ldconfig命令

此时执行可执行文件app就能成功了。

方案二

将编译好的链接库拷贝到/bin,/usr/lib这样的系统库目录下

方案三

设置环境变量,LD_LIBRAY_PATH, export LD_LIBRAY_PATH=libpath:$LD_LIBRAY_PATH