【问题标题】:Adding Boost to CMake project?将 Boost 添加到 CMake 项目?
【发布时间】:2019-07-02 01:32:45
【问题描述】:

背景

我是一个 C++ 的新手,而且我一个接一个地遇到麻烦,所以如果这非常简单并且我 只是那么愚蠢,请原谅我强>...

我有一个最终应该在 Linux 中编译和运行的项目。不幸的是,在lots of issues with my C++ development environemnt(仍未解决)之后,我放弃了尝试在 Linux 中进行开发并转向 Windows Visual Studio 2017。我希望让我的代码在 Windows 中工作,然后,由于 C++ 被认为是一种可移植语言,它应该只需在 Linux 中进行少量更改即可工作。

Visual Studio 似乎工作了一天左右。我可以编写代码,点击“编译”,它会像魔术一样运行。我拼凑了几个类来构建一个有向无环图,使用标准库作为哈希表,然后我尝试创建一个套接字......

Windows 和 Linux 使用不同的套接字库(<sys/socket.h><winsock.h>),所以我需要一些方法来抽象差异,我更喜欢一个完善的标准。谷歌搜索,我发现 the Boost library 似乎符合我的需求......那就是一切都陷入困境的时候。

我的项目设置

因为这个项目将在各种平台和 IDE 上开发(有些人使用 Windows + Visual Studio,有些人使用 Mac + Eclipse,而其他人使用 Linux + VIM)我选择将其作为 CMake 项目。经过几个小时的阅读、学习和研究,CMake 似乎应该给我我想要的东西(方便且可重复的跨平台构建,几乎没有或没有依赖问题)

我的源代码(直接来自Boost Getting Started on Windows指南)如下:

CMakeProject2.cpp

#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    using namespace boost::lambda;
    typedef std::istream_iterator<int> in;

    std::for_each(
        in(std::cin), in(), std::cout << (_1 * 3) << " ");
}

根据Boost Getting Started on Windows 指南,我从这里下载了 Boost:

https://dl.bintray.com/boostorg/release/1.67.0/source/boost_1_67_0.zip

(有趣的是,入门指南的标题是“Boost 在 Windows 上入门 - 1.69.0”,但它链接到 Boost 版本 1.67.0)

下载并解压 ZIP 文件后,我有一堆乱七八糟的文件 - 但不知道把它们放在哪里:

目前为止的工作尝试

我尝试add the Boost library to my project,但没有任何预期的菜单选项可用:

虽然我 couldn't find a single page 会警告你这个问题,但显然 CMake 项目没有难以捉摸的“属性”窗口——而是必须以某种方式包含第三方库通过 CMakeLists.txt 文件

对于初学者,我将 Boost ZIP 文件的整个 540 MB 内容复制到我的项目中名为“Boost”的文件夹下:

然后我尝试了一系列不同的 CMakeList.txt 命令:

How do you add Boost libraries in CMakeLists.txt?:

set(Boost_USE_STATIC_LIBS OFF) 
set(Boost_USE_MULTITHREADED ON)  
set(Boost_USE_STATIC_RUNTIME OFF) 
find_package(Boost REQUIRED COMPONENTS lambda) 

if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS}) 
    add_executable(CMakeProject2 "CMakeProject2.cpp" "CMakeProject2.h") 
    target_link_libraries(CMakeProject2 ${Boost_LIBRARIES})
endif()

https://www.selectiveintellect.net/blog/2016/7/29/using-cmake-to-add-third-party-libraries-to-your-project-1:

include("Boost")
add_subdirectory("Boost")
add_subdirectory("boost")
add_subdirectory("Boost/boost")
add_subdirectory("Boost/boost/lambda")

target_link_libraries(boost)
target_link_libraries(Boost)

https://cmake.org/pipermail/cmake/2009-November/033249.html:

SET (Boost_FIND_REQUIRED TRUE)
SET (Boost_FIND_QUIETLY TRUE)
SET (Boost_DEBUG FALSE)
set (Boost_USE_MULTITHREADED TRUE)
set (Boost_USE_STATIC_LIBS TRUE)
SET (Boost_ADDITIONAL_VERSIONS "1.67" "1.67.0")

