现代CMake高级教程 - 第 7 章:变量与缓存
双笙子佯谬老师的【公开课】现代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 参数太硬核了,有没有图形化的缓存编辑器?
-
在 Linux 中,可以安装
sudo apt install cmake-curses-gui
,运行 ccmake -B build 来启动基于终端的可视化缓存编辑菜单。
-
在 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_TBBprintf("TBB enabled!\n");
#endifprintf("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()
相关文章:
现代CMake高级教程 - 第 7 章:变量与缓存
双笙子佯谬老师的【公开课】现代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 -- Detec…...
SQL知识汇总
什么时候用存储过程合适 当一个事务涉及到多个SQL语句时或者涉及到对多个表的操作时就要考虑用存储过程;当在一个事务的完成需要很复杂的商业逻辑时(比如,对多个数据的操作,对多个状态的判断更改等)要考虑;…...
区位码-GB2312
01-09区为特殊符号 10-15区为用户自定义符号区(未编码) 16-55区为一级汉字,按拼音排序 56-87区为二级汉字,按部首/笔画排序 88-94区为用户自定义汉字区(未编码) 特殊符号 区号:01 各类符号 0 1 2 3 4 …...
文本识别、截图识别保存和多文件识别
一、源码 github源码 二、介绍 采用Tesseract OCR识别 采用多线程进行图片识别 界面 选择 文件是可以识别本地的多张图片文件夹是识别文件夹里面的所有图片的内容截图 可以复制到剪切板、可以识别也可以直接保存 重置 是清除选择的图片和识别结果语言选择 是选择不同的模型…...
针对近日ChatGPT账号大批量封禁的理性分析
文 / 高扬 这两天不太平。 3月31号,不少技术圈的朋友和我闲聊说,ChatGPT账号不能注册了。 我不以为然,自己有一个号足够了,并不关注账号注册的事情。 后面又有不少朋友和我说ChatGPT账号全部不能注册了,因为老美要封锁…...
MATLAB算法实战应用案例精讲-【人工智能】对比学习(概念篇)
目录 前言 几个高频面试题目 推荐领域的对比学习在设计代理任务时与CV和NLP领域有什么不同?...
WeakMap 与 WeakSet
WeakSet WeakSet 结构与 Set 类似,也是不重复的值的集合。 成员都是数组和类似数组的对象,WeakSet 的成员只能是对象,而不能是其他类型的值。 若调用 add() 方法时传入了非数组和类似数组的对象的参数,就会抛出错误。 const b …...
【hello Linux】进程信号
目录 1. 进程信号的引出及整体概况 2. 信号的产生 1. 键盘产生 2. 进程异常 3. 系统调用 4. 软件条件 3. 信号的保存 1. 信号相关的常见概念 2. sigset_t 3. 信号集操作函数 4. sigprocmask:对block位图的操作 5. sigpending:对pending位图的操作 6. 捕捉…...
【SpringBoot】获取HttpServletRequest的三种方式
方法一: Controller中增加request参数 RestController public class DemoController { RequestMapping("/demo")public void demo(HttpServletRequest request) { System.out.println(request.getParameter("hello"));} }线程安全缺点: 每个方法都…...
k8s DCGM GPU采集指标项说明
dcgm-exporter 采集指标项 指标解释dcgm_fan_speed_percentGPU风扇转速占比(%)dcgm_sm_clockGPU sm 时钟(MHz)dcgm_memory_clockGPU 内存时钟(MHz)dcgm_gpu_tempGPU 运行的温度(℃)dcgm_power_usageGPU 的功率(w)dcgm_pcie_tx_throughputGPU PCIeTX 传输的字节总数 (kb)dcgm_pc…...
从线程安全到锁粒度,使用Redis分布式锁的注意事项
关于 Redis 的分布式锁 在分布式的场景下,多个服务器之间的资源竞争和访问频繁性,为了数据的安全和性能的优化,我们需要引入分布式锁的概念,这把锁可以加在上层业务需要的共享数据/资源上,能够同步协调多个服务器的访…...
CopyOnWriteArrayList 的底层原理与多线程注意事项
文章目录 CopyOnWriteArrayList 的底层原理与多线程注意事项1. CopyOnWriteArrayList 底层原理1.1 概念说明1.2 实现原理1.3 优点1.4 缺点 2. CopyOnWriteArrayList 多线程注意事项与实例2.1 注意事项2.2 示例2.2.1 示例代码 3. 总结 CopyOnWriteArrayList 的底层原理与多线程注…...
互斥锁深度理解与使用
大家好,我是易安! 我们知道一个或者多个操作在CPU执行的过程中不被中断的特性,称为“原子性”。理解这个特性有助于你分析并发编程Bug出现的原因,例如利用它可以分析出long型变量在32位机器上读写可能出现的诡异Bug,明明已经把变量…...
Elasticsearch --- 数据聚合、自动补全
一、数据聚合 聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如: 什么品牌的手机最受欢迎? 这些手机的平均价格、最高价格、最低价格? 这些手机每月的销售情况如何? 实现这…...
Haproxy搭建web群集
一.常见的web集群调度器 1、目前常见的web集群调度器分为软件和硬件 2、软件通常使用开源的LVS、Haproxy、Nginx LVS 性能最好,但搭建复杂。Nginx并发量,性能低于Haproxy 3、硬件一般使用比较多的是F5,也有很多人使用国内的一些产品&a…...
Packet Tracer - 配置和验证小型网络
Packet Tracer - 配置和验证小型网络 地址分配表 设备 接口 IP 地址 子网掩码 默认网关 RTA G0/0 10.10.10.1 255.255.255.0 不适用 G0/1 10.10.20.1 255.255.255.0 不适用 SW1 VLAN1 10.10.10.2 255.255.255.0 10.10.10.1 SW2 VLAN1 10.10.20.2 255.25…...
Baumer工业相机堡盟工业相机如何通过BGAPI SDK获取相机设备的各种固件信息如DeviceID或者SerialNumber等(C++)
项目场景 Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具…...
java 的参数传递
一、疑惑引入 首先,我们从一个例子来引出这个问题: public static void main(String[] args) throws IOException {List<String> mockList Lists.newArrayList("a", "b");System.out.println("1: " mockList);L…...
【面试长文】HashMap的数据结构和底层原理以及在JDK1.6、1.7和JDK8中的演变差异
文章目录 HashMap的数据结构和底层原理以及在JDK1.6、1.7和JDK8中的演变差异HashMap的数据结构和原理JDK1.6、1.7和1.8中的HashMap源码演变JDK1.6JDK1.7JDK1.8 总结自己实现一个简单的HashMapHashMap的时间复杂度分析HashMap的空间复杂度分析HashMap的应用场景HashMap的弊端及解…...
【25】linux进阶——网络文件系统NFS
大家好,这里是天亮之前ict,本人网络工程大三在读小学生,拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识,希望能提高自己的技术的同时,也可以帮助到大家 另外其它专栏请关注: 锐捷数通实验&…...
JAVA入坑之JAVADOC(Java API 文档生成器)与快速生成
目录 一、JAVADOC(Java API 文档生成器) 1.1概述 1.2Javadoc标签 1.3Javadoc命令 1.4用idea自带工具生成API帮助文档 二、IDEA如何生成get和set方法 三、常见快捷方式 3.1快速生成main函数 3.2快速生成println()语句 3.3快速生成for循环 3.4“…...
React | React组件化开发
✨ 个人主页:CoderHing 🖥️ React .js专栏:React .js React组件化开发 🙋♂️ 个人简介:一个不甘平庸的平凡人🍬 💫 系列专栏:吊打面试官系列 16天学会Vue 11天学会React Node…...
云计算的优势与未来发展趋势
一、前言二、云计算的基础概念2.1 云计算的定义2.2 云计算的发展历程2.3 云计算的基本架构2.4 云计算的主要服务模式 三、企业采用云计算的优势3.1 降低成本3.2 提高效率和灵活性3.3 提升信息系统的安全性和可靠性3.4 拥有更加丰富的应用和服务 四、行业应用案例4.1 金融行业4.…...
shell编程lesson01
命令行和脚本关系 命令行:单一shell命令,命令行中编写与执行; 脚本:众多shell命令组合成一个完成特定功能的程序,在脚本文件中进行编写维护。 脚本是一个文件,一个包含有一组命令的文件。 编写一个shel…...
看看人家的MyBatis批量插入数据优化,从120s到2.5s,那叫一个优雅!
粗略的实验 最后 最近在压测一批接口的时候,我发现接口处理速度比我们预期的要慢。这让我感到有点奇怪,因为我们之前已经对这些接口进行了优化。但是,当我们进行排查时,发现问题出在数据库批量保存这块。 我们的项目使用了 myb…...
软件和信息服务业专题讲座
软件和信息服务业专题讲座 单选题(共 10 题,每题 3 分) 1、根据本讲,我国要加强物联网应用领域()开发和应用。 A、大数据 2、根据本讲,要充分发挥软件对城市管理和惠民服务的(&am…...
由 ChatGPT 团队开发,堪称辅助神器!IntelliJ IDEA 神级插件
什么是Bito? 为什么要使用Bito? 如何安装Bito插件 如何使用Bito插件 什么是Bito? Bito是一款由ChatGPT团队开发的IntelliJ IDEA编辑器插件,旨在提高开发人员的工作效率。此插件强大之处在于它不仅可以帮助开发人员更快地提交…...
spass modeler
课时1:SPSS Modeler 简介 本课时一共分为五个模块,分别是Modeler概述、工具安装、窗口说明以及功能介绍和应用案例。相信通过本课时内容的学习,大家将会对SPSS Modeler有个基础的了解. 在学习本节课内容之前,先来看看本节课我们究…...
kafka的push、pull分别有什么优缺点
文章目录 kafka的push、pull分别有什么优缺点Push 模式优点缺点 Pull 模式优点缺点 实践操作 kafka的push、pull分别有什么优缺点 Kafka 是由 Apache 软件基金会开发的一个开源流处理平台,广泛应用于各大互联网公司的消息系统中。在 Kafka 中,生产者使用…...
【Canvas入门】从零开始在Canvas上绘制简单的动画
这篇文章是观看HTML5 Canvas Tutorials for Beginners教程做的记录,所以代码和最后的效果比较相似,教程的内容主要关于这四个部分: 创建并设置尺寸添加元素让元素动起来与元素交互 设置Canvas的大小 获取到canvas并设置尺寸为当前窗口的大…...
使用云主机做网站教程/网站优化网站优化
SpringMVC_requestMapping 项目搭建见上篇《初识 Spring(09)---(搭建SpringMVC项目)》 1.requestMapping既可以用在方法上,也可以用在类上 文件目录: 代码:新建SpringmvcTest.java package com.neuedu.springmvc.controller;i…...
清风算法受影响的网站/在线bt种子
今天在部署项目时,遇到项目组其它人重整了server上的iis。结果外部訪问不了所部属的项目,通过一些渠道找到了设置方法 例如以下报错的截图: 原因是“入站ICMP规则”被重整了,所以我们须要又一次新建入站ICMP规则 (详…...
怎么搭建个人网站/襄阳seo培训
mixins一般有两种用途: 1.当你已经写好了构造器之后,需要增加方法或者临时的活动时使用的方法,这是用混入会减少源代码的污染; 下面的需求是构造器已经完成,突然要额外增加控制台打印变化的数据,操作如下: <body><div id"app">{{num}}<p><bu…...
武汉seo关键字优化/信息流优化师需要具备哪些能力
把该窗体的KeyPreview属性设成true private void frmMain_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode Keys.F1) { } }转载于:https://blog.51cto.com/flydragon0815/719558...
网站建设费用分类/百度优化点击软件
jleaksJava Resource Leaks Monitor,用于Java资源泄露检测,代码的GITHUB地址当程序库的作者向用户提供一个使用后需要释放资源的类,通常都苦恼如何保证用户的这个行为。Java的类不像C拥有析构函数,对于库的提供者,C程序…...
电脑上做网站/培训机构
使用for(String item:list)会很好,但是它只会迭代一个列表,而你需要一个显式迭代器用于另一个列表.或者,您可以为两者使用显式迭代器.以下是问题的示例,以及使用索引for循环的解决方案:import java.util.*;public class ListsToMap {static public void …...