动静态库的基本原理:
- 可执行程序的生成包括预处理、编译、汇编和链接四个步骤。
- 源文件经过编译、汇编生成目标文件(.o文件),然后链接生成可执行程序。
- 对于频繁使用的源文件,可以将它们的目标文件打包成库文件,称为静态库或动态库。
认识动静态库:
使用ldd命令可以查看一个可执行程序所依赖的库文件,如libc.so.6。
Linux下,以.so为后缀的是动态库,以.a为后缀的是静态库。
静态库和动态库的特征:
- 静态库:在编译链接时将库的代码复制到可执行文件中,使可执行文件独立运行,但占用较多磁盘空间。
- 动态库:在运行时动态链接库的代码,多个程序可以共享同一库,节省磁盘和内存空间,但必须依赖动态库才能运行。
静态库:
打包静态库:
- 编译源文件生成目标文件:首先,编译每个源文件,生成对应的目标文件。例如:
csharpCopy codegcc -c add.c sub.c
- 使用ar命令创建静态库:使用ar命令将所有目标文件打包成一个静态库文件。使用以下命令进行打包:
ar -rc libcal.a add.o sub.o
- -r
- -c
-
-r
选项表示将文件插入(或替换)到归档文件中。也就是说,它会更新已存在的归档文件libcal.a
,或者如果libcal.a
不存在,它会创建一个新的归档文件并将add.o
和sub.o
这两个目标文件插入到其中。 -
-c
选项告诉ar
命令创建一个新的归档文件,如果它不存在的话。如果省略了-c
选项,并且libcal.a
文件不存在,ar
命令将会报错。所以,在这个命令中,-c
选项确保如果libcal.a
不存在,它会被创建。
组织头文件和库文件:将头文件和生成的静态库文件放入适当的目录结构中,以便其他人使用。
使用静态库:
- 编写源文件:创建需要使用静态库的源文件,例如main.c。
- 编译源文件并链接静态库:使用gcc编译器编译源文件,并链接静态库。需要指定头文件和库文件的搜索路径以及使用-l选项指定库文件名。例如:
gcc main.c -I./mathlib/include -L./mathlib/lib -lcal -o my_program
- -I
- -L
- 生成可执行程序:执行上述编译命令将生成可执行程序,例如my_program。
- 运行程序:运行生成的可执行程序来使用静态库中的函数。
注意事项:
- 头文件和库文件的拷贝:如果不希望拷贝到系统路径下,可以在编译时指定搜索路径。
- 库文件命名规则:库文件名通常以lib开头,去掉前缀lib和后缀.so或者.a以及版本号,剩下的就是库的名字。
- make工具:使用Makefile可以自动化打包和编译过程,使操作更简便。
- 拷贝到系统路径:虽然可以拷贝头文件和库文件到系统路径,但这样做可能对系统造成污染,不推荐。
总之,静态库的打包与使用需要编译源文件、创建静态库、指定搜索路径和链接库文件,以及组织头文件和库文件等步骤。可以使用make工具来简化这些操作。
动态库:
打包动态库:
- 编译源文件生成目标文件:使用
-fPIC 选项编译源文件,生成位置无关的目标文件。例如:
gcc -c -fPIC add.c sub.c
- 使用
-shared 选项将目标文件打包成动态库:使用以下命令进行打包:
gcc -shared -o libcal.so add.o sub.o
- -shared
- -o
-
-shared
选项告诉gcc
编译器生成一个共享库(shared library)文件,而不是生成可执行文件。共享库是一种可重用的二进制代码,它可以被多个程序共享,以减少内存使用和磁盘空间占用。共享库的扩展名通常是.so
(在类Unix系统中)或.dll
(在Windows系统中)。 -
-o
选项后跟着输出文件的名称,这里是libcal.so
。这个选项用于指定生成的共享库的名称。在这个命令中,生成的共享库将被命名为libcal.so
。
将头文件和生成的动态库组织起来:将头文件(add.h和sub.h)放入一个名为include的目录下,将生成的动态库文件(libcal.so)放入一个名为lib的目录下,然后将这两个目录都放到mlib目录下,以便其他人使用。
使用动态库:
- 编写源文件:创建需要使用动态库的源文件,例如main.c。
- 编译源文件并链接动态库:使用gcc编译器编译源文件,并链接动态库。需要指定头文件和库文件的搜索路径以及使用-l选项指定库文件名。例如:
gcc main.c -I./mlib/include -L./mlib/lib -lcal -o my_program
- -I
- -L
- 生成可执行程序:执行上述编译命令将生成可执行程序,例如my_program。
- 运行程序:运行生成的可执行程序来使用动态库中的函数。
解决动态库加载问题:
如果系统找不到动态库,有几种解决方法:
- 方法一:拷贝库文件到系统共享库路径下,如/lib64。
sudo cp mlib/lib/libcal.so /lib64
- 方法二:更改LD_LIBRARY_PATH环境变量,将库文件所在目录路径添加进去。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/mlib/lib
- 方法三:配置
/etc/ld.so.conf.d/,创建以 .conf 后缀的配置文件,其中包含库文件所在目录的路径,并使用 ldconfig 命令更新配置。
sudo echo "/path/to/mlib/lib" > /etc/ld.so.conf.d/mylib.conf sudo ldconfig
以上步骤和命令可用于打包和使用动态库,使程序能够正确加载和运行动态库中的函数。
注意:/etc/ld.so.conf.d/ 目录通常被称为"ld.so配置目录",或者更具体地说,它是用于配置Linux系统中动态链接器的目录。在这个目录下,您可以创建包含库文件路径的配置文件,这些路径将被动态链接器用于查找共享库文件。每个配置文件应该包含一个库文件路径,以指导动态链接器在运行时查找共享库。
这个目录的主要作用是使系统管理员可以更灵活地管理库文件的位置,而不必修改全局的/etc/ld.so.conf文件。通过在/etc/ld.so.conf.d/目录中创建配置文件,系统管理员可以轻松地添加、删除或更改库文件路径,而无需干扰系统的全局配置。这种方式有助于维护和管理库文件的位置,同时确保系统的兼容性和稳定性。