函数库管理——动态函数库与静态函数库
静态函数库与动态函数库基本认知:
GCC编译基础流程包括:预处理、编译、汇编、链接。注意在特定语义环境中区别第一个编译和第二个编译的含义。
静态链接:链接器在链接时将库的内容加入到可执行程序中
动态链接:链接器在链接时仅仅建立与所需库函数之间的链接关系,在程序运行时才将所需资源调入可执行程序中
静态函数库(静态链接库):程序编译时使用
被称作:archive
扩展名:.a
命名格式:libxxx.a
独立执行:编译成功的可执行文件可以独立执行
升级难易度:难
动态函数库(动态链接库):程序运行时使用
被称作:shared object
扩展名:.so
命名格式:libxxx.so
独立执行:编译成功的可执行文件不可独立执行,库函数文件必须要存在,并且函数库所在目录也不能改变
升级难易度:易
注:使用gcc hello.c -o hello时,系统默认使用动态链接方式进行编译程序,若想使用静态编译,需加入-static参数
如果静态库、动态库都放在/lib下,当静态库函数与动态库函数重名时,系统也是优先考虑链接动态库,同样如果想要使用静态库,需加入-static选项
静态函数库与静态函数库的制作与使用:
实例程序:
"mylib.c"
#include "mylib.h"
int sub( int a, int b )
{
return a - b;
}
int add( int a, int b )
{
return a + b;
}
"mylib.h"
#ifndef __MYLIB_H__
#define __MYLIB_H__
extern int sub( int, int );
extern int add( int, int );
#endif
"hello.c"
#include <stdio.h>
#include "mylib.h"
int main( void )
{
printf( "100 - 20 = %d\n", sub( 100, 20 ) );
printf( "100 + 20 = %d\n", add( 100, 20 ) );
return 0;
}
静态函数库的制作步骤:
(1)#gcc -c mylib.c -o mylib.o //编译目标文件
(2)#ar rc libmylib.a mylib.o //制作静态库
静态函数库的使用:
库函数和头文件都在当前目录下:
#gcc -o hello hello.c libmylib.a
或者
#gcc -o hello hello.c -L /home/zhu/program/ -lmylib // /home/zhu/program/为当前目录
上面两种方式都可以成功。
库函数和头文件不在当前目录下:libmylib.a移动到/home/zhu/lib/ mylib.h移动到/home/zhu/include/
#gcc -o hello hello.c -I /home/zhu/include/ -L /home/zhu/lib/ -lmylib
上述编译过程都没有加入-static选项,所以默认都是采用动态链接(dynamically linked)。加上-static后才是静态链接(statically linked)的。用静态库既可以实现静态链接也可以实现动态链接。用file命令查看hello,确实可执行文件大小有差别。奇怪的是,对于这里的动态链接,即使把libmylib.a删除,hello照样可以运行。动态链接不是没有将库函数链接进入可执行文件里吗??
编译程序时,编译器默认会到/lib/、/usr/lib/下查找库函数,到/usr/include/下查找头文件。如果我们把libmylib.a放到/lib/或者/usr/lib/,把mylib.h放到/usr/include/目录下,那么编译时就不需要再加上选项 -I /home/zhu/include/ 和 -L /home/zhu/lib/
可以直接写成:#gcc -o hello hello.c -lmylib
动态函数库的制作:
#gcc -shared mylib.c -o libmylib.so
动态函数库的使用:
库函数、头文件都在当前目录下:
# gcc -o hello hello.c libmylib.so
#./hello
./hello: error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory
需要把当前目录加入搜索路径:
#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/zhu/program
或者把libmylib.so拷贝到/lib/、/usr/lib/中
#./hello 运行成功
把libmylib.so移动到/home/zhu/lib/ mylib.h移动到/home/zhu/include/
#gcc -static hello.c -o hello -I /home/zhu/include/ -L /home/zhu/lib/ -lmylib
/usr/bin/ld: cannot find -lmylib
动态库不能用静态编译
把libmylib.so和libmylib.a同时放到/home/zhu/lib中:
如果使用#gcc hello.c -o hello -I /home/zhu/include/ -L /home/zhu/lib/ -lmylib, 默认使用的是libmylib.so,并且编译成功后不可运行,要想运行必须将/home/zhu/lib/加入到LD_LIBRARAY_PATH中,或者将libmylib.so拷贝到/lib/或/usr/lib下。
如果使用#gcc -static hello.c -o hello -I /home/zhu/include/ -L /home/zhu/lib/ -lmylib,则使用的是libmylib.a,并且编译成功后即可运行。