CMake应用:生成器表达式

2023-11-12

目录

  • 一 概述

  • 二 常用的生成器表达式

    • 1 布尔生成器表达式

    • 2 字符串值生成器表达式

    • 3 调试

CMake的生成器表达式不算是特别常用,但是有一些场景可能是必须要使用的;或者在针对不同编译类型设置不同编译参数的时候可以巧妙应用,从而减少配置代码。

生成器表达式听起来稍微有点复杂,但是其实只需要掌握一些常用的功能就能够有所裨益,至于更加复杂的写法,在需要的时候研究一下即可。本文主要介绍下生成器表达式的概念、种类、和常用的一些生成器表达式。

一 概述

生成器表达式简单来说就是在CMake生成构建系统的时候根据不同配置动态生成特定的内容。比如:

  1. 条件链接,如针对同一个编译目标,debug版本和release版本链接不同的库文件

  2. 条件定义,如针对不同编译器,定义不同的宏

所以可以看到,其中的要点是条件,之所以需要自动生成,那绝大多数时候肯定是因为开发者无法提前确定某些配置,不能提前确定那往往就是有条件的。

生成器表达式的格式形如$<...>,可以嵌套,可以用在很多构建目标的属性设置和特定的CMake命令中。值得强调的是,生成表达式被展开是在生成构建系统的时候,所以不能通过解析配置CMakeLists.txt阶段的message命令打印,文末会介绍其调试方法。

二 常用的生成器表达式

1 布尔生成器表达式

逻辑运算符

逻辑运算很多语言都是需要的,CMake生成器表达式中有这些:

  1. $<BOOL:string>:如果字符串为空、0;不区分大小写的FALSEOFFNNOIGNORENOTFOUND;或者区分大小写以-NOTFOUND结尾的字符串,则为0,否则为1

  2. $<AND:conditions>:逻辑与,conditons是以逗号分割的条件列表

  3. $<OR:conditions>:逻辑或,conditons是以逗号分割的条件列表

  4. $<NOT:condition>:逻辑非

一般来说,条件是列表的,都是使用逗号进行分割,后面不再赘述。

字符串比较

  1. $<STREQUAL:string1,string2>:判断字符串是否相等

  2. $<EQUAL:value1,value2>:判断数值是否相等

  3. $<IN_LIST:string,list>:判断string是否包含在list中,list使用分号分割

注意这里的list是在逗号后面的列表,所以其内容需要使用分号分割。

变量查询

这个会是比较常用的,在实际使用的时候会根据不同CMake内置变量生成不同配置,核心就在于“判断”:

  1. $<TARGET_EXISTS:target>:判断目标是否存在

  2. $<CONFIG:cfgs>:判断编译类型配置是否包含在cfgs列表(比如"release,debug")中;不区分大小写

  3. $<PLATFORM_ID:platform_ids>:判断CMake定义的平台ID是否包含在platform_ids列表中

  4. $<COMPILE_LANGUAGE:languages>:判断编译语言是否包含在languages列表中

2 字符串值生成器表达式

请注意,前面都是铺垫,这里才是使用生成器表达式的主要目的:生成特定的字符串。比如官方的例子:基于编译器ID指定include目录:

include_directories(/usr/include/$<CXX_COMPILER_ID>/)

根据编译器的类型,$<CXX_COMPILER_ID>会被替换成对应的ID(比如“GNU”、“Clang”)。

条件表达式

这便是本文的核心了,主要有两个格式:

  1. $<condition:true_string>:如果条件为真,则结果为true_string,否则为空

  2. $<IF:condition,str1,str2>:如果条件为真,则结果为str1,否则为str2

这里的条件一般情况下就是前面介绍的布尔生成器表达式。比如要根据编译类型指定不同的编译选项,可以像下面这样:

set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")

但是使用生成器表达式可以简化成:

add_compile_options("$<$<CONFIG:Debug>:-g;-O0>")
add_compile_options($<$<CONFIG:Debug>:-O2>)

如果需要指定多个编译选项,必须使用双引号把生成器表达式包含起来,且选项之间使用分号。

后面这个方法适用于设置一些对所有编译器(取决于项目编译语言)都通用的编译选项,而需要设置一些编译器特有的选项时,通过设置指定编译器的编译选项(前一种方法)更加简洁明了。

当然,可以用表达式判断编译器ID设置不同编译选项,不过明显有些为了用而用,这是没必要的。

转义字符

这比较好理解,因为有一些字符有特殊含义,所以可能需要转义,比如常用的$<COMMA>$<SEMICOLON>,分别表示,;

字符串操作

常用的有$<LOWER_CASE:string>$<UPPER_CASE:string>用于转换大小写。

获取变量值

