如何使用CMake将C++程序与Boost库链接

141

在Ubuntu下,将我的程序与Boost库链接的CMake文件应该是怎样的?

运行make时显示的错误信息:

main.cpp:(.text+0x3b): undefined reference to `boost::program_options::options_description::m_default_line_length'

主要文件非常简单:

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/option.hpp>
using namespace std;
#include <iostream>

namespace po = boost::program_options;

int main(int argc, char** argv) {

    po::options_description desc("Allowed options");
    desc.add_options()
        ("help", "produce help message")
        ;

    return 0;
}
我已经做到了。我在我的CMake文件中添加的唯一行是:
target_link_libraries(
my_target_file
${Boost_PROGRAM_OPTIONS_LIBRARY}
)
7个回答

170

在CMake中,您可以使用find_package来查找所需的库。通常,您的CMake安装程序中会有一个FindBoost.cmake文件。

据我所知,它将与其他常见库的查找脚本一起安装在/usr/share/cmake/Modules/中。您只需查看该文件中的文档以了解其工作原理的更多信息。

以下是我想到的一个示例:

FIND_PACKAGE( Boost 1.40 COMPONENTS program_options REQUIRED )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )

ADD_EXECUTABLE( anyExecutable myMain.cpp )

TARGET_LINK_LIBRARIES( anyExecutable LINK_PUBLIC ${Boost_LIBRARIES} )

希望这段代码有所帮助。


2
已从Kitware的Github存储库中添加了一个可用的链接。还添加了一个关于FindBoost.cmake的官方文档链接。 - MOnsDaR
1
为什么特别选择Boost 1.40版本?这个库的基本功能是在什么时候停止变化的? - jgyou
8
为什么不呢?这只是一个例子……填入任何适合您的内容即可。 - MOnsDaR
7
重要的细节是将target_link_libraries放在add_executablefind_package行之后,以便所有链接的组件都得到识别。 - Murphy
9
这个回答对于新代码不太合适。应该优先考虑oLen的回答。 - Alex Reinking

61

将 @MOnsDaR 的答案改写为现代 CMake 语法,并使用导入目标,代码如下:

find_package(Boost 1.40 COMPONENTS program_options REQUIRED)

add_executable(anyExecutable myMain.cpp)

target_link_libraries(anyExecutable Boost::program_options)

注意不需要手动指定包含目录,因为已经通过导入的目标Boost::program_options处理了。


1
这种目标方法的缺点是,如果您的 Boost 版本比 CMake 版本更新,那么可能会失败。FindBoost.cmake 最初只在显式列出您的 Boost 版本时才构建它们。在某个时候,这应该得到改进,但我仍然看到 CMake 3.10.2 和 Boost 1.66(从 brew 获取的最新副本)的失败情况。 - Henry Schreiner
16
Stack Overflow开始出现故障,因为有太多过时的答案,往往很难找到正确的答案(就像这个问题)。 - Carlo Wood
@HenrySchreiner 的评论非常有帮助!它帮助我理解了为什么我的 cmake/conan/boost/g++ 版本混合使用时无法正确链接。有没有一种方法可以确定 Boost 和 CMake 的兼容版本? - WaterFox
他们实际上真的改进了这个 - 如果您不匹配,CMake现在将假定最新的Boost目标扩展到当前目标。此外,如果Boost提供了CMake模块(如果它们使用了CMake),则CMake将使用该模块。我认为最好的来源是检查CMake FindBoost源代码 - 从https://gitlab.kitware.com/cmake/cmake/-/blob/master/Modules/FindBoost.cmake#L1014开始。 - Henry Schreiner

56
以下是我的配置:
cmake_minimum_required(VERSION 2.8)
set(Boost_INCLUDE_DIR /usr/local/src/boost_1_46_1)
set(Boost_LIBRARY_DIR /usr/local/src/boost_1_46_1/stage/lib)
find_package(Boost COMPONENTS system filesystem REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIR})

add_executable(main main.cpp)
target_link_libraries( main ${Boost_LIBRARIES} )

8
不需要 link_directories,因为 Boost_LIBRARIES 将是完全限定路径。 - RobertJMaynard
在我的情况下,link_directories 是必要的。 - mgruber4
5
这个回答不适用于新的代码。应该优先选择oLen的回答。 - Alex Reinking

7

有两种方法,使用系统默认安装路径,通常为/usr/lib/x86_64-linux-gnu/

find_package(Boost REQUIRED regex date_time system filesystem thread graph)
include_directories(${BOOST_INCLUDE_DIRS})
message("boost lib: ${Boost_LIBRARIES}")
message("boost inc:${Boost_INCLUDE_DIR}")

add_executable(use_boost use_boost.cpp)
target_link_libraries(use_boost
        ${Boost_LIBRARIES}
        )

如果您选择在本地目录安装Boost,或选择本地安装而非系统安装,则可以按照以下方式进行操作:
set( BOOST_ROOT "/home/xy/boost_install/lib/" CACHE PATH "Boost library path" )
set( Boost_NO_SYSTEM_PATHS on CACHE BOOL "Do not search system for Boost" )

find_package(Boost REQUIRED regex date_time system filesystem thread graph)
include_directories(${BOOST_INCLUDE_DIRS})
message("boost lib: ${Boost_LIBRARIES}, inc:${Boost_INCLUDE_DIR}")

add_executable(use_boost use_boost.cpp)
target_link_libraries(use_boost
        ${Boost_LIBRARIES}
        )

请注意上面的目录 /home/xy/boost_install/lib/ 是我安装Boost的位置:
xy@xy:~/boost_install/lib$ ll -th
total 16K
drwxrwxr-x 2 xy xy 4.0K May 28 19:23 lib/
drwxrwxr-x 3 xy xy 4.0K May 28 19:22 include/

xy@xy:~/boost_install/lib$ ll -th lib/
total 57M
drwxrwxr-x 2 xy xy 4.0K May 28 19:23 ./
-rw-rw-r-- 1 xy xy 2.3M May 28 19:23 libboost_test_exec_monitor.a
-rw-rw-r-- 1 xy xy 2.2M May 28 19:23 libboost_unit_test_framework.a
.......

xy@xy:~/boost_install/lib$ ll -th include/
total 20K
drwxrwxr-x 110 xy xy  12K May 28 19:22 boost/

如果您想知道如何使用本地安装的Boost,您可以查看这个问题:如何让CMake找到我的替代Boost安装?。请注意保留HTML标记。

4
这里是我的看法:
cmake_minimum_required(VERSION 3.15)

project(TryOuts LANGUAGES CXX)

find_package(Boost QUIET REQUIRED COMPONENTS program_options)

if(NOT Boost_FOUND)
    message(FATAL_ERROR "Boost Not found")
endif()

add_executable(helloworld main.cpp)

target_link_libraries(helloworld PUBLIC Boost::program_options)

target_link_libraries(helloworld PUBLIC Boost::program_options) 会导致 CMAKE 错误:-- 配置完成 CMakeLists.txt:102 行错误 (add_executable): 目标 "DB32" 链接到目标 "Boost::program_options",但该目标未找到。可能缺少一个 IMPORTED 目标的 find_package() 调用,或者缺少 ALIAS 目标? - munsingh
你好,感谢您的反馈。看起来CMake在您的系统上无法定位到Boost。也许您最好从源代码开始重新构建Boost。在此之前,您可能想尝试以下操作: 使用find_package(Boost QUIET REQUIRED)查找包并将其链接到您的目标(DB32):target_link_libraries(DB32 PUBLIC Boost::headers) - user4640261
因为你使用了 REQUIRED,所以 NOT Boost_FOUND 永远不会为真,因此整个 if 语句是无意义的。 - Alex Reinking

1
哪个Boost库?其中许多都是纯模板,不需要链接。
现在,有了那个真正展示告诉我们你想要Boost程序选项的具体示例(甚至更告诉我们你在Ubuntu上),你需要做两件事:
  1. 安装libboost-program-options-dev以便您可以链接它。
  2. 告诉cmake链接到libboost_program_options
我主要使用Makefile,所以这里是直接的命令行用法:
$ g++ boost_program_options_ex1.cpp -o bpo_ex1 -lboost_program_options
$ ./bpo_ex1
$ ./bpo_ex1 -h
$ ./bpo_ex1 --help
$ ./bpo_ex1 -help
$

看起来它似乎没有做很多事情。

对于CMake,您需要将boost_program_options添加到库列表中,如果我没记错,可以通过在CMakeLists.txt中使用SET(liblist boost_program_options)来完成。


16
你的 CMake 建议是错误的(请参考被接受的答案),而你的命令行建议并不是很有帮助,因为问题是关于 CMake 的。 - Ela782

0
另一个可能导致错误的原因是:
如果您使用ABI=0构建了boost库。
./b2 -q cxxflags=-D_GLIBCXX_USE_CXX11_ABI=0 install

如果你要构建应用程序,那么你也必须使用ABI=0。
add_cxx_flags( "-D_GLIBCXX_USE_CXX11_ABI=0" )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接