现代CMake高级教程 - 第 7 章:变量与缓存

news2024/12/26 5:57:44

双笙子佯谬老师的【公开课】现代CMake高级教程课程笔记

第 7 章:变量与缓存

重复执行 cmake -B build 会有什么区别?

❯ cmake -B build
-- The C compiler identification is GNU 11.3.0
-- The CXX compiler identification is GNU 11.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/h/Code/lessonCode/CMakeLession/build

❯ cmake -B build
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/h/Code/lessonCode/CMakeLession/buil

可以看到第二次的输出少了很多,这是因为 CMake 第一遍需要检测编译器和 C++ 特性等比较耗时,检测完会把结果存储到缓存中,这样第二遍运行 cmake -B build 时就可以直接用缓存的值,就不需要再检测一遍了。

然而有时候外部的情况有所更新,这时候 CMake 里缓存的却是旧的值,会导致一系列问题。这时我们需要清除缓存,最简单的办法就是删除 build 文件夹,然后重新运行 cmake -B build。缓存是很多 CMake 出错的根源,因此如果出现诡异的错误,可以试试看删 build 全部重新构建。

清除缓存,其实只需删除 build/CMakeCache.txt 就可以了

删 build 虽然彻底,也会导致编译的中间结果(.o文件)都没了,重新编译要花费很长时间。如果只想清除缓存,不想从头重新编译,可以只删除 build/CMakeCache.txt 这个文件。这文件里面装的就是缓存的变量,删了他就可以让 CMake 强制重新检测一遍所有库和编译器。

build/CMakeCache.txt 的内容:

find_package 就用到了缓存机制

变量缓存的意义在于能够把 find_package 找到的库文件位置等信息,储存起来。这样下次执行 find_package 时,就会利用上次缓存的变量,直接返回。避免重复执行 cmake -B 时速度变慢的问题。

设置缓存变量

语法是:set(变量名 “变量值” CACHE 变量类型 “注释”)

set(myvar "hello" CACHE STRING "this is the docstring .")
message("myvar is: ${myvar}")
❯ cmake -B build
myvar is: hello
-- Configuring done
-- Generating done

缓存的 myvar 会出现在 build/CMakeCache.txt 里

在这里插入图片描述

更新变量缓存

常见问题:我修改了 CMakeLists.txt 里 set 的值,却没有更新?

为了更新缓存变量,有的同学偷懒直接修改 CMakeLists.txt 里的值,这是没用的。因为 set(… CACHE …) 在缓存变量已经存在时,不会更新缓存的值!

CMakeLists.txt 里 set 的被认为是“默认值”,因此不会在第二次 set 的时候更新。

缓存变量到底该如何更新?标准解法:通过命令行 -D 参数

❯ cmake -B build -Dmyvar=world
myvar is: world
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/h/Code/lessonCode/CMakeLession/build

命令行 -D 参数太硬核了,有没有图形化的缓存编辑器?

  1. 在 Linux 中,可以安装 sudo apt install cmake-curses-gui,运行 ccmake -B build 来启动基于终端的可视化缓存编辑菜单。
    在这里插入图片描述

  2. 在 Windows 则可以 cmake-gui -B build 来启动图形界面编辑各个缓存选项。

当然,直接用编辑器打开 build/CMakeCache.txt 修改后保存也是可以的。CMakeCache.txt 用文本存储数据,就是可供用户手动编辑,或是被第三方软件打开并解析的。

缓存变量到底该如何更新?暴力解决:删 build 大法。

用万能的“删 build 大法”当然是可以的。这样重新执行的时候缓存变量不存在,从而 set 会重新设置缓存的值为 world。建议初学者每次修改 CMakeLists.txt 时,都删一下 build/CMakeCache.txt 方便调试。

也可以通过指定 FORCE 来强制 set 更新缓存。set 可以在后面加一个 FORCE 选项,表示不论缓存是否存在,都强制更新缓存。