获取变量的值和前文提到的变量查询很类似,前面说的变量查询是判断是否存在于指定列表中或者等于指定值。语法格式是类似的,以CONFIG为例:

  1. 获取变量值:$<CONFIG>

  2. 判断是否存在于列表中:$<CONFIG:cfgs>

详见Variable Queries:https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#id2。

编译目标查询

这里的查询是指获取编译目标(通过add_executable()add_library()命令生成的)相关的一些信息,包括:

  1. $<TARGET_FILE:tgt>:获取编译目标的文件路径

  2. $<TARGET_FILE_NAME:tgt>:获取编译目标的文件名

  3. $<TARGET_FILE_BASE_NAME:tgt>:获取编译目标的基础名字,也就是文件名去掉前缀和扩展名

官网有更多详细介绍,有其他需要可以阅读:target-dependent-queries:https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#target-dependent-queries。

在本专题前一篇文章中介绍合并静态库的时候,就用到$<TARGET_FILE:tgt>去获取静态库的路径。

3 调试

调试可以通过输出到文件的方式,在cmake执行完之后去检查是否符合预期,比如:

file(GENERATE OUTPUT "./generator_test.txt" CONTENT "$<$<CONFIG:Debug>:-g;-O0>,$<PLATFORM_ID>\n")

在MacOS中执行cmake,得到的结果如下:

# cmake -B cmake-build -DCMAKE_BUILD_TYPE=Debug
...
# cat cmake-build/generator_test.txt
-g;-O0,Darwin

如果不想写文件,也可以添加一个自定义目标,比如:

add_custom_target(gentest COMMAND ${CMAKE_COMMAND} -E echo "\"$<$<CONFIG:Debug>:-g;-O0>,$<PLATFORM_ID>\"")

注意这里需要双引号转义,确保生成器表达式展开之后是字符串。

在执行cmake之后,可以使用make gentest输出到生成器表达式的内容:

# cd cmake-build && make gentest
-g;-O0,Darwin
Built target gentest

