一、创建共享库 1 单独编译SList.cpp,编译时需要传入-fPIC选项,告诉编译器生成位置无关代码. 位置无关代码可以被加载到地址空间的任意位置而不需要修改.
[root@LEE src]# ls main.cpp SList.cpp SList.h [root@LEE src]# g++ -fPIC -g -c SList.cpp
2 当链接到库时,为链接器传入-shared选项,把目标文件SList.o链接为共享对象 libSList.so.1.0.1 每个共享库都有一个特定的搜索名(soname).搜索名约定如下: lib+库名+.so+.版本号 在文件系统中,搜索名是一个指向实名的符号连接.每个共享库也有一个特定的实名,约定如下: 搜索名+.子版本号+.发布号 你可以使用一个特殊的编译器选项-Wl,option,将option传给ld,用逗号分隔多个option, 为了在所有的系统上得到最好结果,链接libSList到标准C++库上
[root@LEE src]# g++ -g -shared -Wl,-soname,libSList.so.1 -o libSList.so.1.0.1 SList.o -lstdc++ [root@LEE src]# ls libSList.so.1.0.1 main.cpp SList.cpp SList.h SList.o
libSList.so.1是搜索名,libSList.so.1.0.1是实名,SList.o是目标文件(也可以是多个目标文件的列表) ,-lstdc++是库需要访问的库(也可以是库的列表-llibrary,关于此选项参考附录.)
3 创建一个从soname链接到库 [root@LEE src]# ln -fs libSList.so.1.0.1 libSList.so.1 [root@LEE src]# ln -fs libSList.so.1 libSList.so 4 使用-L使链接器在当前目录中查找库,并且使用-lSList告诉它要链接哪个库 [root@LEE src]# g++ -g -c main.cpp -o main.o [root@LEE src]# g++ -g -o main main.o -L. -lSList [root@LEE src]# ls libSList.so libSList.so.1.0.1 main.cpp SList.cpp SList.o libSList.so.1 main main.o SList.h
5 运行命令 [root@LEE src]# LD_LIBRARY_PATH=$(pwd) ./main 4->17->19->10->23->21->11->20
LD_LIBRARY_PATH 提供用来搜索库的目录路径,以冒号作为间隔.正常情况下它不应该被设置,因为系统文件 /ect/ld.so.conf提供了默认的路径.
二、使用链接库 当运行一个程序时,动态装载器通常在/ect/ld.so.conf.d目录查找程序所需要的库.但是,如果 LD_LIBRARY_PATH 环境变量被设置,它首先扫描在LD_LIBRARY_PATH 中列出的目录.对于上一节5,如果直接运行 命令 ./main,会出现找不到库的现象.如: [root@LEE src]# ./main ./main: error while loading shared libraries: libSList.so.1: cannot open shared object file: No such file or directory
上述问题的解决方案有两种(我能想到的): 1 如果LD_LIBRARY_PATH 没设定: 拷贝libSList.so到目录 /usr/local/lib (同理也可以拷到/usr/lib下) [root@LEE src]# cp libSList.so /usr/local/lib [root@LEE src]# ldconfig /usr/local/lib [root@LEE src]# ./main 4->17->19->10->23->21->11->20
2 如果LD_LIBRARY_PATH 设定: 编辑.bash_profile文件 添加LD_LIBRARY_PATH:=$LD_LIBRARY_PATH:/path/to/libSList.so(不包括 libSList.so) 执行.bash_profile 文件. [root@LEE src]# . /root/.bash_profile [root@LEE src]# ./main 4->17->19->10->23->21->11->20