8.5 使用超级构建支持项目
NOTE:此示例代码可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-8/recipe-05 中找到,其中有一个C++示例。该示例在CMake 3.5版(或更高版本)中是有效的,并且已经在GNU/Linux、macOS和Windows上进行过测试。
ExternalProject和FetchContent是CMake库中两个非常强大的工具。经过前面的示例,我们应该相信超级构建方法,在管理复杂依赖关系的项目时是多么有用。目前为止,我们已经展示了如何使用ExternalProject来处理以下问题:
存储在源树中的源
从在线服务器上,检索/获取可用的存档资源
前面的示例展示了,如何使用FetchContent处理开源Git存储库中可用的依赖项。本示例将展示,如何使用ExternalProject达到同样的效果。最后,将介绍一个示例,该示例将在第10章第4节中重用。
准备工作
这个超级构建的源代码树现在应该很熟悉了:
.
├── CMakeLists.txt
├── external
│ └── upstream
│ ├── CMakeLists.txt
│ └── message
│ └── CMakeLists.txt
└── src
├── CMakeLists.txt
└── use_message.cpp根目录有一个CMakeLists.txt,我们知道它会配合超级构建。子目录src和external中是我们自己的源代码,CMake指令需要满足对消息库的依赖,我们将在本例中构建消息库。
具体实施
目前为止,建立超级构建的过程应该已经很熟悉了。让我们再次看看必要的步骤,从根目录的CMakeLists.txt开始:
声明一个C++11项目,并对项目构建类型的默认值进行设置。
设置
EP_BASE目录属性。这将固定ExternalProject管理所有子项目的布局:我们设置了
STAGED_INSTALL_PREFIX。与之前一样,这个位置将作为依赖项的构建树中的安装目录:将
external/upstream作为子目录添加:添加
ExternalProject_Add,这样我们的项目也将由超级构建管理:
external/upstream的CMakeLists.txt中只包含一条命令:
跳转到message文件夹,我们会看到对消息库的依赖的常用命令:
首先,调用
find_package找到一个合适版本的库:如果找到,会通知用户,并添加一个虚拟
INTERFACE库:如果没有找到,再次通知用户并继续使用
ExternalProject_Add:该项目托管在一个公共Git库中,使用
GIT_TAG选项指定下载哪个分支。和之前一样,将UPDATE_COMMAND选项置为空:外部项目使用CMake配置和构建,传递必要的构建选项:
项目安装后进行测试:
我们不希望看到下载进度,也不希望在屏幕上报告配置、构建和安装信息,所以选择关闭
ExternalProject_Add:为了确保子项目在超级构建的其余部分中是可见的,我们设置了
message_DIR目录:
最后,来看一下src目录上的CMakeLists.txt:
同样,声明一个C++11项目:
项目需要消息库:
声明一个可执行目标,并将其链接到消息动态库:
工作原理
示例展示了ExternalProject_Add的一些新选项:
GIT_REPOSITORY:这可以用来指定包含依赖项源的存储库的URL。CMake还可以使用其他版本控制系统,比如CVS (CVS_REPOSITORY)、SVN (SVN_REPOSITORY)或Mercurial (HG_REPOSITORY)。
GIT_TAG:默认情况下,CMake将检出给定存储库的默认分支。然而,最好依赖于一个稳定的版本。这可以通过这个选项指定,它可以接受Git将任何标识符识别为“版本”信息,例如:Git提交SHA、Git标记或分支名称。CMake所理解的其他版本控制系统也可以使用类似的选项。
TEST_AFTER_INSTALL:依赖项很可能有自己的测试套件,您可能希望运行测试套件,以确保在超级构建期间一切顺利。此选项将在安装步骤之后立即运行测试。
ExternalProject_Add可以理解的其他测试选项如下:
TEST_BEFORE_INSTALL:将在安装步骤之前运行测试套件
TEST_EXCLUDE_FROM_MAIN:可以从测试套件中,删除对外部项目的主要目标的依赖
这些选项都假定外部项目使用CTest管理测试。如果外部项目不使用CTest来管理测试,我们可以通过TEST_COMMAND选项来执行测试。
即使是为属于自己项目的模块引入超级构建模式,也需要引入额外的层,重新声明小型CMake项目,并通过ExternalProject_Add显式地传递配置设置。引入这个附加层的好处是,清晰地分离了变量和目标范围,这可以帮助管理由多个组件组成的项目中的复杂性、依赖性和名称空间,这些组件可以是内部的,也可以是外部的,并由CMake组合在一起。
Last updated
Was this helpful?