欧克,结了!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CMake应用:生成器表达式 的相关文章

  • 如何使用 --build 选项查看 cmake 发出的命令

    当我运行 cmake build target INSTALL 命令时 如何查看发出的命令 似乎没有像 versbose之类的选项 cmake 帮助说 cmake build 是底层构建工具的接口 但没有说明有关发出的命令转储的任何内容 我
  • cmake 找不到 Qt4

    由于4 8 0已经发布 我重新安装了Qt 现在我也想使用cmake 为了使 cmake 工作 我记得必须添加 mingw bin 文件夹 QtSDK Desktop Qt 4 7 3 到Qt4 7 3中的PATH 所以我猜测在中会有一个类似
  • 使用 Objective-C 将 XMP 数据嵌入到 PNG

    我需要将自定义 XMP 文件嵌入到 iOS 应用程序中的 PNG 中 到目前为止 我能做的就是编译 Adob e XMP 工具包 生成 Xcode 项目 然后正确编译该项目 从那里我不知道如何在我的 Xcode 项目中使用该库以及如何使用它
  • cmake 包括其他目录中的 h 文件

    我在 cmake 项目下进行测试时遇到问题 我的项目是这样安排的 TerrainMap PointAccumulator heightQuadGrid Test 在 TerrainMap 目录中 CMakeLists txt 文件简单地概述
  • 在生成器表达式中使用 cmake 选项

    我想在生成器表达式中使用 cmake 选项 为了打开某个编译标志 来自文档 https cmake org cmake help v3 10 manual cmake generator expressions 7 html我不清楚如何实现
  • 在cmake中设置PKG_CONFIG_PATH

    我已经在本地构建了 opencv 并将其安装到本地目录 不是系统默认目录 opencv pc存在于该本地文件夹中的 pkgconfig 文件夹下 我怎样才能找到这个opencv pc来自 cmake 因为我想从我的程序链接并包含 openc
  • Cmake:将子项目目标导出到主项目

    我目前有一个项目叫做LIBS具有这样的结构 Lib1 CMakeLists txt lib1 class cpp lib1 class h lib2 CMakeLists txt lib2 class cpp lib2 class h cm
  • 在cmake中集成bash测试脚本

    我有一个 C cmake 项目 它使用 Boost Test 进行单元测试 现在我想向 cmake 公开一系列 bash 脚本 用于集成测试 假设每个脚本在以下情况下返回 0PASS或某些情况下 0FAILURE 我希望每次运行时都执行每个
  • 将 Doctest 与代码一起使用时将实现放在哪里

    我在用着doctest https github com onqtam doctest用于我的 C 项目中的测试 我想将测试代码与我的实现放在一起 正如库所说是可能的 但我似乎不知道如何处理 doctest 实现代码 我有一个doctest
  • 将 dll/lib 链接到 cmake 项目

    我试图将库链接到我的 cmake 项目 但遇到链接器错误 我花了 2 个小时尝试解决这个问题 并创建了一个简单的项目 在其中对所有路径进行了硬编码 CMAKE MINIMUM REQUIRED VERSION 3 0 PROJECT Tes
  • Yocto 如何停止 cmake 在本机 sysroot 路径中查找链接?

    到目前为止 我正在尝试将 dlib python 模块添加到我的图像中 这是我正在研究的食谱 python3 dlib 19 21 1 bb SUMMARY A toolkit for making real world machine l
  • Cmake选项默认值

    如果我有一个 CMakeLists txt 文件 cmake minimum required VERSION 2 8 OPTION FOO Foo Option OFF MESSAGE FOO FOO 然后我调用 cmake 得到以下输出
  • 带包装的 CMAKE RPATH

    我正在使用 cmake 创建包 我有以下结构 bin bin1 lib lib1 lib2 其中lib1和lib2是外部动态库 如何设置 RPATH 以便它自动与 lib1 和 lib2 链接 我也在这方面对 cmake 很感兴趣 Cmak
  • 在 CMake 中使用 GLOB 指定源文件还是单独指定每个文件更好?

    CMake 提供了多种方法来指定目标的源文件 一种是使用通配符 文档 https cmake org cmake help latest command file html 例如 FILE GLOB MY SRCS dir 另一种方法是单独
  • 在 PowerShell 中提取 EXIF 数据的简单方法?

    我一直在研究使用 PowerShell 提取 EXIF 数据的各种方法 但到目前为止我发现它相当复杂 一些here http blog cincura net 233463 renaming files based on exif data
  • CMake、Exe找不到DLL

    所以我尝试在 Windows 上使用 cmake 设置一个项目 这就是我的项目结构 游戏引擎 git build include source testing CMakeLists txt 这个想法是 source 目录包含 GameEng
  • 使用 CMake 编译时更改头文件位置会导致缺少 vtable 错误

    对于一个大型 C 项目 我需要从 qmake 过渡到 CMake 但是在处理一个玩具示例时 我遇到了一些我不理解的行为 示例代码具有单个头文件 当该头文件移动到子目录中时 我收到 MainWindow 类缺少 vtable 的错误 CMak
  • 如何使用cmake自动构建第三方库

    我在寻找什么 下载库 提取它 应用自定义补丁 运行配置 运行构建命令 我正在尝试构建的库是 Openssl Boost Thrift C ares Curl Pcre Nginx ICU JsonCPP 我想我可以使用外部模块做这些事情 h
  • CMake source_group() 无法在分层项目设置中正常工作

    在进行更改以使 CMake 项目具有分层文件夹管理后 source group 似乎不再正常工作 CMake 只是将所有内容转储到默认过滤器中 我尝试了各种正则表达式来从父级获取每个源文件的相对文件路径 甚至对父级 CMakeLists t
  • CMake:Fortran 模块和编译顺序

    我有一个大型 Fortran 程序 其中包含许多目录 每个目录都在伪库中单独编译 但仍然存在相互依赖的混乱 因此最终所有伪库都组合在一个可用的库中 我想使用 Fortran 模块 但它非常脆弱 因为我不能依赖自动依赖项检查 并且根据顺序编译

