<<Modern CMake>> 翻译 2.2 CMake 编程
<<Modern CMake>> 翻译 2.2 CMake 编程
流程控制
CMake有一个 if
语句, 经年累月之后,现在它已经相当复杂。 您可以在 if
语句中使用全大写字母书写一系列关键字,并且您通常可以直接通过名称(if语句在历史上出现早于变量扩展)或使用 ${}
语法来引用变量。 下面是 if
语句的示例:
if(variable)
# If variable is `ON`, `YES`, `TRUE`, `Y`, or non zero number
else()
# If variable is `0`, `OFF`, `NO`, `FALSE`, `N`, `IGNORE`, `NOTFOUND`, `""`, or ends in `-NOTFOUND`
endif()
# If variable does not expand to one of the above, CMake will expand it then try again
如果您明确地进行变量扩展(例如 ${variable}
,由于扩展的潜在扩展),这可能会有点混乱。 在CMake 3.1+ 中添加了一个策略(CMP0054),使得被引号引起来的变量扩展不被递归扩展。 因此,只要 CMake 的最低版本是 3.1+,您就可以:
if("${variable}")
# True if variable is not false-like
else()
# Note that undefined variables would be `""` thus false
endif()
这里还有一些可以在 if
命令中使用的关键字,例如:
- 一元关键字:
NOT
,TARGET
,EXISTS
(文件),DEFINED
, 等等 - 二元关键字:
STREQUAL
,AND
,OR
,MATCHES
(正则表达式),VERSION_LESS
,VERSION_LESS_EQUAL
(CMake 3.7+), 等等 - 括号可以用于分组
生成器表达式 (Generator-expressions)
Generator-expressions 非常强大,但也有点奇怪和专业。 大多数 CMake 命令在配置时运行,包括上面看到的 if
语句。 但是如果你需要在构建时甚至安装时间执行逻辑呢? 为了这个目的 CMake 添加了生成器表达式(Generator-expressions)。1 它们在目标属性中进行计算和执行。
最简单的生成器表达式是信息表达式,具有这样 $<KEYWORD>
的形式; 他们评估(计算和执行)一条与当前配置相关的信息。 另一种形式是 $<KEYWORD:value>
,KEYWORD 关键字控制评估,value
是要评估的项目(这里也允许使用信息表达式关键字)。 如果 KEYWORD
是一个计算结果为 0 或 1 的生成器表达式或变量,value
则替换为 0 或 1。 您可以嵌套生成器表达式,并且可以使用变量来使嵌套变量可读。 某些表达式允许使用逗号分隔的多个值。2
例如,如果你想要设置仅在 DEBUG
配置下生效的编译标志,则可以这样写:
target_compile_options(MyTarget PRIVATE "$<$<CONFIG:Debug>:--my-flag>")
这是一种比使用专用 *_DEBUG
变量更新,更好的方式,并且可以推广到生成器表达式支持的所有情况。 请注意,您永远不应该使用配置时的值作为当前配置,因为 IDE 之类的多配置生成器并没有“当前”配置,仅在构建时通过生成器表达式和自定义的 *_<CONFIG>
变量起作用。
生成器表达式的其他常见用法:
- 将项目限制为仅限某种语言(例如 CXX),以避免它与 CUDA 等混在一起,或者根据目标语言将其包装以使其不同。
- 访问配置相关属性,例如目标文件位置。
- 为构建和安装目录提供不同的位置。
最后一个很常见。几乎每个支持安装的软件包都会看到类似的内容:
target_include_directories(
MyTarget
PUBLIC
$<BUILD_INTERFACE:"${CMAKE_CURRENT_SOURCE_DIR}/include">
$<INSTALL_INTERFACE:include>
)
1. 它们就像在构建/安装时评估它们一样,但实际上它们是针对每个构建配置分别进行评估的。↩
2. CMake 文档将表达式拆分为信息,逻辑和输出。↩
宏和函数
你可以方便的定义你自己的 CMake 函数 function
和宏 macro
。 函数和宏之间的唯一区别是作用范围:宏没有作用范围。 因此,如果您在函数中设置了变量并希望它在外部可见,那么您将需要用 PARENT_SCOPE
。 由于您必须在每个函数中明确用 PARENT_SCOPE
设置您希望外部世界可见的变量,嵌套函数有点儿烦。 但是,函数不会像宏一样 “泄漏” 变量。 在以下示例中,我将使用函数。
一个简单使用函数的例子如下:
function(SIMPLE REQUIRED_ARG)
message(STATUS "Simple arguments: ${REQUIRED_ARG}, followed by ${ARGV}")
set(${REQUIRED_ARG} "From SIMPLE" PARENT_SCOPE)
endfunction()
simple(This)
message("Output: ${This}")
如果你想用位置参数,它们需要明确列出,并且所有其他参数都被放在 ARGN
中(ARGV
中保存有所有参数,甚至那些你已经列出的参数)。 您只能通过设置变量来解决 CMake 中函数没有返回值的问题。 在上面的示例中,您可以显式指定要设置的变量名称。
参数
你已经在 CMake 函数的大部分使用中看到,CMake 有一个命名变量系统。 您可以将它与 cmake_parse_arguments
函数一起使用。 如果要支持 3.5 以下的 CMake 版本,您还需要包含 CMakeParseArguments 模块,该模块在成为内置命令之前就已存在。
以下是如何使用它的示例:
function(COMPLEX)
cmake_parse_arguments(
COMPLEX_PREFIX
"SINGLE;ANOTHER"
"ONE_VALUE;ALSO_ONE_VALUE"
"MULTI_VALUES"
${ARGN}
)
endfunction()
complex(SINGLE ONE_VALUE value MULTI_VALUES some other values)
在此调用 cmake_parse_arguments
函数后,在 complex
函数内部,给我们产生了这些变量:
COMPLEX_PREFIX_SINGLE = TRUE
COMPLEX_PREFIX_ANOTHER = FALSE
COMPLEX_PREFIX_ONE_VALUE = "value"
COMPLEX_PREFIX_ALSO_ONE_VALUE = <UNDEFINED>
COMPLEX_PREFIX_MULTI_VALUES = "some;other;values"
如果你查看官方页面,你会看到一个稍微不同的使用 set
的方法避免在列表中明确写分号的方法; 随意使用您最喜欢的结构。 您也可以将它与上面列出的位置参数混合使用; 任何剩余的参数(包括可选的位置参数)都会保存在 COMPLEX_PREFIX_UNPARSED_ARGUMENTS
中。
<<Modern CMake>> 翻译 2.2 CMake 编程的更多相关文章
- <<Modern CMake>> 翻译 2. CMake 基础
<<Modern CMake>> 翻译 2. CMake 基础 最低版本 这是每个 CMakeLists.txt 文件的第一行.CMakeLists.txt 是 CMake 所 ...
- <<Modern CMake>> 翻译 1. CMake 介绍
<<Modern CMake>> 翻译 1. CMake 介绍 人们喜欢讨厌构建系统. 仅仅观看 CppCon17 上的演讲,就可以看到开发人员因为构建系统而闹笑话的例子. 这 ...
- <<Modern CMake>> 翻译 2.3 与代码通信
<<Modern CMake>> 翻译 2.3 与代码通信 配置文件 CMake 允许您使用代码通过 configure_file 存取 CMake 变量. 此命令复制一个文件 ...
- <<Modern CMake>> 翻译 2.4 项目目录结构
<<Modern CMake>> 翻译 2.4 项目目录结构 本节内容有点跑题.但我认为这是一个很好的方法. 我将告诉你如何规划项目的目录. 这是基于惯例,但将帮助您: 轻松阅 ...
- Effective Modern C++翻译(1):序言
/*********************************************************** 关于书: 书是我从网上找到的effective Modern C++的样章,内 ...
- mysql配置文件夹错误:在安装mysql 5.6.19 时运行cmake命令是出现CMake Error: The source directory does not appear to contai
在安装mysql 5.5.xx 时运行cmake命令是出现CMake Error: The source directory does not appear to contain CMakeLists ...
- cmake之譬判断cmake的版本
note 有时候,可能使用的cmake语法 与cmake的版本有关系, 比如modern cmake. 这时候我们可以在 CMAKELISTS.TXT中 判断 cmakeLists.txt 代码 if ...
- 源码安装cmake(或者叫升级cmake)
cmake source install as follows: 0 cd ~ 1 wget https://cmake.org/files/v3.5/cmake-3.5.2.tar.gz 2 tar ...
- [书籍翻译] 《JavaScript并发编程》第一章 JavaScript并发简介
> 本文是我翻译<JavaScript Concurrency>书籍的第一章,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript并 ...
随机推荐
- API 文档管理工具 (Yapi) Docker Compose部署指南
前言介绍 Yapi 由 YMFE 开源,旨在为开发.产品.测试人员提供更优雅的接口管理服务,可以帮助开发者轻松创建.发布.维护 API. 权限管理 YApi 成熟的团队管理扁平化项目权限配置满足各类企 ...
- spring 5.x 系列第20篇 ——spring简单邮件、附件邮件、内嵌资源邮件、模板邮件发送 (代码配置方式)
源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.说明 1.1 项目结构说明 邮件发送配置类为com.heibaiyin ...
- node实现文件拷贝2
https://www.cnblogs.com/coding4/p/7495968.html 文件拷贝NodeJS 提供了基本的文件操作 API,但是像文件拷贝这种高级功能就没有提供,因此我们先拿文件 ...
- mvc中的表现和数据分离怎么理解?
使用过 JavaScript框架(如 AngularJS, Backbone)的人都很熟悉在UI(用户界面,前端)中mvc的工作机理.这些框架实现了MVC,使得在一个单页面中实现根据需要变化视图时更加 ...
- CentOS7系统安装
CenOS7安装系统 镜像下载地址: http://isoredirect.centos.org/centos/7/isos/x86_64/ https://mirrors.aliyun.com/ce ...
- Linux文件系统目录结构详解
在我们初学嵌入式Linux时,首先学习的就是Linux的最小根文件系统:下面我将为初学者们详细的阐述一下Linux的最小根文件系统. 根目录在Linux中即为“/”,要进入根目录,命令“cd /”即 ...
- Google play中下载apk
在 Google play中下载apk:先在Google play中找到该apk,再去找APK downloader(https://www.allfreeapk.com/),Google play的 ...
- Codeforces Gym101505G:Orchard Division(扫描线+线段树第k大)
题目链接 题意 给出一个m*m的地图,上面有n个点,现在需要用一个自定义面积的矩形笼罩住恰好n/2个点,并且这个矩形需要有一个点在至少一个角落上,问这个矩形最小的面积是多少. 思路 有点类似于扫描线. ...
- Windows使用Python统一设置解析器路径
碰到的问题: .py文件放在cgi-bin文件夹下面,这个.py文件都要设置"#!python.exe路径"来告诉CGI如何找解析器解析这个.py的文件,我是想知道这个路径可否统一 ...
- iOS自动化探索(十)代码覆盖率统计
iOS APP代码覆盖率统计 今年Q3季度领导给加了个任务要做前后端代码覆盖率统计, 鉴于对iOS代码代码比较熟就选择先从iOS端入手,折腾一整天后终于初步把流程跑通了记录如下 覆盖率监测的原理 Xc ...