CMake 笔记 | [40] 超级构建模式
一、导言
每个项目都需要处理依赖关系,使用**CMake很容易查询这些依赖关系,是否存在于配置项目中。前面的笔记中,展示了如何找到安装在系统上的依赖项,到目前为止我们一直使用这种模式。但是,当不满足依赖关系,我们只能使配置失败,并向用户警告失败的原因。然而,使用CMake可以组织我们的项目,如果在系统上找不到依赖项,就可以自动获取和构建依赖项。后续的几篇笔记将介绍和分析ExternalProject.cmake和FetchContent.cmake标准模块,及在超级构建模式中的使用。前者允许在构建时检索项目的依赖项,后者允许我们在配置时检索依赖项(CMake的3.11版本后添加)。使用超级构建模式,我们可以利用CMake作为包管理器:相同的项目中,将以相同的方式处理依赖项,无论依赖项在系统上是已经可用,还是需要重新构建。**
首先通过一个简单示例,介绍超级构建模式。我们将展示如何使用**ExternalProject_Add命令来构建一个的hello_world程序。**
二、项目结构
| |
项目结构:
https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter8/01
三、相关源码
src/CMakeLists.txt
| |
src/hello_world.cpp
| |
CMakeLists.txt
| |
| |
为当前目录和底层目录设置EP_BASE目录属性。
| |
包括ExternalProject.cmake标准模块。该模块提供了ExternalProject_Add函数。
| |
Hello, World源代码通过调用ExternalProject_Add函数作为外部项目添加的。外部项目的名称为example_core。
ExternalProject_Add命令可用于添加第三方源。本篇通过将自己的项目,分为不同CMake项目的集合管理。本例中,主CMakeLists.txt和子CMakeLists.txt都声明了一个CMake项目,它们都使用了project命令。
ExternalProject_Add有许多选项,可用于外部项目的配置和编译等所有方面。这些选择可以分为以下几类:
Directory:用于调优源码的结构,并为外部项目构建目录。本篇,我们使用
SOURCE_DIR选项让CMake知道源文件在${CMAKE_CURRENT_LIST_DIR}/src文件夹中。用于构建项目和存储临时文件的目录,也可以在此类选项或目录属性中指定。通过设置EP_BASE目录属性,CMake将按照以下布局为各个子项目设置所有目录:1 2 3 4 5 6TMP_DIR = <EP_BASE>/tmp/<name> STAMP_DIR = <EP_BASE>/Stamp/<name> DOWNLOAD_DIR = <EP_BASE>/Download/<name> SOURCE_DIR = <EP_BASE>/Source/<name> BINARY_DIR = <EP_BASE>/Build/<name> INSTALL_DIR = <EP_BASE>/Install/<name>Download:外部项目的代码可能需要从在线存储库或资源处下载。
Update和Patch:可用于定义如何更新外部项目的源代码或如何应用补丁。
Configure:默认情况下,
CMake会假定外部项目是使用CMake配置的。如下所示,我们并不局限于这种情况。如果外部项目是CMake项目,ExternalProject_Add将调用CMake可执行文件,并传递选项。对于本篇示例,我们通过CMAKE_ARGS和CMAKE_CACHE_ARGS选项传递配置参数。前者作为命令行参数直接传递,而后者通过CMake脚本文件传递。实际,脚本文件位于build/subprojects/tmp/example_core/example_core- cache-.cmake。然后,配置如以下所示:1 2 3 4 5 6 7 8 9 10 11loading initial cache file /home/jiangli/repo/tutorials/cmake-tutorial/chapter8/01/build/subprojects/tmp/example_core/example_core-cache-.cmake -- The CXX compiler identification is GNU 9.4.0 -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /home/jiangli/repo/tutorials/cmake-tutorial/chapter8/01/build/subprojects/Build/example_coreBuild:可用于调整外部项目的实际编译。我们使用
BUILD_ALWAYS选项确保外部项目总会重新构建。Install:这些选项用于配置应该如何安装外部项目。我们将
INSTALL_COMMAND保留为空。Test:为基于源代码构建的软件运行测试。
ExternalProject_Add的这类选项可以用于此目的。我们的没有使用这些选项,因为Hello, World示例没有任何测试。
四、结果展示
| |
构建目录的结构稍微复杂一些,subprojects文件夹的内容如下:
| |
补充内容
ExternalProject.cmake定义了ExternalProject_Get_Property命令,该命令对于检索外部项目的属性非常有用。外部项目的属性是在首次调用ExternalProject_Add命令时设置的。例如,在配置example_core时,检索要传递给CMake的参数可以通过以下方法实现:
| |
ExternalProject.cmake模块定义了以下附加命令:
ExternalProject_Add_Step: 当添加了外部项目,此命令允许将附加的命令作为自定义步骤锁定在其上。ExternalProject_Add_StepTargets:允许将外部项目中的步骤(例如:构建和测试步骤)定义为单独的目标。这意味着可以从完整的外部项目中单独触发这些步骤,并允许对项目中的复杂依赖项,进行细粒度控制。ExternalProject_Add_StepDependencies:外部项目的步骤有时可能依赖于外部目标,而这个命令的设计目的就是处理这些情况。
支付宝
微信