Liu Shouda coder

不同编译器版本库混用问题

2017-03-02

本文记录编译superviseddescent库碰到的问题。问题本质在于使用不同编译器版本编译的库,有时候不能混用。

查错记录

刚开始编译在ubuntu16.04下编译不通过,在ubuntu14.04编译通过。

在ubuntu16.04 + opencv3.1 + boost1.58下,报boost program_options链接错误。
在ubuntu14.04 + opencv2.4.8 + boost1.54下, 一次通过

一度怀疑是boost库链接问题,以为是不同版本boost不一样导致的。下载boost源码,发现没有CMake编译,暂时作罢。。后来使用下面脚本,发现应该不是boost库找不到造成的。

function(VerifyVarDefined)
  foreach(lib ${ARGV}) 
    if(DEFINED ${lib})
    else(DEFINED ${lib})
      message(SEND_ERROR "Variable ${lib} is not defined")
    endif(DEFINED ${lib})
  endforeach()
endfunction(VerifyVarDefined)

VerifyVarDefined(Boost_PROGRAM_OPTIONS_LIBRARY)

依稀记得以前编译OpenFace, 碰到过boost问题,好像是将gcc切换到5就搞定了的。至此把怀疑目光转向g++版本和opencv版本问题。

设置opencv搜索路径:

set(OpenCV_DIR "/home/sooda/tools/OpenCV/opencv-2.4.10/build")

做了以下测试:

在ubuntu16.04 + opencv2.4.10(用g++4.9编译) + boost1.58下,gcc4.9编译报boost program_options链接错误。
在ubuntu16.04 + opencv2.4.10(用g++4.9编译) + boost1.58下,切换编译器到g++5, 报opencv各种cv::error, cv::exception, cv::string等错误

查找文章怀疑是c++ ABI在不同版本之间不同导致的。也就是说,使用不同版本编译器编译出来的库未必能够通用。

将编译器切换到g++5,重新编译opencv,superviseddescent库顺利编译成功。

猜测ubuntu16.04上的boost1.58应该是用g++5编译的,这也解释了以前不少代码编译不通过,切换编译器之后就编译通过的情况。编译不通过可能不是代码版本不兼容,而是库版本不兼容!

更好的解决方案

既然已经知道是由于boost版本库导致的不兼容,是否可以使用g++4.9编译一个版本,然后opencv等其他库都不变呢。这样有利于保证整个系统使用相同的编译器版本。

下载boost最新代码,编译之:

sh bootstrap.sh --prefix=/home/sooda/tools/boost/
./b2 install

编译完了之后, 记得设置库的搜索路径:

export LD_LIBRARY_PATH=/home/sooda/tools/boost/lib:$LD_LIBRARY_PATH

需要设置boost的cmake搜索路径。boost是通过FindBoost.cmake来驱动的。查看/usr/share/cmake-3.5/Modules/FindBoost.cmake之后, 在CMakeLists.txt中加入以下内容就可以使用自己编译的boost版本。

set(Boost_NO_SYSTEM_PATHS TRUE) 
if (Boost_NO_SYSTEM_PATHS)
  set(BOOST_ROOT "/home/sooda/tools/boost/")
  set(BOOST_INCLUDE_DIRS "${BOOST_ROOT}/include")
  set(BOOST_LIBRARY_DIRS "${BOOST_ROOT}/lib")
endif (Boost_NO_SYSTEM_PATHS)

这样我们就实现了不切换编译器版本,顺利编译项目的。从这里也可以看出使用,有些项目为了避免系统依赖库混乱,将库编译到项目路径下是有必要的。


上一篇 tts tutorial

下一篇 mxnet loss

Content