• 程序编译与部署中依赖问题总结


    服务器部署问题:

    本质上,目标程序开发完成后,要在机器上部署,要求开发机器必须于服务器环境一致,这样风险相对较小,部署相对容易。可是现实中常常因为各种原因,很难保证开发机器与部署机器的一致性。下面是一些问题总结。

     

    动态库依赖动态库

    最常问题:

    库版本兼容问题(如:`GLIBCXX_3.4.20' not found 问题)

    问题原理如下: 

    该问题源于程序本身直接依赖的库没有问题,但是在迁移到其他机器时,间接依赖的库版本不兼容(某些接口已经删除了)。实际上就是找不到某些接口的问题,外在的表现就是某些符号找不到。此类问题一般不会在编译的时候表现出来,编译通过后,启动程序时才会提示。

    解决的方法就是升级到对应版本的库。比如上面libstdc++.so.6,我们可以看看其链接的具体版本:

    我没有急着去安装,因为之前可能有人已经安装过了,只是没有创建对应的软链接,可以先查找看看:

     

    找到了其他版本的库,但是我们并不确定其是否符合我们的要求,也就是内部是是否包含我们所有要求的”符号“,可以使用如下命令验证:

    以上输出证明该版本库确实符合我们的要求,删掉旧的链接重新建立新版本的库的链接就好了:

     

    动态库”依赖“静态库

    1)常规用法与变异

    静态库的的初衷是编译进可执行文件,并且不再依赖。一般用于直接”依赖“,目标文件--->libxx.a:

    以上是常规形式,但是也不排除下面这种模式: 目标文件—>动态库---->静态库。libxx3.so在编译时把libyy.a编译进去了。

     

    这种形式一般用于:

      (1)不想将libyy.a暴露给甲方,(提供动态库,甲方能直接看到)

      (2)为了编译的程序的依赖树更加简洁

      (3)锁死间接依赖,避免出现上面提到的"GLIBCXX_3.4.20' not found 问题"。(这一条很重要)

      (4)欢迎补充。。。

     

     2)动态库包含“依赖”静态库的问题:

    静态库参编译进可执行文件后,其存在价值就不存在了,因为,静态库的源码已经连接到了可执行文件,本质上来讲静态库编译进可执行文件,和二进制文件(*.o)链接成一个可执行文件没有本质的区别。libyy.a的本质就是一个包含了众多二进制文件的包。同理,如果静态库被编译到动态库中也是一样的。动态库编译成功后,静态库删掉也不影响动态库的使用。所谓静态依赖就是编译时依赖,运行时已经不再需要。但是这里有一个问题:将一个静态库编译进可执行文件和动态库,对这个静态库的要求是不一样的。从编译步骤说起:

    静态库/动态库 步骤 中间文件
    libxyz.a

    gcc -c  xx.c yy.c zz.c

    ar r  libxyz.a xx.o yy.o zz.o

    xx.o yy.o zz.o
    libxyz,so

    gcc -c -fPIC xx.c yy.c zz.c

    ar r  libxyz.a xx.o yy.o zz.o

    xx.o yy.o zz.o

    动态库在生成时需要使用-fPIC选项告诉编译器生成与位置无关的代码,讲的明白点就是一个进程在运行时可以加载动态库到一个区域中的任何虚拟地址(下图中红色箭头指向),而不是绝对的位置。而静态库是依赖绝对位置的,哪里调用,它就被安排在那里 ,被静态的嵌入进去(下图绿色箭头部分),其代码块地址是绝对的。

    如果我们直接在使用上面这种方法生成的静态库编译动态库(将静态库编入动态库),会怎么样呢?错误提示大概如下!

    /usr/bin/ld: /usr/lib64/libxyz.a(gen_uuid.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
    /usr/lib64/libxyz.a: could not read symbols: Bad value
    collect2: error: ld returned 1 exit status
    make[1]: *** [libapr-1.la] 错误 1
    make[1]:正在离开目录 `/home/fernando/OneMS/OneMS-TR-Install/depends/apr-1.4.5'
    make: *** [all-recursive] 错误 1

    其提示我们需要重新使用-fPIC选项来编译静态库,才能使用改静态库构建其他的动态库。

    所以我们需要的是这样:

    gcc -c  -fPIC xx.c yy.c zz.c

    ar r  libxyz.a xx.o yy.o zz.o

    这样生成的静态库可以带有-fPIC的标记,与动态库生成的第一步统一了,兼容了动态库的生成要求。

    此时再使用:

    gcc -shared -o libxx.so xx.c libbxyz.a

    libxx.so就可以正常生成了

    二进制兼容问题:

    (续)

    关于“undefined reference to”问题,这种问题最为常见,也容易处理,总结几种无非就是,找不到库,C版本接口命名倾轧,旧库依赖问题,库依赖顺序等问题。下面的的文章总结的不错。可以看看。

    https://blog.csdn.net/KgdYsg/article/details/90705766

     

    参考资料:

    《Linux/Unix系统编程》

    《Linux编程手册》

    参考博客

    https://blog.csdn.net/KgdYsg/article/details/90705766

     

  • 相关阅读:
    linux性能指令分析进阶篇
    数据库提升篇
    linux之基础命令大全
    数据库事务测试以及级联更新级联删除
    【Comet OJ】—模拟赛测试 Day1题解
    【Comet OJ】—模拟赛测试 Day1题解
    【LOJ # 6268】—分拆数(生成函数+多项式Ln/Exp+NTT)
    【LOJ # 6268】—分拆数(生成函数+多项式Ln/Exp+NTT)
    【LOJ #6041】【雅礼集训 2017 Day7】—事情的相似度(后缀自动机+LCT+树状数组)
    【LOJ #6041】【雅礼集训 2017 Day7】—事情的相似度(后缀自动机+LCT+树状数组)
  • 原文地址:https://www.cnblogs.com/wangkeqin/p/12794504.html
Copyright © 2020-2023  润新知