库:本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行,分为静态库和动态库两类。另外,需要知道的是,由于windows和Linux是两款操作系统,因此,二者的库是不兼容的。
静态函数库:
后缀通常为***.a,利用静态库编译的程序有着一定的优点,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去,但这会造成另外一个问题,如果静态库发生改变,程序就需要重新编译,同时,静态库编译程序生成的文件较大,因为整个函数库的所有数据都会被整合进目标代码中。
利用静态库编译,通常情况下是因为我们希望我们的程序需要有更好的移植性。
动态函数库:
后缀通常为***.so,动态函数库在编译的时候并没有被编译进目标代码,只有当程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。关于平台的问题上,如果利用动态库编译的程序希望得到运行,那么该运行环境中必须要有相应的库来支持,动态函数库并不影响程序,所以动态函数库升级更加方便。
二者的最大不同之处在于库代码被在于内存的时刻不同,静态库通常在编译时刻就被载入可执行程序,动态库是在程序运行时载入内存的,编译过程中只是简单的引用。
gcc生成静态链接库实例:
在当前目录下,有如下几个文件,Makefile暂不关心。
前三个文件内容如下:
要生成静态库文件,首先我们需要将源代码转换为二进制目标文件(hello.c -- > hello.o)
[muhui@bogon mylib]$ gcc -c hello.c -o hello.o
接下来我们需要将hello.o依照静态库命名规范【注1】转化为静态库文件 libmyhello.a
[muhui@bogon mylib]$ ar cr libmyhello.a hello.o
得到静态库文件之后,就可以使用gcc命令生成最终目标文件时指明静态库名,gcc将会从静态库中将共用函数链接到目标文件。【注2】
[muhui@bogon mylib]$ gcc -o hello main.c -L. -lmyhello
# -L.指定了静态库文件目录在当前目录下
完成了gcc编译的任务之后,我们需要做一件事,来验证是否我们成功使用了静态库。我们尝试将静态库文件删除,看生成的可执行程序是否还能正确运行。
[muhui@bogon mylib]$ rm -f libmyhello.a
[muhui@bogon mylib]$ ./hello
hello world
程序运行正常,表明静态库文件已经被添加进入目标文件。
最后这里我们留意一下生成的目标文件大小:
[muhui@bogon mylib]$ ll
总用量 652
-rwxrwxr-x. 1 muhui muhui 645220 2月 18 08:44 hello
-rw-rw-r--. 1 muhui muhui 81 2月 17 18:17 hello.c
-rw-rw-r--. 1 muhui muhui 108 2月 17 18:15 hello.h
-rw-rw-r--. 1 muhui muhui 856 2月 18 08:36 hello.o
-rw-rw-r--. 1 muhui muhui 63 2月 17 18:19 main.c
gcc生成动态链接库实例:
同样还是和上面一样,使用同一个例子。
动态库文件依旧需要由.o文件来创建,首先我们清理当前工作目录。
[muhui@bogon mylib]$ ls
hello hello.c hello.h hello.o main.c Makefile
[muhui@bogon mylib]$ rm -f hello
[muhui@bogon mylib]$ ls
hello.c hello.h hello.o main.c Makefile
这里保留的hello.o文件,同时也遵守动态库文件命名规范【注3】,创建动态库文件libmuhello.so
[muhui@bogon mylib]$ gcc -shared -fPCI -o libmyhello.so hello.o
[muhui@bogon mylib]$ ls
hello.c hello.h hello.o libmyhello.so main.c Makefile
接下来在程序中使用动态库文件,使用动态库和使用静态库文件方式完全一样,如下
[muhui@bogon mylib]$ gcc -o hello main.c -L. -lmyhello
[muhui@bogon mylib]$ ls
hello hello.c hello.h hello.o libmyhello.so main.c Makefile
[muhui@bogon mylib]$ ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory
报错!原因说的很清楚,没有找到动态库文件。程序运行时,通常还在/usr/lib 和/lib 目录下查找所需要的动态库文件,所以这里我们需要将我们生成的动态库文件移动到/usr/lib 目录下(需要root权限)
[muhui@bogon mylib]$ sudo mv libmyhello.so /usr/lib/
[sudo] password for muhui:
[muhui@bogon mylib]$ ls
hello hello.c hello.h hello.o main.c Makefile
[muhui@bogon mylib]$ ./hello
hello world
完成之后,我们再次查看目标文件大小
[muhui@bogon mylib]$ ll
总用量 28
-rwxrwxr-x. 1 muhui muhui 4888 2月 18 09:06 hello
-rw-rw-r--. 1 muhui muhui 81 2月 17 18:17 hello.c
-rw-rw-r--. 1 muhui muhui 108 2月 17 18:15 hello.h
-rw-rw-r--. 1 muhui muhui 856 2月 18 08:36 hello.o
-rw-rw-r--. 1 muhui muhui 63 2月 17 18:19 main.c
两次对比,就会发现,使用动态库文件的话,生成的目标文件就会小的多。
这里需要强调的一点是,如果我们同时生成静态库和动态库文件的话,操作系统一般会优先选择动态库。
【注1】静态库命名规范:以lib为前缀,紧接着跟静态库名,扩展名为.a。
【注2】gcc会在静态库名前加上lib前缀,然后追加扩展名.a,得到的静态库文件名来查找静态库文件,注意下面静态库名的变化,前缀lib变为l,同时省略后缀。
【注3】动态库命名规范:以lib为前缀,紧接着跟动态库名,扩展名为.so
补充一点的是,如果在编译过程中发现会有报错产生,很可能是因为缺少一个叫做glib-static的库,可以直接使用
yum -y install glibc-static
安装该文件,推荐直接使用网络yum源下载,个人尝试,搭建的本地yum源,安装失败,具体原因应该是该库在镜像B的问题,这里不深究。
------muhuizz整理