使用 CMake 构建 .so 库时提升未定义符号
Boost undefined symbol when building .so library with CMake
我正在 Linux 上使用使用 Boost 1.75.0 的 CMake 构建共享库 (.so)。
在CMakeLists.txt中,Boost的添加方式如下:
find_package(Boost REQUIRED COMPONENTS system chrono filesystem date_time log iostreams program_options)
并添加到目标:
target_link_libraries(mytarget PUBLIC ${Boost_LIBRARIES})
CMake 找到了 Boost,所以这里没有问题。
Boost 链接为静态库。当我列出链接的目标文件时,我得到了正确的库:
-- LIB_FILES: ...;/path/to/boost/debug/lib/libboost_filesystem.a;...
库编译和链接没有错误。
但是,当我使用库的一个简单函数时,出现以下错误:
undefined symbol: _ZNK5boost10filesystem16filesystem_error4whatEv
这个符号确实在库中未定义:
$ nm -g libmytarget.so | grep _ZNK5boost10filesystem16filesystem_error4whatEv
U _ZNK5boost10filesystem16filesystem_error4whatEv
demangled名称为boost::filesystem::filesystem_error::what() const
,在boost/filesystem/exception.hpp
中定义为
namespace boost
{
namespace filesystem
{
class BOOST_FILESYSTEM_DECL filesystem_error : public std::exception
{
public:
virtual const char * what() const throw();
...
请注意,我的代码不会调用此方法。
符号在libboost_filesystem.a
中定义,链接器使用,作为文本(代码)部分中的符号:
$ nm -g /path/to/boost/debug/lib/libboost_filesystem.a | grep _ZNK5boost10filesystem16filesystem_error4whatEv
00000000000003fa T _ZNK5boost10filesystem16filesystem_error4whatEv
我的问题:
我不明白为什么这个符号在编译库中是未定义的,当它出现在静态链接库(文件libboost_filesystem.a
)中时,它被链接器识别和使用.
在 CMake 中启用 INTERPROCEDURAL_OPTIMIZATION
解决了问题:
set_target_properties(mytarget PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
现在,符号已正确链接:
$ nm -g libmytarget.so | grep filesystem_error4what
00000000001cfe22 T _ZNK5boost10filesystem16filesystem_error4whatEv
但我仍然不知道幕后发生了什么,也不知道为什么首先会出现这个错误。
我正在 Linux 上使用使用 Boost 1.75.0 的 CMake 构建共享库 (.so)。
在CMakeLists.txt中,Boost的添加方式如下:
find_package(Boost REQUIRED COMPONENTS system chrono filesystem date_time log iostreams program_options)
并添加到目标:
target_link_libraries(mytarget PUBLIC ${Boost_LIBRARIES})
CMake 找到了 Boost,所以这里没有问题。
Boost 链接为静态库。当我列出链接的目标文件时,我得到了正确的库:
-- LIB_FILES: ...;/path/to/boost/debug/lib/libboost_filesystem.a;...
库编译和链接没有错误。
但是,当我使用库的一个简单函数时,出现以下错误:
undefined symbol: _ZNK5boost10filesystem16filesystem_error4whatEv
这个符号确实在库中未定义:
$ nm -g libmytarget.so | grep _ZNK5boost10filesystem16filesystem_error4whatEv
U _ZNK5boost10filesystem16filesystem_error4whatEv
demangled名称为boost::filesystem::filesystem_error::what() const
,在boost/filesystem/exception.hpp
中定义为
namespace boost
{
namespace filesystem
{
class BOOST_FILESYSTEM_DECL filesystem_error : public std::exception
{
public:
virtual const char * what() const throw();
...
请注意,我的代码不会调用此方法。
符号在libboost_filesystem.a
中定义,链接器使用,作为文本(代码)部分中的符号:
$ nm -g /path/to/boost/debug/lib/libboost_filesystem.a | grep _ZNK5boost10filesystem16filesystem_error4whatEv
00000000000003fa T _ZNK5boost10filesystem16filesystem_error4whatEv
我的问题:
我不明白为什么这个符号在编译库中是未定义的,当它出现在静态链接库(文件libboost_filesystem.a
)中时,它被链接器识别和使用.
在 CMake 中启用 INTERPROCEDURAL_OPTIMIZATION
解决了问题:
set_target_properties(mytarget PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
现在,符号已正确链接:
$ nm -g libmytarget.so | grep filesystem_error4what
00000000001cfe22 T _ZNK5boost10filesystem16filesystem_error4whatEv
但我仍然不知道幕后发生了什么,也不知道为什么首先会出现这个错误。