【问题标题】:Is it possible to build Boost with CMake? [closed]是否可以使用 CMake 构建 Boost? [关闭]
【发布时间】:2013-08-23 15:30:38
【问题描述】:

我不想在交叉编译项目的源代码树中包含静态库,而是想将 boost 直接添加到 cmake 中并构建它。这个可以吗?

【问题讨论】:

  • 为什么是cmake,bjam有什么问题?
  • 嗨,bjam 没什么问题。只是 CMake 可以与我拥有的所有其他库顺利集成。当(这并不常见)我找到一个没有 cmakefile 的库时,我会从网上获取它或自己编写它。但是在 boost, 1 的情况下,libs 的关系并不是微不足道的。 2 有些人似乎已经在研究这个,所以我更喜欢使用正确的方式(git模块化也很棒,但这只是一个奖励)。
  • 您可以使用外部项目通过 bjam 构建 boost。喜欢这里:cmake.org/pipermail/cmake/2012-June/050775.html
  • @EmileCormier 投票和收藏并不表示问题的主题性质。此问题与 SO 无关,请随时对其进行编辑,使其与主题内容保持一致,并将进入重新打开队列以供审核。
  • @bluefeet,我尽我所能试图挽救这个问题。我很确定我抓住了原始发帖人的动机,并将问题改写为不主观。

标签: c++ boost cmake


【解决方案1】:

在我的工作场所,我们也为此苦苦挣扎。虽然我当然不能声称自己知道“最好”的方法,但我可以就我的经历提出以下想法。

我们最初只要求开发人员单独安装 boost,并让 CMake 以find_package(Boost...) 调用的形式进行正常检查。这很容易,但不是自动化的,并且给已经安装了旧版本 boost 的开发人员带来了问题。

然后我们改变了策略并添加了我们从您上面提到的一个项目中克隆的增强源的副本。我不记得具体细节了,但我认为这是 Ryppl 项目目前正在开发的一个前身。重点是它已经支持 CMake。 boost 库是通过 add_library 调用添加的实际 CMake 目标,这使它们更易于在 CMake 代码中使用。

虽然这通过在我们的项目中自动使用 boost 解决了之前的问题,但它最终变成了维护的噩梦。我们克隆的 boost 项目发生了根本性的变化,现在非常依赖于 Ryppl 特定的 CMake 函数。我们不想将 Ryppl 添加为依赖项,所以我们再次改变了策略!

我们查看了您在问题中提到的项目,同样发现它们都不可用。

我们当前的设置使用了 CMake 的 ExternalProject 模块。这使我们能够下载并构建提升到我们的构建树。

优点:

  • 维护成本低
  • 自动化,因此所有开发人员都使用使用相同标志构建的相同版本
  • 使我们自己的源代码树不受第三方代码的影响
  • boost 的多个副本可以愉快地共存(因此不会意外链接到使用不同编译器/stdlib 组合构建的副本)

缺点

  • 删除构建树意味着必须从头开始下载和构建 boost。这可以通过例如改善。下载到固定位置(例如,系统临时目录),因此如果找到了 boost 源的现有副本,则可以跳过下载/解压缩步骤。
  • boost 库不是正确的 CMake 目标(即它们不是通过 add_library 调用添加的)

这是our CMake code 的链接。有几种方法需要改进,但目前对我们来说效果还不错。

我希望这个答案很快就会过时,并且可以提供一个体面的、模块化的、兼容 CMake 的解决方案。

