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

这篇具有很好参考价值的文章主要介绍了现代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 的内容:

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

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 里

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

更新变量缓存

常见问题:我修改了 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 来启动基于终端的可视化缓存编辑菜单。
    现代CMake高级教程 - 第 7 章:变量与缓存

  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 里看不到。文章来源地址https://www.toymoban.com/news/detail-433384.html

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 章:变量与缓存的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CMake入门教程【高级篇】CPack打包项目Linux的deb和windows的msi

    😈 「CSDN主页」 :传送门 😈 「Bilibil首页」 :传送门 😈 「动动你的小手」 : 点赞 👍 收藏 ⭐️ 评论 📝

    2024年02月02日
    浏览(35)
  • springboot 高级教程 jetcache 二级缓存用法

    多级缓存实际上是在二级缓存的基础上,为了更好地提高系统的性能和可靠性,更适用于大型分布式系统的应用场景。 使用多级缓存的原因包括: 数据缓存分层:不同级别的缓存可以被用来缓存不同类型、不同频率访问的数据。在这种情况下,系统会先在本地缓存中寻找数

    2024年02月08日
    浏览(30)
  • 黑马Redis视频教程高级篇(二:多级缓存)

    目录 一、什么是多级缓存? 二、JVM进程缓存 2.1、导入案例 2.2、初识Caffeine 2.3、实现JVM进程缓存 2.3.1、需求 2.3.2、实现 三、Lua语法入门 3.1、初识Lua 3.2、HelloWord 3.3、变量和循环 3.3.1、Lua的数据类型 3.3.2、声明变量 3.3.3、循环 3.4、条件控制、函数 3.4.1、函数 3.4.2、条件控制

    2024年02月09日
    浏览(28)
  • 黑马Redis视频教程高级篇(一:分布式缓存)

    目录 分布式缓存 一、Redis持久化 1.1、RDB持久化 1.1.1、执行时机 1.1.2、RDB原理 1.1.3、小结 1.2、AOF持久化 1.2.1、AOF原理 1.2.2、AOF配置 1.2.3、AOF文件重写 1.3、RDB与AOF对比 二、Redis主从 2.1、搭建主从架构 2.1.1、集群结构 2.1.2、准备实例和配置 2.1.3、启动 2.1.4、开启主从关系 2.1.5、

    2024年02月08日
    浏览(47)
  • 现代 CMake 模块化项目管理指南

    参考小彭老师的视频教程整理笔记,学习同时方便快速查阅,视频链接如下 【公开课】现代 CMake 模块化项目管理指南【C/C++】 对应课程 PPT 和源码见 https://github.com/parallel101/course 完整案例参考源码仓库 https://github.com/parallel101/course/tree/master/16/00 第一点,划分了 biology 和 pybm

    2024年02月03日
    浏览(30)
  • Games104现代游戏引擎笔记高级ai

    World State是一个主观的对世界的认知,并不是一个真实世界的描述 Sensors负责从游戏环境中抓取各种状态 HTN Domain 存放层次化的树状结构Task和之间的关联关系1 Planner 根据World State从 Domain 里规划 task Plan Runner 根据 Planner 设定的计划执行 Task,当 Task 执行过程中发生了很多其他问

    2024年02月06日
    浏览(37)
  • CMake高级用法实例分析(学习paddle官方的CMakeLists)

    cmake基础学习教程 https://juejin.cn/post/6844903557183832078 项目名 variable 选项名 help_text 描述、解释、备注 value 选项初始化值(除ON而外全为OFF)) 这个大写的SET其实和小写的set是一样的, CMake中的命令不区分大小写,CMake中的变量区分大小写 官方手册 比较好的案例博客https://blog.c

    2024年02月09日
    浏览(34)
  • Java Web现代化开发:Spring Boot + Mybatis + Redis二级缓存

    Spring-Boot因其提供了各种开箱即用的插件,使得它成为了当今最为主流的Java Web开发框架之一。Mybatis是一个十分轻量好用的ORM框架。Redis是当今十分主流的分布式key-value型数据库,在web开发中,我们常用它来缓存数据库的查询结果。 本篇博客将介绍如何使用Spring-Boot快速搭建一

    2024年01月17日
    浏览(42)
  • [opencv][windows]cmake opencv opencv_contrib所需的缓存文件下载

    这个是windows上源码编译opencv+opencv-contrib时候cmake时候缓存文件,只需要将压缩文件夹解压到源码目录下面,cmake-gui上configure时候就不会报错,注意解压后文件夹名字是.cache,文件夹名字不能改变,比如opencv/.cache,有的人解压后成opencv/.cache/.cache是错误的,请仔细检查文件夹名字

    2024年02月19日
    浏览(44)
  • Redis高级篇 - 多级缓存

    传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,如图: 存在下面的问题: 请求要经过Tomcat处理,Tomcat的性能成为整个系统的瓶颈 Redis缓存失效时,会对数据库产生冲击 多级缓存就是充分利用请求处理的每个环节,分别添加缓存,减轻Tomcat压

    2024年02月08日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包