请参看:
其实,这以下文字主要是记录在linux下面编译程序的时候碰到的问题,当然如果有大侠路过,对这个问题有所了解,还忘指点一二。
一个测试程序想同时链接静态库和动态库:
dynamic.cpp 动态库代码如下;
#include <iostream>
using namespace std;
int math_sub( int a, int b )
{
return a – b;
}
编译动态库:
g++ -Wall -shared -o ../lib/libdynamic.so.1 dynamic.cpp
成功得到libdynamic.so.1
staticlib.cpp 静态库代码如下:
#include <iostream>
using namespace std;
int math_add( int a, int b )
{
return a + b;
}
编译静态库;
g++ -c -o ../lib/libstatic.o staticlib.cpp
ar -cvp libstatic.a.1 libstatic.o
成功得到libstatic.a.1
main.cpp 调用程序代码如下:
#include <iostream>
using namespace std;
int math_add(int,int);
int math_sub(int,int);
int main( int argv, char** argc )
{
cout<<“now call function in static lib”<<endl;
cout<<“add result:”<<math_add(2,3)<<endl;
cout<<“sub result:”<<math_sub(3,2)<<endl;
}
接下来我们编译main.cpp
g++ -Wall -o main ../lib/libstatic.a.1 ../lib/libdynamic.so.1 main.cpp
结果出错了:
undefined reference to ‘math_add(int, int)’
math_add是staticlib.cpp中函数,怎么找不到呢?好,先用:
nm ../lib/libstatic.a.1
查看一下,发现有导出这个函数啊。
我换一个顺序吧:
g++ -Wall -o main main.cpp ../lib/libstatic.a.1 ../lib/libdynamic.so.1
结果成功了。
我百思不得其解,如果有高人路过,请指点。
接下来,我们使用另外一种方式编译:
g++ -Wall -o main main.cpp -L../lib/ -ldynamic -lstatic
结果:
cannot find -ldynamic
这个也是无法解释.
============================================================================================================================
———————————————————————————————————-问题解答—————————————————————————————————
============================================================================================================================
时隔一年多,这个问题有了答案。因为工作需要,需要在linux开发,因此有时间在重新捡起这个问题。
其实上面总共有两个问题,下面做一一分析和解答
问题一:
“接下来我们编译main.cpp
g++ -Wall -o main ../lib/libstatic.a.1 ../lib/libdynamic.so.1 main.cpp
结果出错了:
undefined reference to ‘math_add(int, int)’
math_add是staticlib.cpp中函数,怎么找不到呢?好,先用:
nm ../lib/libstatic.a.1
查看一下,发现有导出这个函数啊。
我换一个顺序吧:
g++ -Wall -o main main.cpp ../lib/libstatic.a.1 ../lib/libdynamic.so.1
结果成功了。”
—————————————————————
原因:这个问题发生的原因是链接库的链接顺序,gcc在链接的时候,是从第一个开始解析,第一个文件引用的符号会在后面的文件中查找,依次类推,直到所有的符号被解析,这样算整个解析完成。由于main.cpp中引用了
libstatic.a.1
libdynamic.so.1
这个2个库中函数,因此main.cpp要放在第一个,而这2个库要放在后面,如果这个2个库又有相互依赖关系,比如libstatic.a.1引用了libdynamic.so.1中的函数,那么libstatic.a.1要放在libdynamic.so.1的前面,如果是相反,则要把它们的顺序调换。
问题二:
接下来,我们使用另外一种方式编译:
g++ -Wall -o main main.cpp -L../lib/ -ldynamic -lstatic
结果:
cannot find -ldynamic
这个也是无法解释.
—————————————————————–
原因:如果告诉g++链接 -ldynamic,那么g++所寻找期望的是
libdynamic.so或者是libdynamic.a,也就是没有版本号的库,那怎么办呢?有2个解决办法,其一是直接将版本号去掉,用同样的命令进行编译,毕竟去掉版本号就违背版本管理的初衷,很难从文件名方便的看出动态库或者静态库的版本,因此这种方法不是理想的方法;还有一种方法,这种是比较提倡的,就是建立符号链接:
cd lib ln -s libdynamic.so libdynamic.so.1 ln -s libstatic.a.1 libstatic.a.1
然后使用同样的命令就可以链接成功。
接下来运行生成的可执行程序,结果告诉你:
./main: error while loading shared libraries: libdynamic.so: cannot open shared object file: No such file or directory
说找不到libdyn.so,发生这个错误的原因是,这个共享库不在系统查找共享库的任何路径中,系统使用下面路劲和顺序查找需要加载的共享库:
- 编译目标代码时指定的动态库搜索路径
- 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
- 配置文件/etc/ld.so.conf中指定的动态库搜索路径;//只需在在该文件中追加一行库所在的完整路径如”/root/test/conf/lib”即可,然后ldconfig是修改生效
- 默认的动态库搜索路径/lib
- 默认的动态库搜索路径/usr/lib
这里我们配置环境变量LD_LIBRARY_PATH,方法:
export LD_LIBRARY_PATH=/xxx/xxx/xxx/lib:$LD_LIBRARY_PATH
这里的
/xxx/xxx/xxx/lib
是库的全路经。
然后再次运行程序,结果成功执行。
如果这里的libdynamic既有静态库又有动态库,这个时候gcc就不知道链接哪一个了,你需要使用
-WI,-Bstatic -lxxx
来链接静态库,
-WI,Bdynamic -lxxx
来链接动态库
因此上面的命令变成了:
g++ -Wall -o main main.cpp -L../lib/ -WI, Bdynamic -ldynamic -WI, -Bstatic-lstatic
完
版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则按侵权处理.