不过这样会导致没办法用 -Dmyvar=othervalue 来更新缓存变量。

set(myvar "hello" CACHE STRING "this is the docstring." FORCE)
message("myvar is: ${myvar}")

缓存变量类型

  • STRING 字符串,例如 “hello, world”
  • FILEPATH 文件路径,例如 “C:/vcpkg/scripts/buildsystems/vcpkg.cmake”
  • PATH 目录路径,例如 “C:/Qt/Qt5.14.2/msvc2019_64/lib/cmake/”
  • BOOL 布尔值,只有两个取值:ON 或 OFF。

注意:TRUE 和 ON 等价,FALSE 和 OFF 等价;YES 和 ON 等价,NO 和 OFF 等价。

案例

案例:添加一个 BOOL 类型的缓存变量,用于控制要不要启用某特性

CMakeLists.txt

add_executable(main main.cpp)

set(WITH_TBB ON CACHE BOOL "set to ON to enable TBB, OFF to disable TBB.")
if (WITH_TBB)
	target_compile_definitions(main PUBLIC WITH_TBB)
	find_package(TBB REQUIRED)
	target_link_libraries(main PUBLIC TBB::tbb)
endif()

main.cpp

#include <cstdio>

int main()
{
#ifdef WITH_TBB
	printf("TBB enabled!\n");
#endif
	printf("Hello, world!\n");
}

编译运行结果:

TBB enabled!
Hello, world!

option

CMake 对 BOOL 类型缓存的 set 指令提供了一个简写:option

option(变量名 “描述” 变量值)

等价于:

set(变量名 CACHE BOOL 变量值 “描述”)

CMakeLists.txt

add_executable(main main.cpp)

option(WITH_TBB "set to ON to enable TBB, OFF to disable TBB." ON)
if (WITH_TBB)
	target_compile_definitions(main PUBLIC WITH_TBB)
	find_package(TBB REQUIRED)
	target_link_libraries(main PUBLIC TBB::tbb)
endif()

修改 option 变量值

经典问题:option 设为 OFF 了为什么还是 ON

因为在 CMakeLists.txt 里直接改 option 是错的。option 等价于 set(... CACHE BOOL ...)。因此在 CMakeLists.txt 里改同样不会立即更新缓存里的值。官方推荐做法是通过 -D变量名:BOOL=ON/OFF 来改缓存变量。

cmake -B build -DWITH_TBB:BOOL=OFF

或者不要 option 了,直接用 set 加个 FORCE 即可始终强制更新缓存。

CMakeLists.txt

add_executable(main main.cpp)

set(WITH_TBB ON CACHE BOOL "set to ON to enable TBB, OFF to disable TBB." FORCE)
if (WITH_TBB)
	target_compile_definitions(main PUBLIC WITH_TBB)
	find_package(TBB REQUIRED)
	target_link_libraries(main PUBLIC TBB::tbb)
endif()

当然最方便的还是删 build,或者删 build/CMakeCache.txt。删 build 大法总能把缓存变量强制初始化为 CMakeLists.txt 里的值。

绕开缓存的方法:使用普通变量,但仅当没有定义时设定为默认值。一般来说 CMake 自带的变量(如 CMAKE_BUILD_TYPE)都会这样设置。

这样项目的使用者还是可以用 -D 来指定参数,不过会在 ccmake 里看不到。

if (NOT DEFINED WITH_TBB)
	set(WITH_TBB ON)
endif()
if (WITH_TBB)
	target_compile_definitions(main PUBLIC WITH_TBB)
	find_package(TBB REQUIRED)
	target_link_libraries(main PUBLIC TBB::tbb)
endif()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/484913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++:分治算法之输油管道问题

目录 描述 输入 输出 输入样例 输出样例 分析 代码 运行结果 描述 ¢ 某石油公司计划建造一条 由东向西 的主输油管道。该管道要穿过一个有n口油井的油田。从每口油井都要有一条输油管道沿最短路经&#xff08;或南或北&#xff09;与主管道相连。 ¢ 如果给定…

