linux下动态库链接静态库问题记录

        背景: 最近一直在忙项目,现在项目的开发工作基本上已经接近尾声。该项目的框架是采用CTK的插件框架,每个功能都是以插件的形式提供,功能之间的交互是采用CTK的插件服务进行交互。项目的开发平台是windows平台,但是实际运行的平台是linux平台。在windows平台上开发完成后,移植到linux平台上。在移植的过程中,出现了好多链接问题,最主要的是动态库链接静态库的问题。下面我们就来看下这个问题。

        CTK的插件本身就是一个动态库,在windows平台上,CTK的插件如果引用了静态库,msvc系列编译器会将静态库链接到动态库中去,但是在linux系统下,gcc系列编译器并不会将静态库链接至动态库中,gcc仅仅是编译了插件动态库,并没有去链接。整个系统在编译的时候,就提示了好多链接错误的提示。怎么办呢? 当时我也比较懵了,总不能把所有的静态库都已源码的方式提供吧?这是当时的一个想法,如果这样的话,修改的地方还很多,windows/linux平台的代码就有所区别,不能统一一套代码,有没有什么方法可以解决呢。后来我就想了,gcc不能自动链接静态库,那我手动去链接下,能不能行呢?好了,说干就干吧。

        linux系统下,静态库的后缀名是.a(a是archive的缩写,也就是文档文件),是一个文档,然后解压缩,将其解压缩至当前目录,进入目录中,里面都是以.o后缀名的文件,右键弹出终端命令行,在命令行中输入:

 

ar crs xxxx.a *.o ,在该目录下,会生成xxxx.a的静态文件。

linux下动态库链接静态库问题记录_第1张图片

这时插件动态库就可以引用到我们手动进行链接的静态库了。

ar crs xxxx.a *.o 命令解释:

-c:建立备存文件

-r:将文件插入备存文件中

-s:若库文件中包含了对象模式,可利用此参数建立备存文件的符号表,等价于运行ranlib

xxxx.a 需要输出的静态库文件名,以.a 后缀名结尾

*.o:当前目录下所有的.o文件。

ar的命令还有很多,可以自行查找学习,我这里仅用到了这三个参数即可。

突然间看到希望了,然后将手动链接的静态库放到项目的路径下,编译主程序,天哪,一堆的问题。问题如下图所示:

linux下动态库链接静态库问题记录_第2张图片

慢慢的一屏幕错误。尴尬,难道这种方法不好使。

        我们仔细看下错误,提示都是recompile with -fPIC,那要是在编译的时候加入-fPIC参数后,是不是就好了呢?再次尝试,打开静态库源码:

        1.如果第三方的库(大部分的库都是采用CMake构建系统构建的),可以查看CMakefileLists.txt文件,搜索是否有-fPIC参数,没有的话,可以在CMakefileLists.txt文件中键入(首先要找到linux平台宏定义),这里linux定义是在else()分支里,在下面空白处添加如下代码

        linux下动态库链接静态库问题记录_第3张图片

         然后再进行编译。

        2.如果是自己编写的动态库,我这里是用QCreator编写的静态库,在.pro文件中加入如下代码:

         linux下动态库链接静态库问题记录_第4张图片

        然后重新编译。

        静态库已经编译通过后,采用上述提供的ar指令,手动打包静态库。打包完成后,在放到主程序下,重新编译主程序,这时候,会发现没错误了,而且主程序也可以运行了。完美解决。

       总结:linux系统下,最好是用动态库,而不是静态库。静态库大,而且构建相比较与动态库,稍显麻烦了点,知道问题的解决办法还好点,如果要是不知道的话,就懵了。我这里呢,因为代码都已经在windows系统上跑起来了,仅仅是移植到linux系统上,为了让两个平台的代码统一,也就没有将静态库修改为动态库,而且时间也不允许,所以才有了今天的这个文章。嘎嘎,也算是一点积累吧。 好了,今天抽空记录下,怕时间长,忘记了~

 

 

你可能感兴趣的:(linux,动态库链接静态库问题记录,linux,c++,qt)