FIND_PACKAGE(Boost COMPONENTS  lambda)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})

我尝试了其他几种咒语(不熟悉 C++ CMake 作为工具),要么从 CMakeLists.txt 或从 CMakeProject2.cpp 收到关于 @ 的错误987654355@。事实上,关于那些“CMakeLists.txt”错误,在我的文件中添加了 enough 行之后,我开始定期使 Visual Studio 崩溃。请注意,我有一个第 8 代 i7、32 GB 的 RAM 和一个 M.2 NVMe 硬盘驱动器——所以我印象深刻的是,文本文件中的几行足以让 Microsoft 将我的计算机锁定 10 分钟一次。

所有这些都失败了,我尝试将我需要的文件直接复制到我的项目中:

现在,我又是 C/C++ 开发的新手,所有可能出错的事情已经出错了。到目前为止,我已经花了将近两个星期的时间,勉强在两台计算机、三个 IDE 和四个编译器上编译了一个“Hello, World”应用程序。我还没有取得任何成功,包括来自任何地方、任何流行程度或简单程度的第三方库,并且实际上编译了一个引用该库的功能程序。因此,当我说:我不知道“仅标题库”和……无论替代方案是什么时,请相信我。我只知道,根据Boost Getting Started on Windows 指南,大多数 Boost 是“仅标题”,因此我不应该有任何构建步骤 - 它应该是使用简单。此外,这个例子(使用boost::lambda)是 - 根据他们的说明 - 一个只有头文件的库,因此应该非常容易使用。

我现在稍微更新了源代码以查看当前目录,而不是查看系统包含目录(据我目前所知,Windows 中不存在该目录):

#include "boost/lambda/lambda.hpp"
#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    using namespace boost::lambda;
    typedef std::istream_iterator<int> in;

    std::for_each(
        in(std::cin), in(), std::cout << (_1 * 3) << " ");
}

现在我可以手动验证此文件是否存在(文件 CMakeProject2\CMakeProject2\boost\lambda\lambda.hpp 可以在文件资源管理器中找到) - 但我是 仍然出现错误:

cannot open source file "boost/lambda/lambda.hpp"

进一步的谷歌搜索让我再次更新了我的 CMakeLists.txt 文件,将其置于当前形式:

# CMakeList.txt : CMake project for CMakeProject2, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)

# Add source to this project's executable.
file(GLOB CMakeProject2_SRC
    "*.h"
    "*.cpp"
    "**/*.h"
    "**/*.cpp"
    "**/*.hpp"
    "boost/lambda/lambda.hpp"
)
add_executable (CMakeProject2 ${CMakeProject2_SRC})
#add_executable (CMakeProject2 "CMakeProject2.cpp" "CMakeProject2.h")

# TODO: Add tests and install targets if needed.

尽管如此,我仍然收到错误:

cannot open source file "boost/lambda/lambda.hpp"

此时我正在扯掉我的头发。我究竟做错了什么?我不知道什么?像“Hello, World”这样简单的类似 Boost 的东西怎么不适合我?

【问题讨论】:

  • 尝试使用基于目标的 API。 target_link_libraries(you_exe PUBLIC boost::lambda) 这条命令应该添加包含目录以及链接库。
  • @GuillaumeRacicot imgur.com/ChwBo57 运气不好
  • 要使用 target 你必须首先找到 boost 包:find_package(Boost COMPONENT lambda REQUIRED)
  • 所以find_package(Boot COMPONENTS lambda REQUIRED) 抛出错误“无法找到请求的 Boost 库。请将 BOOST_ROOT 设置为根目录...”。然后我添加了set(BOOST_ROOT "C:\\local\\boost_1_69_0"),第一次看到“Boost 版本:1.69.0”(正在取得进展!)紧接着是“找不到以下 Boost 库:lambda。没有找到 Boost 库。您可能需要设置BOOST_LIBRARYDIR……”。我试过set(BOOST_LIBRARYDIR "${BOOST_ROOT}\\libs")(除其他外)但还没有运气
  • 我第一次尝试使用 boost 时遇到了类似的错误。我现在不在我的主计算机上,当我可以物理访问它时,我会通知你。我知道我设法让它发挥作用。据我记得,cmake 没有正确检测到较新的 boost 版本,但我现在不能 100% 确定。

