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个解决办法,其一是直接将版本号去掉,用同样 的命令进行编译,毕竟去掉版本号就违背版本管理的初衷,很难从文件名方便的看出动态库或者静态库的版本,因此这种方法不是理想的方法;还有一种方法,这种 是比较提倡的,就是建立符号链接:

 

 

  1. cd lib  
  2. ln -s libdynamic.so libdynamic.so.1  
  3. ln -s libstatic.a.1 libstatic.a.1  


然后使用同样的命令就可以链接成功。

 

 

接下来运行生成的可执行程序,结果告诉你:

 

 

  1. <span style="color:#FF0000">./main: error while loading shared libraries: libdynamic.so: cannot open shared object file: No such file or directory</span>  


说找不到libdyn.so,发生这个错误的原因是,这个共享库不在系统查找共享库的任何路径中,系统使用下面路劲和顺序查找需要加载的共享库:

 

  1. 编译目标代码时指定的动态库搜索路径
  2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
  3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径;//只需在在该文件中追加一行库所在的完整路径如"/root/test/conf/lib"即可,然后ldconfig是修改生效
  4. 默认的动态库搜索路径/lib
  5. 默认的动态库搜索路径/usr/lib

这里我们配置环境变量LD_LIBRARY_PATH,方法:

 

 

  1. export LD_LIBRARY_PATH=/xxx/xxx/xxx/lib:$LD_LIBRARY_PATH  

 

这里的

 

  1. /xxx/xxx/xxx/lib  

是库的全路经。

 

 

然后再次运行程序,结果成功执行。

 

如果这里的libdynamic既有静态库又有动态库,这个时候gcc就不知道链接哪一个了,你需要使用

 

 

-WI,-Bstatic -lxxx

来链接静态库,

 

 

-WI,-Bdynamic -lxxx

来链接动态库

 

 

因此上面的命令变成了:

 

 

  1. g++  -Wall -o main  main.cpp -L../lib/ -WI, Bdynamic -ldynamic  -WI, -Bstatic -lstatic  

 

 

版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则按侵权处理.

    分享到:

Leave a Reply

Your email address will not be published. Required fields are marked *