随机推荐

  • 判断字符串是否为回文串的Java实现方法(收藏自力扣)

    先把字符串转成字符数组 可以调用toCharArray 方法 public char toCharArray 将此字符串转换为一个新的字符数组 Returns 一种新分配的字符数组 其长度是该字符串的长度 其内容被初始化为包含由该字符串表示
  • 时间序列模型Prophet使用详细讲解

    之前我们已经讲过了如何在Windows系统下安装Python版本的Prophet 详细见这里 接下来的几个部分 我们说下如何使用Prophet 以此来体验下Prophet的丰富内容 内容会比较多 主要翻译自官方文档 教程中使用的数据集可在
  • DAP数据分析平台权限体系说明

    数据对于企业来说是非常重要的 所以产品的安全性需要有所保证 而权限分配就是一种保障方式 通过不同权限查看到不同的数据进行数据隔离 保障数据的安全性 DAP数据分析平台通过授权管理进行角色授权 配置授权 业务授权实现三权分立 不同的用户能看到
  • 后端解决跨域

    对于跨域 相信同学们都有所了解 前端的跨域的若干种方式 大家也都知道 什么 JSONP iframe domain 等等 但是我们今天的主题 不是前端跨域 而是后端跨域 一旦提及到跨域 就会想到同源策略 那我们就先来回顾跨域和同源策略 什么
  • upload-labs第五关 pass-05 大小写绕过

    六 pass 05 大小写绕过 源码 is upload false msg null if isset POST submit if file exists UPLOAD ADDR deny ext array php php5 php4
  • 封装浏览器外壳

    Net本身包含WebBrower控件 可惜内核是IE http www cnblogs com M Silencer p 5846494 html 参考以上文章 通过一些控件可以再窗体中嵌入webkit内核的浏览器 目前在尝试CefShar
  • 快手广告推广效果由哪些因素决定?快手广告能满足哪些推广目标?

    快手广告用户与你的行业用户一致快手用户为三线城市 95后年轻用户为主 同时其用户人群也在大城市进行渗透 那么快手广告推广效果由哪些因素决定 快手广告能满足哪些推广目标 一 快手广告推广效果由哪些因素决定 1 广告的推广效果可以分为曝光效果
  • 大数据代表技术:Hadoop、Spark、Flink、Beam

    大数据代表技术 Hadoop Spark Flink Beam Hadoop 从2005年到2015年 说到大数据都是讲hadoop Hadoop是一整套的技术框架 不是一个单一软件 它是一个生态系统 Hadoop有两大核心 第一个是它解决
  • ubuntu系统安装pangolin

    ubuntu 安装 pangolin 1 安装pangolin依赖项以及安装过程中用到的工具 2 创建安装目录 3 下载pangolin源文件 4 安装pangolin 1 安装pangolin依赖项以及安装过程中用到的工具 ctrl al
  • LeetCode_BinaryTree_1129. Shortest Path with Alternating Colors 颜色交替的最短路径【BFS求最短路径】【java】【中等】

    一 题目描述 英文描述 You are given an integer n the number of nodes in a directed graph where the nodes are labeled from 0 to n 1
  • Vue面试题(一)

    目录 一 vue2和vue3的区别 二 mixin混入对象 三 hooks 特点 四 keep alive 五 生命周期 六 el template render 七 vue router 有哪几种导航钩子 路由守卫 八 HTTP和TCP的
  • CVPR‘2023 即插即用系列!

    Title BiFormer Vision Transformer with Bi Level Routing Attention Paper https arxiv org pdf 2303 08810 pdf Code https gi
  • 电商入门_仓库管理系统wms

    在2010电商WMS第一个阶段 那时的双十一就是各个仓库的噩梦 库区不够用 WMS系统瘫痪 拣货人员都被埋在商品里 往往半个月之后才能发出订单 那时京东的亚洲一号仓刚开始立项 大家还半信半疑 大部分电商库房后台还是处于小作坊状况 纯粹靠人工
  • react动态给组件添加事件_React实战—组件行为:React中的事件(4)

    网页是组件构成的 组件是一系列标签形成的单一功能 所以考虑组件无非也就三件事 结构 表现 和行为 结构JSX搞定了 当然JSX不仅仅干这个 表现是CSS的事儿 我们重点说下行为 也就是事件和钩子 事件好说 就是户干了啥事儿 然后有什么样的相
  • Fiddler / Charles - 夜神模拟器证书安装App抓包

    Fiddler Charles 夜神模拟器证书安装App抓包 文章目录 Fiddler Charles 夜神模拟器证书安装App抓包 前言 一 软件安装 1 Openssl安装 1 1下载安装 1 2配置环境变量 1 3查看openssl版
  • 基于AWS的云服务架构最佳实践 #CSDN博文精选# #IT# #云服务实践#

    大家好 小C将继续与你们见面 带来精选的CSDN博文 在这里 你将收获 将系统化学习理论运用于实践 系统学习IT技术 学习内容涵盖数据库 软件测试 主流框架 领域驱动设计和第三方生态等 离全栈工程师更近一步 精心整理的CSDN技术大咖博文
  • Java版工程项目管理系统源码 工程项目源码

    数 据 库 MySQL 开发语言 Java 开发工具 MyEclipse 源码类型 WebForm 以甲方项目管理为中心 包括项目启动 计划 执行 控制与收尾阶段的全生命周期管理 并对范围 预算 进度 质量 资源 风险等管理要素进行控制与预
  • 06FFMPEG的AVCodecContext结构体分析

    06FFMPEG的AVCodecContext结构体分析 概述 该结构体位于libavcodec库中的avcodec h中 1 AVCodecContext编解码上下文结构体 位于libavcodec库里 AVFormatContext A
  • C++的sort函数如何实现从大到小排序

    C 的sort函数如何实现从大到小排序 一 sort的基本用法 1 所在的头文件 2 包含的参数 3 时间复杂度 二 具体示例 USACO07DEC Bookshelf B 题目描述 输入格式 输出格式 样例 1 样例输入 1 样例输出 1
  • CMake应用:生成器表达式

    目录 一 概述 二 常用的生成器表达式 1 布尔生成器表达式 2 字符串值生成器表达式 3 调试 CMake的生成器表达式不算是特别常用 但是有一些场景可能是必须要使用的 或者在针对不同编译类型设置不同编译参数的时候可以巧妙应用 从而减少配