标签: c++ visual-studio boost cmake


【解决方案1】:

以下配方应该可以工作

official boost binaries location 下载 Boost 二进制文件并安装到 C:\Boost

大多数时候您不需要自己构建 Boost。

您的 CMakeLists.txt 应如下所示

cmake_minimum_required (VERSION 3.8)

project(boostAndCMake)

set(BOOST_ROOT "C:\Boost") # either set it here or from the command line  
set(Boost_USE_STATIC_LIBS OFF) 
set(Boost_USE_MULTITHREADED ON)  
set(Boost_USE_STATIC_RUNTIME OFF) 
find_package(Boost REQUIRED COMPONENTS system) # header only libraries must not be added here

add_executable(CMakeProject2 CMakeProject2.cpp CMakeProject2.h) 
target_include_directories(CMakeProject2 PUBLIC ${Boost_INCLUDE_DIRS}) 
target_link_libraries(CMakeProject2 ${Boost_LIBRARIES})

因为我们在find_package 调用中使用了REQUIRED,所以如果找不到,CMake 将执行失败并跳过脚本的其余部分。所以不需要检查Boost_FOUND。当你省略REQUIRED时,你需要检查它。

现在从脚本所在目录的命令行调用:

cmake -H. -Bbuildit -G "Visual Studio 15 2017" -DBOOST_ROOT=C:\Boost 

这会在当前目录中创建一个名为 buildit 的构建目录,进一步在构建目录中为 Visual Studio 2017 创建一个解决方案,并为在 find_package 调用中使用的变量 BOOST_ROOT 提供设置以识别 Boost电脑上的目录。要查看 find_package(Boost ...) 调用中可用的选项,请参阅 CMake 中的 FindBoost 文档。

仅标题库

如果您的库只是标题,您需要在 find_package(Boost ...) 调用中省略它们。要查看哪些库是不是标头,请仅查看此post

使用较新的 Boost 版本

如果您的 CMake 安装找不到请求的版本,例如1.69.0,但支持更新的 Boost 版本的命名方案,您可以将其与 set(Boost_ADDITIONAL_VERSIONS "1.69.0" "1.69") 一起使用。 Boost 命名方案的最后一次更改是从 1.65.1 到 1.66。

【讨论】:

  • 据我所知,顶部的“下载最新版本”链接只是下载了我已有的旧版本(1.66.0 与 1.67.0)——一个包含几个 Boost 的目录头文件、文档等。鉴于您说要下载 Boost“二进制文件”,我假设您的意思是要在版本文件夹中找到其中一个 EXE 文件。点击“1.69.0”它显示了几个EXE——我怎么知道要下载哪一个?我不确定我的 MSVC 版本是什么(或如何弄清楚):imgur.com/3TRTJgl
  • 您的编译器 Visual Studio 15 2017 是 MSVC 14.1。请参见此处:blogs.msdn.microsoft.com/vcblog/2017/11/15/…
  • 下载boost_1_69_0-msvc-14.1-64,双击可执行文件,同意运行来自未知发布者的应用程序,Windows“Antimalware Service Executable”开始锁定我的整个系统。如果这种情况持续太久,那么我将禁用反恶意软件/防病毒软件并重试。现在explorer.exe 没有响应
  • 如果您安装 Boost 64 位版本,您也需要调整生成器:然后是 Visual Studio 15 2017 Win64。 Boost 安装可执行文件的大小为 200+ MB,包含数十个微小、中小型文件。这可能需要一些时间。
  • 在我的计算机连续 20 分钟无响应后,我关闭了电源,重新启动,然后再次尝试(没有先禁用防病毒,看看它是否是侥幸冻结了这么久) .探险者再次僵住了。 10 分钟后,我又进行了一次硬关机、重启、禁用防病毒软件并运行它——立即生效。然后试了你的CMakeLists.txt,还是不行:imgur.com/sz8mbnu
【解决方案2】:

