linker & lib
大体上 C 程序构建过程可以分为预编译、编译、汇编以及链接四个过程。
库的分类
库的分类 | 备注 | 优劣 |
---|---|---|
static lib | 将库文件与目标文件在程序构建的链接阶段链接在一起即静态链接。 | 它的好处是程序运行不再依赖系统中存在这样一个库文件供调用,因为它已经在程序可执行文件中了。缺点是如果同一个库被大量程序使用,那么静态链接将导致空间浪费、库有问题修复需要所有使用该库的程序重新编译。 |
dynamic lib | 动态库的链接是在程序执行的时候被链接的。 | 动态库的出现正弥补了静态库的以上弊端。劣势是如果系统不存在程序所需的动态库,那程序将无法运行。运行速度稍逊,但在如今的硬件能力面前不值一提,因此动态链接使用非常广泛。 |
库的创建及使用
创建目录如下:
.
├── main.c
├── Makefile
└── so.c
// main.c
#include <stdio.h>
extern void hello(void);
int main()
{
printf("call func in the so\n");
hello();
return 0;
}
// so.c
#include <stdio.h>
void hello(void)
{
printf("Hello world\n");
}
// Makefile
CC=aarch64-linux-gnu-
a.out: libso.so a_static.out main.c
${CC}gcc main.c -lso -L. -o $@
a_static.out: libso.a main.c
${CC}gcc main.c -lso -L. -o $@ -static
libso.so: so.c
${CC}gcc -shared so.c -o $@
libso.a: so.c
${CC}gcc -c so.c -o so.o
${CC}ar -r $@ so.o
.PHONY: clean
clean:
${RM} -rf *.so *.a *.out *.o
在当前目录下执行 make
命令得到如下文件。其中 a_static.out
是通过与 libso.a
静态链接而来,a.out
是通过与 libso.so
动态链接而来。
.
├── a.out
├── a_static.out
├── libso.a
├── libso.so
├── main.c
├── Makefile
├── so.c
└── so.o
-l
提示 linker 寻找名为 libxxx.a
或 libxxx.so
的库
-L
提示 linker 去哪些目录下寻找 -l
指定的库
生成动态链接库使用 -shared
选项
生成静态库则使用 ar
命令将 .o
文件打包即可。
动态链接的程序要运行需要指定库路径,否则运行会报错。
方法可以是:
- 把当前路径加到
/etc/ld.so.conf
中,然后运行ldconfig
- 以当前路径为参数运行
ldconfig
- 将当前路径添加到环境变量
LD_LIBRARY_PATH
中,export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
- 将动态库拷到 /lib /usr/lib 路径下,原因是操作系统默认会从上述路径中找动态库
推荐使用方法3,即通过环境变量的方式来指定动态库路径,这样影响最小。
动态库的原理
这部分挖个坑,之后再谈 😃。