【讨论】:

  • 谢谢,我会试一试,我在安装版本时遇到了同样的问题,所以现在我就是这样做的,仅限于文件系统(即少于 10 个 src 文件)所以重建不是一个大问题,但是我在 git/ryppl 上看到的模块会更好,因为它可以帮助我不在另一个项目上重做这个,而只是构建我需要的东西。
  • 是的——可惜的是 CMake 版本依赖于 Ryppl 模块。我们真的宁愿没有另一个 3rd 方依赖项。我认为在您的情况下,我很想调查只是将 Boost.Filesystem 及其依赖(例如 Boost.System)源文件添加到您的存储库并使用 add_library。顺便说一句,我认为正在研究 Boost.Filesystem 是为了将其添加到标准库中。据我回忆,这不是 C++14 计划的更改之一,但我认为委员会正在推动更快地将新库纳入标准。那时你可能根本不需要 Boost。
  • 是的,我知道,但即使它已经在 VC2012 中,它也不在我所看到的 xcode 5 (DP5) 中,所以我决定使用 boost.filesystem。是的,现在我已经直接将文件系统和系统的源添加到我的 pproject 中,但是如果将来我想使用更多的 boost,那将是最好的。关于 boost 模块化的 cmake,我可以在 windows 上构建大部分,使用 boost-zero 存储库和子模块,但它既不是真正成熟的生产,也不是我所见的 boost 1.54 的最新版本,但我不是 boost 专家.
  • 关于你的 cmake 也很棒,但我什至无法启动 bootstrat.bat,我不知道 bjam 是否可以工作(我确定这是我这边的一个问题,因为这是一个经过良好测试的工具)
  • 是的 - 对不起 - 我的意思是在未来的某个时候你可能不需要 Boost.Filesystem。至于运行 bootstrap.bat 的问题,我可能必须查看错误消息才能提供帮助。您可以尝试在新下载的 Boost 副本上从 MSVC 命令提示符运行 bootstrap.bat 以检查它是否有效。
【解决方案2】:

我发现上面 Fraser 的回答是一个很好的起点,但在我们的系统上使用 Boost 1.55.0 时遇到了一些问题。

首先,我们希望为我们的应用程序提供一个独立的源代码包,因此不希望使用 CMake ExternalProject。我们只使用了 Boost 的 thread 和 date_time 库,因此我们使用 bcp 创建了 Boost 的一个子集以及构建工具、thread 和其他依赖库:

$ bcp tools/build thread system date_time ../boost_1_55_0_threads_only

并将其签入我们的 svn 存储库。

接下来,我能够调整 Fraser 的 CMake 文件以在 Linux 上构建,但在使用 CMake 的 execute_process 命令在 Windows 上运行 bootstrap.bat 文件时遇到了问题。要运行 bootstrap.bat,我们首先需要运行相关的 Visual Studio vcvarsall.bat 脚本来设置环境变量(我们可能会弄清楚需要设置哪些单个变量,但运行整个脚本更容易)。为了在同一个 shell 中使用 execult_process 运行两个 .bat 文件,我们使用了cmd /c 并列出了以& 分隔的文件作为参数。

另外bootstrap.bat 没有在失败的情况下将退出代码设置为非零,因此使用execute_process RESULT_VARIABLE 来检查是否成功不起作用。相反,我们在命令运行后检查了 b2.exe 可执行文件是否已创建。

最后一个问题:bootstrap.sh 支持--prefix= 选项,bootstrap.bat 不支持。我还发现在 Windows 上为 b2.exe 指定 --prefix 选项有效,但是 在 Linux 上为b2 使用--prefix 选项,但没有为bootstrap.sh 指定它会出错。 (我还不明白为什么)。

