之前写 c-cpp 代码会用到第三方的库如 libmysql 来连接 MySQL 数据库,jsoncpp 相关的库来使用 json 数据,但没怎么注意到这些 dynamic lib 或者 static lib 的创建,网上翻了一下相关的教程,在这里记录一下。
静态库和动态库有什么区别?
- 在这里通俗的回答一下,使用了静态库中相关的函数的程序代码在编译时会把静态库的相关的代码一起嵌入到整体的代码中,体积会大一些,但由于所有引用的函数功能代码都包含在程序中,所以这个程序可以直接在同种系统中直接运行。
- 使用了动态库的程序,在编译程序代码时并不会像使用静态库那样嵌入代码,而是记录了相关函数的位置,在程序运行时再去从相关的动态库中载入函数实现相关的功能,由于程序与库代码分开,所以程序在编译后的体积不会很大,但如果在同种系统中没有相关的动态库或者动态库文件的位置与编译时指定的位置不一致就无法运行程序了。
创建静态库文件的主要步骤是 将编译源文件得到的.o 文件使用 ar 来打包成.a 静态库文件
直接看我操作的整个过程记录
root@dockers src]# cc -Wall -c ctest.c
[root@dockers src]# ls
conf.sh ctest.c ctest.o include.h main.c makefile prog.c
[root@dockers src]# ar -vcq libcteststatic.a ctest.o
a - ctest.o
[root@dockers src]# ls
conf.sh ctest.c ctest.o include.h libcteststatic.a main.c makefile prog.c
[root@dockers src]# cc -o prog prog.c libcteststatic.a
[root@dockers src]# ./prog
1 Valx=5
2 Valx=100
[root@dockers src]# cp libcteststatic.a /opt/lib/
[root@dockers src]# cc -o progstatic prog.c -L /opt/lib/ -lcteststatic
[root@dockers src]# ./progstatic
1 Valx=5
2 Valx=100
[root@dockers src]# ll prog progstatic
-rwxr-xr-x. 1 root root 8598 Jul 10 00:31 prog
-rwxr-xr-x. 1 root root 8598 Jul 10 00:32 progstatic
[root@dockers src]# cc -o prognormal prog.c ctest.c
[root@dockers src]# ll prognormal
-rwxr-xr-x. 1 root root 8598 Jul 10 00:32 prognormal
动态库文件的创建主要是
使用编译器时如 gcc,clang,g++ 等指定 -fPIC 参数来编译得到.o 文件后再使用 -shared 参数来生成动态库文件,
操作过程可参考 ctest_dynamic 中的 makefile 文件的内容。
值得注意是
- 如果在生成.so 动态文件时,使用
-Wl,-soname,libxxx.so.1
来指定被 ldconfig 认定的动态文件名字为 libxxx.so.1 而 -o 生成的却是 libxxx.so.0 文件时,则要以 libxxx.so.0 为 source 生一个 symbol 文件 libxxx.so.1, 因为在编译时 ldconfig 认定的是名为 libxxx.so.1 的文件,否则会出现类似的这种提示./prog: error while loading shared libraries: libctest.so.1: cannot open shared object file: No such file or directory
, 可通过 [ldd 可执行程序』来检查所依赖的动态库文件是否存在;同时也要以 libxxx.so.0 生成一个 symbole 文件 libxxx.so 文件,因为 -lxxx 需要的是 libxxx.so 文件,否则会直接出现提示未找到相关的文件。相关的操作直接看 ctest-dynamic 中的 makfile 即可。 - 记得配置一下动态库的默认路径,教程里面提到了三种方法来使程序能正常运行
一种是改 ldconfig 的配置并更新缓存,(如图)另一种是指定 LD_LIBRARY_PATH 环境变量的值,当然不同类型的系统对个环境变量的名称不一样,不过我试了一下第一种有效,但是第二种没试成功。配合这里的演示我写了一个 conf.sh 脚本来增加默认的 lib 路径,所以在编译完程序之后记得运行一下这个脚本。
demo 文件下载
referrence:
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html