如何区分GPT3.5和4?

切换模型 前两天申请的GPT 4的API调用权限终于申请下来了。 这两天我也是抓紧开发&#xff0c;让自己搭建的国内网站&#xff08;aichatroom.cn&#xff09;可以快速支持上使用GPT 4。 GPT 3.5和GPT4的区别 GPT-3.5 和 GPT-4 分别代表了 OpenAI 发布的两个不同版本的自然语言处…

现代CMake高级教程 - 第 4 章:对象的属性

双笙子佯谬老师的【公开课】现代CMake高级教程课程笔记 第 4 章&#xff1a;对象的属性 除了 POSITION_INDEPENDENT_CODE 还有哪些这样的属性&#xff1f; add_executable(main main.cpp)set_property(TARGET main PROPERTY CXX_STANDARD 17) # 采用 C17 标准进行编译&am…

STC15W104 8脚单片机串口下载程序

单片机串口下载是一种常见的单片机程序下载方式&#xff0c;它通过串口线连接单片机的串口引脚和电脑的串口接口实现。下面是单片机串口下载的基本原理和操作方法&#xff1a; 原理 确定下载模式&#xff1a;大多数单片机芯片都支持串口下载模式&#xff0c;需要在程序中设置…

常识性概念图谱建设与应用

目录 一、知识图谱背景介绍 &#xff08;一&#xff09;基本背景 &#xff08;二&#xff09;与NLP的关系 &#xff08;三&#xff09;常识性概念图谱的引入对比 二、常识性概念图谱介绍 &#xff08;一&#xff09;常识性概念图谱关系图示例 &#xff08;二&#xff09…

深度学习-tensorflow 使用keras进行深度神经网络训练

概要 深度学习网络的训练可能会很慢、也可能无法收敛&#xff0c;本文介绍使用keras进行深度神经网络训练的加速技巧&#xff0c;包括解决梯度消失和爆炸问题的策略&#xff08;参数初始化策略、激活函数策略、批量归一化、梯度裁剪&#xff09;、重用预训练层方法、更快的优化…

linux进程描述指令:ps与top

这里写自定义目录标题 一 ps指令1 ps -aux2. ps -a3. ps -u4.ps -x 二 top指令1 top2 top -d 时间3. top -i4 top -p ID 一 ps指令 1 ps -aux 显示系统中的所有进程 PID就是进程的唯一编号&#xff0c;操作系统书里有一个PCD的概念&#xff0c;就是一个标识性的控制单元 [ro…

学系统集成项目管理工程师(中项)系列16b_风险管理(下)

1. 规划风险应对 1.1. 针对项目目标&#xff0c;制订提高机会、降低威胁的方案和措施的过程 1.2. 制订风险应对措施 1.3. 制订风险应对计划 1.4. 次生风险是实施风险应对措施的直接结果 1.5. 应对措施必须与风险的重要性相匹配&#xff0c;能经济有效地应对挑战 1.5.1. 【…

项目管理-计算专题(三点估算、PERT估算)

基本概念 通过考虑估算中的不确定性和风险&#xff0c;可以提高活动持续时间估算的准确性。这个概念源自计划评审技术(PERT)。PERT使用三种估算值来界定活动持续时间的近似区间: 最可能时间(tM)&#xff1a;基于最可能获得的资源、最可能取得的资源生产率、对资源可用时间的现…

C语言CRC-16 MODBUS格式校验函数

C语言CRC-16 MODBUS格式校验函数 CRC-16校验产生2个字节长度的数据校验码&#xff0c;通过计算得到的校验码和获得的校验码比较&#xff0c;用于验证获得的数据的正确性。基本的CRC-16校验算法实现&#xff0c;参考&#xff1a; C语言标准CRC-16校验函数。 不同应用规范通过对…