所以我们的 CMake 文件的相关部分如下所示:

  #
  # run bootstrap
  #
  if(WIN32)
    if(MSVC10)
      set(VCVARS_CMD "C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 10.0\\VC\\vcvarsall.bat")
    elseif(MSVC11)
      set(VCVARS_CMD "C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 11.0\\VC\\vcvarsall.bat")
    elseif(MSVC12)
      set(VCVARS_CMD "C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat")
    # elseif(...)
     # add more options here
    endif(MSVC10)
    set(BOOTSTRAP_CMD "${VCVARS_CMD} & bootstrap.bat")
    message("Executing command: ${BOOTSTRAP_CMD}")
    execute_process(COMMAND cmd /c "${BOOTSTRAP_CMD}" WORKING_DIRECTORY ${APT_BOOST_SRC}
                  RESULT_VARIABLE BS_RESULT OUTPUT_VARIABLE BS_OUTPUT ERROR_VARIABLE BS_ERROR)
    if(NOT EXISTS ${APT_BOOST_SRC}/b2.exe)
      message(FATAL_ERROR "Failed running cmd /c ${BOOTSTRAP_CMD} in ${APT_BOOST_SRC}:\n${BS_OUTPUT}\n${BS_ERROR}\n")
    else(NOT EXISTS ${APT_BOOST_SRC}/b2.exe)
      message("bootstrap output:\n${BS_OUTPUT}")
    endif(NOT EXISTS ${APT_BOOST_SRC}/b2.exe)
  else(WIN32)
    set(BOOTSTRAP_CMD "./bootstrap.sh")
    set(BOOTSTRAP_ARGS "--prefix=${APT_BOOST_BIN}")
    message("Executing command: ${BOOTSTRAP_CMD} ${BOOTSTRAP_ARGS}")
    execute_process(COMMAND "${BOOTSTRAP_CMD}" ${BOOTSTRAP_ARGS} WORKING_DIRECTORY ${APT_BOOST_SRC}
                  RESULT_VARIABLE BS_RESULT OUTPUT_VARIABLE BS_OUTPUT ERROR_VARIABLE BS_ERROR)
    if(NOT BS_RESULT EQUAL 0)
      message(FATAL_ERROR "Failed running ${BOOTSTRAP_CMD} ${BOOTSTRAP_ARGS} in ${APT_BOOST_SRC}:\n${BS_OUTPUT}\n${BS_ERROR}\n")
    endif()
  endif(WIN32)
  #
  # run b2
  #
  set(B2_ARGS "link=static" "threading=multi" "runtime-link=static" "variant=release")
  foreach(COMP IN LISTS APT_BOOST_COMPONENTS)
    set(B2_ARGS "--with-${COMP}" ${B2_ARGS})
  endforeach(COMP IN LISTS APT_BOOST_COMPONENTS)
  if(WIN32)
    if(MSVC11)
      set(B2_ARGS "--toolset=msvc-11.0" ${B2_ARGS})
    elseif(MSVC12)
      set(B2_ARGS "--toolset=msvc-12.0" ${B2_ARGS})
    endif(MSVC11)
    file(TO_NATIVE_PATH ${APT_BOOST_BIN} APT_BOOST_BIN_WIN)
    set(B2_ARGS "--prefix=${APT_BOOST_BIN_WIN}" ${B2_ARGS} "architecture=x86" "address-model=64")
  endif(WIN32)
  set(B2_ARGS ${B2_ARGS} install)
  set(B2_CMD "./b2")
  message("Executing command: ${B2_CMD} ${B2_ARGS}")
  execute_process(COMMAND ${B2_CMD} ${B2_ARGS} WORKING_DIRECTORY ${APT_BOOST_SRC}
                  RESULT_VARIABLE B2_RESULT OUTPUT_VARIABLE B2_OUTPUT ERROR_VARIABLE B2_ERROR)
  if(NOT B2_RESULT EQUAL 0)
    message(FATAL_ERROR "Failed running ${B2_CMD} in ${APT_BOOST_SRC}:\n${B2_OUTPUT}\n${B2_ERROR}\n")
  endif()

上面APT_BOOST_SRC是我们源目录中Boost子目录的位置,APT_BOOST_BIN是我们在CMake构建目录中用来存储库的位置,APT_BOOST_COMPONENTS是Boost库的列表我们正在使用。

【讨论】:

  • 是的。我看了一点,但我遇到的问题是路径中需要转义的空格和括号。引用路径并在 execute_process 命令中将其传递给 cmd.exe 很尴尬,因此显式设置路径并使用 ^ 转义字符似乎更容易。我可以使用 CMake 的一些字符串函数来操作来自 VS*COMNTOOLS 的路径。
  • 这应该是答案。请参阅CMaker_Boost,在配置时使用 CMake 构建 Boost。现在在 Linux 和 Android、gcc 和 clang 上进行了测试。其他系统未测试。我希望这会有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-05
  • 2019-12-13
  • 1970-01-01
  • 2012-10-25
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多