linux编译同时链接静态和动态库

请参看:

linux链接动态库和静态库

其实,这以下文字主要是记录在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,发生这个错误的原因是,这个共享库不在系统查找共享库的任何路径中,系统使用下面路劲和顺序查找需要加载的共享库:

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

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

    分享到:

留言

你的邮箱是保密的 必填的信息用*表示