【问题标题】:HelloWorld: downloading, building and linking Boost using CMakeHelloWorld:使用 CMake 下载、构建和链接 Boost
【发布时间】:2017-05-29 10:07:24
【问题描述】:

我有一个 Hello, World 风格的小程序,我想使用 CMake 以端到端的方式进行更多工作。在这种情况下,这意味着我可以下载 Boost 库,编译它们,最后编译我的小 Hello, World 并将 Boost 库链接到它。

目录布局目前看起来像这样

cmaketest |- build //我希望这里有 CMake 生成的 IDE 文件。 |- 源 |- 主.cpp |- 你好.cpp |- 你好.hpp |- 依赖 //我想在这里有内置的 Boost 库和头文件。 |- downloads //这包含下载的 zip 文件。 |- temp //临时文件。

我有以下 CMakeLists.txt,目前我生成 Visual Studio 2015 项目文件,如下所示:cmake build -G "Visual Studio 14 2015 Win64"。一切都好,我将开始解决方案,CMake 抱怨它找不到 Boost,去下载它开始构建(在下面的代码中,我设置为获取以前获取的文件)。但是建了一段时间后,问题就出现了……

  1. Boost 文件似乎以根目录出现在\cmaketest\CMakeFiles\build\Boost-prefix\src\Boost 中。我如何才能将它们构建为\depends\boost(或达到此效果)以及如何包含要链接到解决方案的库?这个链接是我遇到的另一个问题,我知道如何包含这个奇怪目录中的标题,但这并不是我真正想要的。
  2. 看起来 VS IDE 首先警告找不到 Boost 标头(请参阅主程序),然后开始 Boost 构建。这可以避免吗?
  3. 如何让Boost库从VS解决方案中消失? IE。不做一个项目,而只是依赖于头文件和库?
  4. 如果 Boost 包已经在磁盘上,是否有内置方法可以避免下载它?看起来它无论如何都会被检索到,我考虑过检查文件是否存在。

main.cpp(我想这是本例中的相关文件)

//The Boost headers are included just to check the linker.
#include "hello.hpp"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <iostream>
using std::cout;
using std::endl;

int main()
{
    hello helloer;
    cout << helloer.greet("World here") << endl;

    return EXIT_SUCCESS;
}

然后是CMakeLists.txt 文件。

cmake_minimum_required(VERSION 3.6 FATAL_ERROR)
set(CMAKE_VERBOSE_MAKEFILE ON)
project(Cmaketest)

if(POLICY CMP0042)
   cmake_policy(SET CMP0042 NEW)
endif()

if(POLICY CMP0066)
   cmake_policy(SET CMP0066 NEW)
endif()

# Default build type if none was specified.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
  message(STATUS "Setting build type to '${CMAKE_BUILD_TYPE} as none was specified.")

  # Possible values of build type for CMake GUI.
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()

# The path to extra modules.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

