error adding symbols: DSO missing from command line
更新日期:
文章目录
问题描述
由于Linux Kernel或编译器版本升级后,经常对原有工程项目编译期遇到如下问题:
1 | error adding symbols: DSO missing from command line |
发生的场景及原因
我们有一个shared libA中,定义了函数foo()
另一个静态库libB显示地链接了libA
一个可执行文件bin_c显示地链接了libB
那么问题来了,如果bin_c中调用了函数foo(),那么编译能不能通过?
- 在binutils<2.22时,ld正常完成了,bin_c对于foo的调用经由libB,传递到了libA,链接成功。
- 但是当binutils>=2.22时,编译出错了,ld会报上面的错,告诉你foo这个symbol解析不到,这时,我们需要编译bin_c时,显示地链接libA才可以通过。
- binutils2.22开始,其中的ld开始把–no-copy-dt-needed-entries默认打开,这样一来,ld不会再自动递归地解析链接的lib,而需要由用户来一一指定。
解决方案
- 一个ld的选项–allow-shlib-undefined,作用是允许在动态库中存在未解析到的函数symbol,至于理由可以自行查看man.
- 编译期修改Makefile LINK选项,手动加入全部依赖.(推荐方法)
案例剖析(Alibaba/Tair)
- 以Tair为例,其Github地址为:Alibaba/Tair
- 编译环境:CentOS 5.4 GCC 4.9.3 BOOST-1.57.0
编译期错误一
1 | /lib64/libcrypto.so.6: error adding symbols: DSO missing from command line |
产生原因
- 编译器使用的是GCC 4.9.3, 高于CentOS 5.4系统标配,其相关的ld等版本也高于2.24, 故在编译期时不会自动引入递归依赖,因此报错.
- 如果采用GCC 4.1.2, 则不会报错.
- Tair所需要的snappy版本其编译依赖高于系统自带,需要手动安装ld相关. 见参考文献.
解决方案
- 手动加入-lcrypto编译选项.
编译期错误二
1 | httpclient.hpp:122:36: error: static data member ‘System::Net::HttpWebRequest::<anonymous struct>::POST’ in unnamed class [-fpermissive] |
产生原因
1 | class A |
- GCC 4.9.3不再支持该定义语法(即在类内定义匿名类,进而定义静态常量成员).
解决方案
- 升级代码,使之兼容C++ 11标准.
编译期错误三
1 | tair_client_api_impl.cpp:4079:15: error: variable 'get_statistics_success' set but not used [-Werror=unused-but-set-variable] |
产生原因
- GCC编译选项配置导致.
解决方案
- 找到对应目录中的Makefile文件,找到 -Werror 字段,去掉-Werror,重新编译,则问题解决!
- 根据提示修改源代码,去掉无用变量,减少代码冗余和在编译优化过程中可能导致的致命错误!(推荐)
其它
- gflags增加-fPIC: SET(CMAKE_CXX_FLAGS “-fPIC”) [CMakeLists.txt]
- glog增加-fPIC: CXXFLAGS = -fPIC [Makefile]