在 cmake 配置后的链接阶段不尊重 BOOST_ROOT

Posted

技术标签:

【中文标题】在 cmake 配置后的链接阶段不尊重 BOOST_ROOT【英文标题】:BOOST_ROOT not respected at link stage after cmake config 【发布时间】:2019-01-15 18:44:10 【问题描述】:

为冗长的标题道歉。

由于/usr/lib64 目录中存在boost 库,我正在努力将boost 与cmake 链接起来。我的 boost 在不同的地方编译,我用BOOST_ROOT 指向cmake。意识到潜在的问题,我正在设置一个最小版本和Boost_NO_SYSTEM_PATH。配置阶段工​​作正常,但链接时出现错误:

test.cpp:(.text._ZN5boost15program_options25basic_command_line_parserIcEC2EiPKPKc[_ZN5boost15program_options25basic_command_line_parserIcEC5EiPKPKc]+0xa8): undefined reference to `boost::program_options::detail::cmdline::cmdline(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
 >, std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>, std::allocator<char> > > > const&)'

这显然是选择错误库的问题,我可以通过make VERBOSE=2 看到g++ 行不尊重我之前在BOOST_ROOT 中找到的提升设置

g++ CMakeFiles/test.dir/test.cpp.o -o test -rdynamic -lboost_program_options-mt

但我会期待以下内容:

g++ ... -L/path/to/my/own/boost/lib -lboost_program_options-mt

作为“调试”步骤,我在cmake 中打印出一条带有Boost_LIBRARY_DIRS 的消息,我可以看到/path/to/my/own/boost/lib。当我“手动”添加 -L 标志时,链接有效,这就是我知道系统库仍在干扰的方式。另外,我的*LIBRARY_PATH 只指向/path/to/my/own/boost/lib

也许,这不太可能是FindBoost 模块的错误,但我很难相信。在我看来,cmake 中还有一些我不明白的主要内容?为什么在此实例中未生成 -L 标志或指向特定文件的链接?请指教。

这是我的CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

set(Boost_NO_SYSTEM_PATHS ON)
find_package(Boost 1.67.0 REQUIRED COMPONENTS program_options)

include_directories($Boost_INCLUDE_DIR)

add_executable(test test.cpp)

target_link_libraries(test LINK_PUBLIC $Boost_PROGRAM_OPTIONS_LIBRARY)

还有我的程序:

#include <iostream>
#include <string>

#include <boost/program_options.hpp>

namespace po=boost::program_options;

int main( int argc, char* argv[]) 
 
    po::options_description options_description;
    po::positional_options_description positional_options_description;
    po::variables_map variables_map;


    options_description.add_options()
    ("help,h", "print usage message");
    po::store(po::command_line_parser(argc, argv).options(
        options_description).positional(positional_options_description).run(),
        variables_map);

    return 0; 
 

其他相关输出

我正在使用messagefind_package 之后从cmake 配置步骤中提取变量:

$Boost_INCLUDE_DIR /path/to/my/own/boost/include
$Boost_LIBRARY_DIRS /path/to/my/own/boost/lib
$Boost_LIBRARIES /path/to/my/own/boost/lib/libboost_program_options-mt.so
$Boost_PROGRAM_OPTIONS_LIBRARY /path/to/my/own/boost/lib/libboost_program_options-mt.so

【问题讨论】:

-L 总是在需要时添加。您没有指定他的问题应该是什么值或者$Boost_LIBRARIES 是否具有完整路径。顺便说一句,应该是$Boost_PROGRAM_OPTIONS_LIBRARY (IIRC)。另一个选项是将库设置为源,否则它将始终使用-l 谢谢@MatthieuBrucher 我增加了我的期望。由于服务器上的目录结构复杂,我的实际目录名称很长,但我希望一个简单的 /path/to 形式就可以了。程序选项我也试过了,效果一样。 $Boost_PROGRAM_OPTIONS_LIBRARY 中有什么?如果我问具体变量的内容,那是有原因的…… @RobertSawko:当遇到意外的链接库/包含目录/无论是检查您在代码中使用的变量时,调试的第一步。您的代码使用变量Boost_INCLUDE_DIRBoost_PROGRAM_OPTIONS_LIBRARY,因此请检查它们是否具有合理的值。只有在执行完这一步后,您才能更深入地检查已使用命令的语义(find_package)等等。 @Tsyvarev 是的,我不清楚这一点,但我已经检查过了。我现在在我的问题中添加了一个部分。在我看来一切都很好。我的主要惊喜是这些变量似乎是正确的,但 make 中没有 -L。 【参考方案1】:

我不知道您使用的是哪个 CMake 版本,但您是否尝试使用 Boost 导入目标而不是老式 CMake 变量:

即 代替: target_link_libraries(test LINK_PUBLIC $Boost_PROGRAM_OPTIONS_LIBRARY) 经过 target_link_libraries(test LINK_PUBLIC Boost::program_options)

【讨论】:

感谢您的建议。我有 cmake 3.12,所以我将从现在开始使用更新的语法。【参考方案2】:

在致电cmake-developer 邮件列表并最终在cmake gitlab issues 上发表帖子后,我意识到问题不在于我的 cmake 版本,而在于我从旧项目继承的cmake_minimum_required

我在设置:

cmake_minium_required(VERSION 2.8)

将其更新到 3.12 后,我得到了正确的行为:

/path/to/g++ -rdynamic CMakeFiles/test.dir/test.cpp.o -o test -lboost_program_options-mt

阅读cmake_minimum_required 文档我了解到“命令隐式调用”cmake_policy。我相信后者与我的 3.12 `cmake 中的FindBoost 配合得不好。

我不确定这篇文章是否对 SO 有用,但我确实在这里学到了我的 cmake 课程。

【讨论】:

以上是关于在 cmake 配置后的链接阶段不尊重 BOOST_ROOT的主要内容,如果未能解决你的问题,请参考以下文章

无法在 CMAKE 中链接 Boost

在 CMake 中链接 boost 文件系统的问题

如何使用 CMake 自动链接 boost 库

Boost.Python 和 CMake 链接和加载错误

Linux下使用CMake进行编译的时候寻找Boost库

Clion使用MinGW编译好的boost库