# Setup build locations.
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
set(CMAKE_CURRENT_BINARY_DIR    
${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/build)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

include(ExternalProject)
include(ProcessorCount)
ProcessorCount(N)
if(NOT N EQUAL 0)
    set(CMAKE_BUILD_FLAGS -j${N})
endif()
# set(BOOST_VERSION 1.63.0)
# Boost related settings:    
# https://cmake.org/cmake/help/v3.6/module/FindBoost.html.
# Should one check the environment variables and flags here explicitly
# to remove the complaint about missing Boost library? Or should perhaps
# BOOST_ROOT be set? Point to what?
find_package(Boost)
if(NOT Boost_FOUND)
    # It shouldn't hurt to enable extensive diagnostics, just in case.
    # Also, a different set of files is downloaded for UNIX and WIN32
    # due to file permissions and line-feeds (Windows should handle
    # also Unix style line-feeds).
    set(Boost_DETAILED_FAILURE_MSG on)
    add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
    set(Boost_Bootstrap_Command)
    if(UNIX)
       set(Boost_Url     "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.gz")
        set(Boost_Sha1 "2cecf1848a813de55e5770f324f084c568abca0a")
        set(Boost_Bootstrap_Command ./bootstrap.sh)
        set(Boost_b2_Command ./b2)
     elseif(WIN32)
        set(Boost_Url "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.zip")
        set(Boost_Sha1 "4364989afbe6b11f2d5e59df902c3ca4d7851824")
        set(Boost_Bootstrap_Command bootstrap.bat)
        set(Boost_b2_Command b2.exe)
    endif()
        set(Config_Libraries "chrono,filesystem,program_options,system,thread,test")
ExternalProject_Add(Boost
    TMP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/temp"
    DOWNLOAD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/downloads"
    URL "${CMAKE_CURRENT_SOURCE_DIR}/downloads/boost_1_63_0.zip"
    URL_HASH "SHA1=${Boost_Sha1}"
    BUILD_IN_SOURCE 1
    UPDATE_COMMAND ""
    PATCH_COMMAND ""
    CONFIGURE_COMMAND ${Boost_Bootstrap_Command} --without-icu --with_libraries=${Config_Libraries}
    BUILD_COMMAND  ${Boost_b2_Command}
        # --prefix="${CMAKE_CURRENT_SOURCE_DIR}/depends"
        --without-python
        --address-model=64
        --architecture=x64
        --threading=multi
        --link=static
        --variant=release
        --layout=tagged
        --build-type=complete
        -j${N}
    INSTALL_COMMAND ""
    # INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/depends"

    #As it happens, these directories are currently empty...
    # set(BOOST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/depends/include/boost-1_63)
    # set(Boost_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/boost_1_63/include)
    # set(Boost_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/depends/boost_1_63/lib)
)
endif()

 set(Boost_USE_STATIC_LIBS OFF)
 set(Boost_USE_MULTITHREADED ON)
 set(Boost_USE_STATIC_RUNTIME OFF)
 include_directories(${CMAKE_SOURCE_DIR}/src)

# Grabbing just all the test project files.
file(GLOB SOURCES "src/*.*")
add_executable(cmaketest ${SOURCES})
# TARGET_LINK_LIBRARIES(cmaketest ${Boost_LIBRARY})

【问题讨论】:

  • 您的意图和目标是从源代码构建 Boost,还是只想在您的应用程序中使用 Boost,而您的应用程序是使用 CMake 构建的?在后一种情况下,我建议下载预构建的 Boost,例如从这里sourceforge.net/projects/boost/files/boost-binaries/1.63.0 然后在您的 CMake 中使用 find_package(Boost 1.63 REQUIRED),它将设置变量(请参阅 FindBoost 模块文档)以及 Boost 库和头文件的位置。您可能需要通过在您调用 find_package() 的 CMakeLists.txt 中提供 BOOST_ROOT 变量来帮助 FindBoost
  • 我想从源代码构建它,以学习在 Boost 的上下文中做到这一点。接下来的事情是从 vspkg、Nuget、Conan 或类似的地方获取二进制依赖项。我也试探性地看了一下。无论如何,我有这个我想解决的当前问题。 @fedepad 写的内容有助于了解我的方式错误,但仍有一段路要走。我相信我稍后(目前在移动设备上)将问题更新为最新尝试。
  • @ivan_onys 我还可以想象如何根据构建决定是否包含调试和发布二进制文件存在问题。但也许以后的时间。 :)
  • @ivan_onys 我想说这个想法是让下载源代码的人只下载cmake、make 和 make install,而不用担心大量的依赖关系(尤其是 boost,这是一个地狱般的依赖);这可以帮助技术含量较低的用户构建和使用应用程序。

标签: c++ boost cmake


【解决方案1】:

我会尝试给您一些提示,尝试回答您的问题。

1) 使用这个 sn-p,您应该能够在正确的目录中拥有源代码和构建文件。我保留了TMP_DIR "${Cmaketest_SOURCE_DIR}/temp",但在我的项目中我不使用那条线。

ExternalProject_Add(Boost
    TMP_DIR "${Cmaketest_SOURCE_DIR}/temp"
    DOWNLOAD_DIR "${Cmaketest_SOURCE_DIR}/downloads"
    URL "${Cmaketest_SOURCE_DIR}/downloads/boost_1_63_0.zip"
    URL_HASH "SHA1=${Boost_Sha1}"
    SOURCE_DIR ${Cmaketest_SOURCE_DIR}/downloads/boost_1_63_0
    BUILD_IN_SOURCE 1
    UPDATE_COMMAND ""
    PATCH_COMMAND ""
    CONFIGURE_COMMAND ${Boost_Bootstrap_Command} --without-icu --with_libraries=${Config_Libraries}
    BUILD_COMMAND  ${Boost_b2_Command}
        --prefix="${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0"
        --without-python
        --address-model=64
        --architecture=x64
        --threading=multi
        --link=static
        --variant=release
        --layout=tagged
        --build-type=complete
        -j${N}
    INSTALL_COMMAND ${Boost_b2_Command} --prefix="${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0" --without-python
        --address-model=64
        --architecture=x64
        --threading=multi
        --link=static
        --variant=release
        --layout=tagged
        --build-type=complete
        -j${N} install
    INSTALL_DIR "${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0"
)

