C++ 是否可以使用 CMake 构建 Boost?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18354398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to build Boost with CMake?
提问by dzada
Rather than include static libraries in my source tree in a cross-compiled project I'd like to add boost directly into cmake and build it. Is this available?
我不想在交叉编译项目的源代码树中包含静态库,我想直接将 boost 添加到 cmake 中并构建它。这个可用吗?
采纳答案by Fraser
We've struggled with this a fair bit too at my workplace. While I certainly can't claim to know the "best" way, I can offer the following thoughts on my experiences.
在我的工作场所,我们也为此苦苦挣扎。虽然我当然不能声称知道“最好”的方式,但我可以根据我的经验提供以下想法。
We initially just required devs to install boost separately and had CMake do its normal checks in the form of a find_package(Boost...)
call. This was easy, but not automated, and caused problems for devs with older versions of boost already installed.
我们最初只要求开发人员单独安装 boost,并让 CMake 以find_package(Boost...)
调用的形式进行正常检查。这很容易,但不是自动化的,并且给已经安装了旧版本 boost 的开发人员带来了问题。
We then changed tack and added a copy of the boost sources which we cloned from one of the projects you mentioned above. I can't recall the specifics, but I think it was a precursor to the one currently being worked on in the Ryppl project. The main point was that it already had support for CMake; the boost libraries were actual CMake targets added via add_library
calls, which made them easier to work with in the CMake code.
然后我们改变了策略并添加了我们从您上面提到的一个项目中克隆的 boost 源的副本。我不记得具体细节,但我认为它是 Ryppl 项目中目前正在进行的工作的前身。重点是它已经支持 CMake;boost 库是通过add_library
调用添加的实际 CMake 目标,这使得它们更容易在 CMake 代码中使用。
While this solved the previous problems by automating the use of boost in our project, it ultimately became a maintenance nightmare. The boost project we had cloned from changed radically and is now very dependent on Ryppl-specific CMake functions. We didn't want to add Ryppl as a dependency, so we changed tack again!
虽然这通过在我们的项目中自动化使用 boost 解决了之前的问题,但它最终变成了维护的噩梦。我们克隆的 boost 项目发生了根本性的变化,现在非常依赖于 Ryppl 特定的 CMake 函数。我们不想添加 Ryppl 作为依赖项,所以我们再次改变了策略!
We looked at the projects you mentioned in your question, and likewise found none of them to be usable.
我们查看了您在问题中提到的项目,同样没有发现它们可用。
Our current setup makes use of CMake's ExternalProject
module. This allows us to download and build boost to our build tree.
我们当前的设置使用了 CMake 的ExternalProject
模块。这允许我们下载并构建我们的构建树。
Advantages:
好处:
- Low maintenance
- Automated, so all devs use the same version built with the same flags
- Keeps our own source tree free from third-party code
- Multiple copies of boost can happily co-exist (so no chance of accidentally linking to a copy built with a different compiler/stdlib combination)
- 低维护
- 自动化,因此所有开发人员都使用使用相同标志构建的相同版本
- 保持我们自己的源代码树不受第三方代码的影响
- boost 的多个副本可以愉快地共存(因此不会意外链接到使用不同编译器/stdlib 组合构建的副本)
Disadvantages
缺点
- Deleting your build tree means having to download and build boost from scratch. This could be ameliorated by e.g. downloading to a fixed location (say, system temp dir), so the download/unzip step could be skipped if an existing copy of the boost sources is found.
- The boost libraries are not proper CMake targets (i.e. they haven't been added via
add_library
calls)
- 删除构建树意味着必须从头开始下载和构建 boost。这可以通过例如下载到固定位置(例如系统临时目录)来改善,因此如果找到增强源的现有副本,则可以跳过下载/解压缩步骤。
- boost 库不是正确的 CMake 目标(即它们没有通过
add_library
调用添加)
Here's a link to our CMake code. There are a few ways in which this needs improved, but it currently works reasonably well for us.
这是我们的 CMake 代码的链接。有几种方法可以改善这种情况,但目前对我们来说效果还不错。
I hope that soon this answer becomes out of date and a decent, modularised, CMake-compatible solution becomes available.
我希望这个答案很快就会过时,并且可以使用一个体面的、模块化的、与 CMake 兼容的解决方案。
回答by akosky
I found Fraser's answer above to be a good starting point, but ran into some issues using Boost 1.55.0 on our system.
我发现上面弗雷泽的回答是一个很好的起点,但在我们的系统上使用 Boost 1.55.0 时遇到了一些问题。
First we wanted to have a self-contained source code package for our applications, so preferred not to use the CMake ExternalProject. We were only using the thread and date_time libraries from Boost, so we used bcp to create a subset of Boost with the build tools, thread and other dependent libraries:
首先,我们希望为我们的应用程序提供一个自包含的源代码包,因此不希望使用 CMake ExternalProject。我们只使用了 Boost 的 thread 和 date_time 库,所以我们使用 bcp 来创建 Boost 的一个子集,其中包含构建工具、线程和其他依赖库:
$ bcp tools/build thread system date_time ../boost_1_55_0_threads_only
and checked this into our svn repository.
并将其签入我们的 svn 存储库。
Next, I was able to adapt Fraser's CMake file to build on Linux, but ran into problems running the bootstrap.bat
file on Windows with CMake's execute_process command. To run bootstrap.bat we first needed to run the relevant Visual Studio vcvarsall.bat
script to set environment variables (we could probably figure out which individual variables need to be set, but it was easier to run the whole script). To run two .bat files in the same shell using execult_process, we used cmd /c
and listed the files separated by a &
as the argument.
接下来,我能够调整 Fraser 的 CMake 文件以在 Linux 上构建,但是在bootstrap.bat
使用 CMake 的 execute_process 命令在 Windows 上运行该文件时遇到了问题。要运行 bootstrap.bat,我们首先需要运行相关的 Visual Studiovcvarsall.bat
脚本来设置环境变量(我们可能会弄清楚需要设置哪些单独的变量,但运行整个脚本会更容易)。要使用 execult_process 在同一个 shell 中运行两个 .bat 文件,我们使用cmd /c
并列出了由 a 分隔的文件&
作为参数。
Also bootstrap.bat
did not set the exit code to non-zero in case of failure, so using the execute_process RESULT_VARIABLE to check for success didn't work. Instead we checked that the b2.exe executable had been created after the command was run.
也bootstrap.bat
没有在失败的情况下将退出代码设置为非零,因此使用 execute_process RESULT_VARIABLE 来检查是否成功不起作用。相反,我们检查了 b2.exe 可执行文件是否在命令运行后创建。
One last issue: bootstrap.sh
supports the --prefix=
option, which bootstrap.bat
does not. I also found that specifying the --prefix
option for b2.exe
on windows worked, but
using the --prefix
option for b2
on Linux, without specifying it for bootstrap.sh
gave errors. (I haven't understood why yet).
最后一个问题:bootstrap.sh
支持--prefix=
选项,但bootstrap.bat
不支持。我还发现在 Windows 上指定--prefix
选项b2.exe
有效,但在 Linux 上使用--prefix
选项b2
,而没有指定它bootstrap.sh
给出了错误。(我还不明白为什么)。
So the relevant part of our CMake file looks like:
所以我们的 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()
In the above APT_BOOST_SRC
is the location of the Boost subdirectory in our source directory, APT_BOOST_BIN
is the location we use to store the libraries in our CMake build directory, and APT_BOOST_COMPONENTS
is a list of the Boost libraries we are using.
上面APT_BOOST_SRC
是 Boost 子目录在我们的源目录APT_BOOST_BIN
中的位置,是我们用来在我们的 CMake 构建目录中存储库的位置,是APT_BOOST_COMPONENTS
我们正在使用的 Boost 库的列表。