这是 Boost 1.68 与 CMake 3.12 的工作设置。 Boost 1.69 显然“太新”,cmake 无法正确检测到它。由于 cmake 无法构建 boost,因此 cmake 本身必须提供一个 FindBoost.cmake 模块,该模块必须跟上 boost 的变化。

所以无论如何,CMakeLists.txt 就是这么小:

cmake_minimum_required(VERSION 3.11)

project(foobar)

find_package(Boost 1.68 REQUIRED)
add_executable(foo foo.cpp)
target_link_libraries(foo PUBLIC Boost::boost)

当然,你可以把它分成很多子目录。

在命令行中调用 CMake 应该如下所示:

cmake -DCMAKE_PREFIX_PATH=path_to_local_directory ..

其中path_to_local_directory 是您要依赖的all 库的安装路径。它适用于 Boost、nlohmann_json、glfw3、Qt,您可以将其命名为 *(1)。对于我来说,是C:/local/,另一个是../external/(是的,它可以是项目本地的目录!)

让我们看看我自己的C:/local/

ls -l /c/local/
total 12
drwxr-xr-x 1 myself 197609 0 May 26  2018 boost_1_67_0/
drwxr-xr-x 1 myself 197609 0 Sep  5 02:02 boost_1_68_0/

警告:确保您的编译器架构与安装的 boost 版本相同。否则 cmake 根本找不到它。

我是这么想的。下一个 CMake 版本 (3.14) 应该可以使用最新的 boost。


*(1) 上述库要么需要导出它的 CMake 目标,要么您必须提供 FindXXX.cmake

【讨论】:

  • 如果您的 CMake 版本支持更新的 Boost 版本的命名方案,您可以将其与 set(Boost_ADDITIONAL_VERSIONS "1.69.0" "1.69") 一起使用。 Boost 命名方案的最后一次更改是从 1.65.1 到 1.66。
  • @vre 感谢您提供此信息,我将在我的项目中尝试一下。
【解决方案3】:

我正在使用 CMake 3.22 和 Boost 版本 1.78。

最简单的解决方法是在调用Cmake时设置Boost_INCLUDE_DIR

cmake -DBoost_INCLUDE_DIR=boost

将目录传递到 Boost 库所在的位置。如果您使用的是 Visual Studio,您也可以在 CMake 设置中进行设置:

或者,在 CMakeSettings.json 文件中:

"cmakeCommandArgs": "-DBoost_INCLUDE_DIR=boost",

在我看来,这比使用 set 函数要好,因为您不需要对路径进行硬编码。

【讨论】:

    【解决方案4】:

    target_include_directories(CMakeProject2 PRIVATE .) 添加到您的CMakeList.txt

    .是boost/lambda/lambda.hppCMakeLists.txt的相对路径

    并且您不应该将任何.hpp 文件添加到源列表中。

    【讨论】:

    • 好吧,我看看你的截图......首先 target_include_directories() 命令是添加一个包含目录到一个 cmake 目标(即可执行的 CMakeProject2)。并且必须放在 add_executable() 之后。此外,最好将显式文件名放在 add_executable() 中,而不是 glob。在你的情况下: add_executable(CMakeProject2 CMakeProject2.cpp) .
    • 但这并不能真正解释为什么找不到 boost/lambda/lambda.hpp。
    • imgur.com/l7ywL6e - 移动 target_include_directories 并用显式文件名替换 glob 后仍然抛出错误
    • 这个问题让我很感兴趣......所以我刚刚建立了一个像你这样的项目......用 cmake 3.6 (Linux) 和 3.13 (macOS) 进行了测试 - 好的,它不是 vs2017 和 windows。正如您所猜测的那样,它有效。 github.com/rene-d/test-CMakeProject2.
    • 听起来像我在使用 Clang++ 时遇到的问题(请参阅:stackoverflow.com/questions/54521402/locating-iostream-in-clang)我最终加入了 Clang IRC 并调试了 几个小时并且没有人能弄清楚。有时我觉得这就是我的生活:xkcd.com/2083
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 2018-10-31
    • 2017-02-16
    • 2018-03-30
    • 2018-11-25
    • 1970-01-01
    相关资源
    最近更新 更多