set(BOOST_ROOT ${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0)
set(Boost_LIBRARY ${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0/lib)
set(Boost_INCLUDE_DIR ${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0/include)
include_directories(${Boost_INCLUDE_DIR})

要注意您没有调用“安装”,因此一旦在那个“奇怪”目录中构建,文件就不会移动到指定的前缀。还要注意使用${Cmaketest_SOURCE_DIR} 而不是以前的。
尝试打印两者,看看是否有区别。

2) 要解决在未找到 Boost 时收到的警告,您应该编写:

find_package(Boost QUIET)  

3)为了解决这个问题,我猜你无法生成项目文件,即,而不是

cmake build -G "Visual Studio 14 2015 Win64"  

只需要cmake . 或cmake ..,具体取决于您将进行源内构建还是源外构建。我建议进行源外构建,但这是您的选择。
4) FindBoost.cmake (FindBoost.cmake) 使您可以将任意路径传递到 Boost 目录。您可以在配置中使用它来提示 CMake 在您提供的位置查找 Boost,例如您可以通过以下方式调用 cmake:

cmake -DBOOST_ROOT=/path_to_cmaketest_dir/depends/boost_1_63_0 ..  

如果您的系统可能很挑剔,您可以指定所有内容:

cmake -DBOOST_ROOT=/path_to_cmaketest_dir/depends/boost_1_63_0 -DBOOST_LIBRARYDIR=/path_to_cmaketest_dir/depends/boost_1_63_0/lib DBOOST_INCLUDEDIR=/path_to_cmaketest_dir/depends/boost_1_63_0/include ..  

请注意,在最后两个 sn-ps 中,我假设配置了源外构建。
另请注意,如果您已经安装或下载了 Boost 包,则在 1) 中的代码片段中使用 ${Cmaketest_SOURCE_DIR} 应该也可以解决 4) 所以当它找不到 Boost 时它会尝试下载但它不会,因为现在cmake 应该可以看到文件(.zip)。

【讨论】:

  • 嗨! ${Cmaketest_SOURCE_DIR} 和 ${Cmaketest_SOURCE_DIR} 都打印相同的路径:C:/projektit/cmaketest。这看起来很奇怪,因为现在我收到错误消息,我认为罪魁祸首是CMake Error at C:/Program Files/CMake/share/cmake-3.7/Modules/ExternalProject.cmake:1117 (message): dir 'C:/projektit/cmaketest/depends/boost_1_63;set;(;BOOST_ROOT;C:/projektit/cmaketest/depends/include/boost_1_63;);set;(;Boost_LIBRARY;C:/projektit/cmaketest/depends/boost_1_63/lib;);include_directories;(;Boost_INCLUDE_DIR-NOTFOUND;)' does not exist after file(MAKE_DIRECTORY)
  • 我自然需要对此进行调查。我还发现我可能应该添加 SYSTEM,如 include_directories(SYSTEM ${Boost_INCLUDE_DIR}),以排除生成的 VS 解决方案中的头文件。
  • 好的,问题是我脚本中的 Boost 路径设置在括号内(多么尴尬)。然而,将它们移出并没有解决构建的问题。仍有待调查...
  • 我回来了...${Cmaketest_SOURCE_DIR} 和 ${Cmaketest_SOURCE_DIR} 当然打印相同的路径...我的意思是 ${CMAKE_CURRENT_SOURCE_DIR} 和 ${Cmaketest_SOURCE_DIR}。
  • 啊,我写错了,我有message 用于这两个,它们打印相同的路径。
【解决方案2】:

请参阅CMaker_Boost,在配置时使用 CMake 构建 Boost。现在在 Linux 和 Android、gcc 和 clang 上进行了测试。其他系统未测试。我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2022-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    相关资源
    最近更新 更多