Simulink 自动代码生成电机控制:弱磁控制从仿真到硬件开发板验证实验

目录 前言 仿真 生成代码在硬件上运行 总结 前言 测试了一个新的小电机&#xff0c;24V只能跑2000RPM左右&#xff0c;在此基础上测试一下弱磁控制&#xff0c;由于MTPA只适用于表贴电机&#xff0c;测试效果不能直观看出来&#xff0c;一般是通过测试效率。而前馈解耦的响…

【Paper】2019_DoS/数据注入攻击下基于一致性的信息物理系统安全性研究_曹雄

2019_DoS/数据注入攻击下基于一致性的信息物理系统安全性研究_曹雄 文章目录 第2章 拒绝服务攻击下多智能体系统安全性研究2.1 问题描述2.1.1 系统模型2.1.2 拒绝服务攻击模型 2.2 安全估计与一致性分析2.4 数值仿真2.4.1 观测器网络受到攻击下的结果及分析2.4.1.1 线性多智能体…

视频分享平台PeerTube的搭建

老苏下载了吴恩达的 Prompt for developer 课程&#xff0c;不管是否有兴趣&#xff0c;都可以看看&#xff0c;早晚我们都得学会使用 ChatGPT 虽然课程对话是英文&#xff0c;但有中文字幕&#xff0c;课程地址&#xff1a;https://www.aliyundrive.com/s/H3CpaapD87Z 这个软…

使用ChatGPT+Xmind一键生成思维导图,简直泰裤辣

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

python 编写K210控制步进电机的程序示例

今天正好看到K210的脉冲章节&#xff0c;就顺便拿出步进电机做个小实验&#xff0c;也好巩固一下所学的知识。下面是K210关于脉冲的相关介绍&#xff1a; 构造函数 machine.PWM(tim, freq, duty, pin, enableTrue) PWM 对象在 machine 模块下 【tim】K210 的 PWM 依赖…

789. 数的范围(C++和Python3)——2023.5.3打卡

文章目录 QuestionIdeasCode Question 给定一个按照升序排列的长度为 n 的整数数组&#xff0c;以及 q 个查询。 对于每个查询&#xff0c;返回一个元素 k 的起始位置和终止位置&#xff08;位置从 0 开始计数&#xff09;。 如果数组中不存在该元素&#xff0c;则返回 -1 -…

【C++从0到王者】第二站:类和对象(上)

文章目录 一、面向过程与面向对象二、类的引入三、类的访问限定符四、类的定义五、封装六、类的作用域七、类的实例化八、类对象模型1.如何计算类对象的大小2.类对象存储方式猜测 九、this指针1.this指针的引出2.this指针的特性 一、面向过程与面向对象 C语言是面向过程的&…

Web2与Web3开发的不同之处

Web2是引入交互功能的第二代互联网&#xff0c;也是我们今天所熟悉的。随着Web的不断发展&#xff0c;第三代互联网&#xff0c;也被称为Web3&#xff0c;正处于积极开发中。Web3引入了在区块链上运行的去中心化和无需许可的系统。但是Web2和Web3开发之间有什么区别呢&#xff…

23.5.1总结

这几天都在写项目&#xff1a; 在实现页面&#xff0c;调用数据库的时候&#xff0c;总是把数据库的表改了又改&#xff0c;然后完善了下数据库的表。 存储的思路大概是&#xff1a; 一个课程下可以有多个班级&#xff0c;所以以课程id作为主键建一个表&#xff0c;内容包括…

在win11搭建ubuntu目标机器的QT开发环境的实践

环境&#xff1a; 笔记本电脑 16G内存 win11 尝试wsl的方案&#xff1a; wsl2 ubuntu gnome xrdp wsl安装ubuntu并设置gnome图形界面详细步骤&#xff08;win11ubuntu18&#xff09;_heusjh的博客-CSDN博客 wsl2 ubuntu gnome VcXsrv Windows中WSL2 配置运行GNOM…