CMake语法—普通变量与函数(Normal Variable And Function)

1 CMake普通变量与函数示例

1.1 CMakeLists.txt

cmake_minimum_required(VERSION 3.18)

# 设置工程名称
set(PROJECT_NAME KAIZEN) # 设置工程版本号
set(PROJECT_VERSION "1.0.0.10" CACHE STRING "默认版本号") # 工程定义
project(${PROJECT_NAME}
LANGUAGES CXX C
VERSION ${PROJECT_VERSION}
) # 打印开始日志
message(STATUS "\n##########BEGIN_TEST") # 零个值
set(MY_LOCAL_ZERO_VAR)
message(STATUS "MY_LOCAL_ZERO_VAR: ${MY_LOCAL_ZERO_VAR}") # 1个值
set(MY_LOCAL_VAR "I am a local variable")
message(STATUS "MY_LOCAL_VAR_1: ${MY_LOCAL_VAR}") # 在相同作用域修改普通变量
set(MY_LOCAL_VAR "I am a local variable by modify same scope")
message(STATUS "MY_LOCAL_VAR_2: ${MY_LOCAL_VAR}") # 多个值
set(MY_LOCAL_LIST_VAR "kaizen" "baidu" "C++" "developer")
message(STATUS "MY_LOCAL_LIST_VAR: ${MY_LOCAL_LIST_VAR}") # 定义函数func
function(func)
# 修改父作用域普通变量值
# 修改前打印
message(STATUS "MY_LOCAL_VAR_3: ${MY_LOCAL_VAR}")
# 修改动作
set(MY_LOCAL_VAR "I am a local variable by modify func")
# 修改后打印
message(STATUS "MY_LOCAL_VAR_4: ${MY_LOCAL_VAR}")
# 函数作用域内定义普通变量不加选项PARENT_SCOPE
set(MY_FUNC_VAR "I am a func inner variable")
# 函数作用域打印定义变量值
message(STATUS "MY_FUNC_VAR_1: ${MY_FUNC_VAR}")
endfunction() # 定义函数func_parent_scope
function(func_parent_scope)
# 修改父作用域普通变量值
# 修改前打印
message(STATUS "MY_LOCAL_VAR_5: ${MY_LOCAL_VAR}")
# 修改动作
set(MY_LOCAL_VAR "I am a local variable by modify func_parent_scope" PARENT_SCOPE)
# 修改后打印
message(STATUS "MY_LOCAL_VAR_6: ${MY_LOCAL_VAR}")
# 函数作用域内定义普通变量加选项PARENT_SCOPE
set(MY_FUNC_VAR "I am a func inner variable" PARENT_SCOPE)
# 函数作用域打印定义变量值
message(STATUS "MY_FUNC_VAR_2: ${MY_FUNC_VAR}")
endfunction() # 调用函数func
message(STATUS "\n########## Begin call func")
func()
message(STATUS "########## End call func")
# 调用函数func后打印
message(STATUS "MY_LOCAL_VAR_7: ${MY_LOCAL_VAR}")
# 调用函数func后打印
message(STATUS "MY_FUNC_VAR_3: ${MY_FUNC_VAR}") # 调用函数func_parent_scope
message(STATUS "\n########## Begin call func_parent_scope")
func_parent_scope()
message(STATUS "########## End call func_parent_scope")
# 调用函数func_parent_scope后打印
message(STATUS "MY_LOCAL_VAR_8: ${MY_LOCAL_VAR}")
# 调用函数func_parent_scope后打印
message(STATUS "MY_FUNC_VAR_4: ${MY_FUNC_VAR}") # 打印结束日志
message(STATUS "##########END_TEST\n")

1.2 执行CMake配置脚本

@echo off
set currentDir=%~dp0
set buildDir=%currentDir%
set cmakeOutputDir=%currentDir%\build
cmake -S %buildDir% -B %cmakeOutputDir% -G"Visual Studio 16 2019" -T v140 -A x64
pause

1.3 目录结构

  • learn_cmake:为根目录
  • build:为CMake配置输出目录(在此例中即生成sln解决方案的地方)
  • cmake_config.bat:执行CMake配置过程的脚本(双击直接运行)
  • CMakeLists.txt:CMake脚本

2 运行结果

2.1 环境说明

本地安装VS版本:Visual Studio 2019(2015工具集)

CMake版本:3.18.2

F:\learn_cmake
λ cmake --version
cmake version 3.18.2 CMake suite maintained and supported by Kitware (kitware.com/cmake).

2.2 运行结果

-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.17763.
-- The CXX compiler identification is MSVC 19.0.24245.0
-- The C compiler identification is MSVC 19.0.24245.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
--
##########BEGIN_TEST
-- MY_LOCAL_ZERO_VAR:
-- MY_LOCAL_VAR_1: I am a local variable
-- MY_LOCAL_VAR_2: I am a local variable by modify same scope
-- MY_LOCAL_LIST_VAR: kaizen;baidu;C++;developer
--
########## Begin call func
-- MY_LOCAL_VAR_3: I am a local variable by modify same scope
-- MY_LOCAL_VAR_4: I am a local variable by modify func
-- MY_FUNC_VAR_1: I am a func inner variable
-- ########## End call func
-- MY_LOCAL_VAR_7: I am a local variable by modify same scope
-- MY_FUNC_VAR_3:
--
########## Begin call func_parent_scope
-- MY_LOCAL_VAR_5: I am a local variable by modify same scope
-- MY_LOCAL_VAR_6: I am a local variable by modify same scope
-- MY_FUNC_VAR_2:
-- ########## End call func_parent_scope
-- MY_LOCAL_VAR_8: I am a local variable by modify func_parent_scope
-- MY_FUNC_VAR_4: I am a func inner variable
-- ##########END_TEST -- Configuring done
-- Generating done
-- Build files have been written to: F:/learn_cmake/build
请按任意键继续. . .

2.3 结论

2.3.1 定义普通变量方式
set(<variable> <value>... [PARENT_SCOPE])
2.3.2 variable:表示普通变量名称;
2.3.3 value:表示变量的值列表,value后面有三个点,表示变量的值可以为0或1或n个值

示例程序中第19行:定义普通变量,赋值为0个值,可理解为占位符。值为空,打印结果也为空,参见运行结果输出第16行。

示例程序中第23行:定义普通变量,赋值为1个值,即字符串中内容。参见运行结果输出第17、18行打印内容。

示例程序中第31行:定义普通变量,赋值为4个值,当多个值时,将来会用分号拼接起来为一个字符串。参见运行结果输出第19行打印内容。

2.3.4 PARENT_SCOPE:表示父作用域,若加此选项,特别明确定义或修改父作用域变量的值
2.3.5 普通变量,在函数func作用域中,会拷贝一份父作用域的所有普通变量(即在被调用函数内可访问父作用域内的普通变量)

从示例程序出发,再结合输出结果分析可知:

  1. 同作用域修改普通变量值,不用添加PARENT_SCOPE选项。好像是一句废话,但为了下文更好理解与函数作用域的区别,在此强调一遍。

    如示例程序中第27行,对23行定义的MY_LOCAL_VAR变量进行修改值,没有添加PARENT_SCOPE选项,修改生效。

    如果此场景笔误或理解错添加PARENT_SCOPE选项了呢?经笔者验证的结果:会出现CMake Warning,同时修改不会生效(即suppress 阻止)

  2. 函数作用域内修改父作用域普通变量的值,不添加PARENT_SCOPE选项,仅仅在函数作用域内有效

    换句话表述:类比法,等同于C++中函数内部(等同于嵌套的新作用域)局部变量与父作用域变量同名的情景,此时父作用域同名变量会被隐藏掉。

    #include <iostream>
    int main()
    {
    int var = 1024;
    {
    std::cout << var << std::endl; // 1024
    int var = 2048;
    var = 2049;
    std::cout << var << std::endl; // 2049
    }
    std::cout << var << std::endl; // 1024
    system("pause");
    }

    如示例程序中第40行,对父作用域第27行的MY_LOCAL_VAR变量进行修改值,没有加PARENT_SCOPE选项。

    第42行打印结果MY_LOCAL_VAR_4貌似的确是修改后的值。但是退出函数后,第69行打印结果MY_LOCAL_VAR_7的值却仍然是原旧值(即调用函数前的值)。

  3. 函数作用域内修改父作用域普通变量的值,添加PARENT_SCOPE选项,只表明修改父作用域变量的值(注意:不会立即生效)

    如示例程序中第55行,对父作用域第27行的MY_LOCAL_VAR变量的值进行修改,添加PARENT_SCOPE选项。

    第57行打印结果MY_LOCAL_VAR_6没有改变,仍然是原旧值(即进入函数瞬时拷贝的那份变量值,此时的修改不会立竿见影)。

    但是,退出函数后,第78行打印结果MY_LOCAL_VAR_8却是被修改后的值,即修改仅对父作用域空间内有效。

  4. 在函数作用域内,利用PARENT_SCOPE选项,也可为父作用域定义普通变量

    如示例程序中第61行,添加PARENT_SCOPE选项,即使退出函数后,第80行打印结果MY_FUNC_VAR_4的值不为空,即父作用域定义的普通变量有效。

    相反,第46行,没有添加PARENT_SCOPE选项,退出函数后,第71行打印结果MY_FUNC_VAR_3的值为空,即父作用域定义的普通变量被视为无效。

CMake语法—普通变量与函数(Normal Variable And Function)的更多相关文章

  1. CMake语法—普通变量与子目录(Normal Variable And Subdirectory)

    目录 CMake语法-普通变量与子目录(Normal Variable And Subdirectory) 1 CMake普通变量与子目录示例 1.1 代码目录结构 1.2 父目录CMakeLists ...

  2. CMake语法—普通变量与包含、宏(Normal Variable And Include、Macro)

    目录 CMake语法-普通变量与包含.宏(Normal Variable And Include.Macro) 1 CMake普通变量与包含.宏示例 1.1 代码目录结构 1.2 根目录CMakeLi ...

  3. CMake语法—缓存变量(Cache Variable)

    目录 CMake语法-缓存变量(Cache Variable) 1 CMake缓存变量 2 定义缓存变量 2.1 定义格式 2.2 定义示例代码 2.3 运行结果 2.4 小结 3 CMakeCach ...

  4. CMake语法—环境变量(Environment Variable)

    目录 CMake语法-环境变量(Environment Variable) 1 定义环境变量 2 应用环境变量 2.1 代码结构 2.2 示例代码 2.3 运行结果 3 小结 CMake语法-环境变量 ...

  5. Kotlin基础语法:变量、函数、类、枚举、控制流

    一切都需要从基础学起! 前言: 在Kotlin语言中,没有分号的概念了,也就是每一行代码,都不在需要用分号结束了 点击查看代码 定义 常量:val --相当于java当中的final 变量:var 关 ...

  6. CMake语法—内置变量

    目录 CMake语法-内置变量 1 CMake变量分类 1.1 普通变量 1.2 缓存变量 1.3 环境变量 1.4 内置变量 2 CMake内置变量分类 2.1 提供信息的变量 2.2 改变行为的变 ...

  7. 【转载】CMake 两种变量原理

    原文地址:https://cslam.cn/archives/c9f565b5.html 摘要: 本文记录一下 CMake 变量的定义.原理及其使用.CMake 变量包含 Normal Variabl ...

  8. CMake 两种变量原理

    目录 [TOC] 1.两种变量的定义参考 2.两种变量的作用域原理及使用 1.Normal Variables (1).包含 add_subdirectory().function().(本质是值拷贝 ...

  9. Swift语法基础入门三(函数, 闭包)

    Swift语法基础入门三(函数, 闭包) 函数: 函数是用来完成特定任务的独立的代码块.你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数 格式: ...

随机推荐

  1. ajax 有终止请求 abort 那 axios 有没有,怎么实现

    见代码 class View extends Component { constructor(props){ super(props); this.state = { cancel:null, can ...

  2. 微信支付——沙箱调试环境getsignkey方法秘钥获取及常见问题说明

    官方文档 :https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=23_1 微信支付PC二维码支付:https://www.cnblogs ...

  3. c++ vector释放概述

    这里仅为概述,具体的详情分析,可以Google下,会得到更详尽的解释. 1.函数clear和erase都将数组的size清空,但对应的空间并没有回收,而且,一直push_baclk, 对应的capac ...

  4. 【九度OJ】题目1144:Freckles 解题报告

    [九度OJ]题目1144:Freckles 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1144 题目描述: In an ...

  5. [LeetCode] 729. My Calendar I 731. My Calendar II 732. My Calendar III 题解

    题目描述 MyCalendar主要实现一个功能就是插入指定起始结束时间的事件,对于重合的次数有要求. MyCalendar I要求任意两个事件不能有重叠的部分,如果插入这个事件会导致重合,则插入失败, ...

  6. 【剑指Offer】左旋转字符串 解题报告(Python)

    [剑指Offer]左旋转字符串 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews 题目 ...

  7. Adversarial Training with Rectified Rejection

    目录 概 主要内容 rejection 实际使用 代码 Pang T., Zhang H., He D., Dong Y., Su H., Chen W., Zhu J., Liu T. Advers ...

  8. CausalVAE: Disentangled Representation Learning via Neural Structural Causal Models

    目录 概 主要内容 模型 ELBO 关于 Yang M., Liu F., Chen Z., Shen X., Hao J. and Wang J. CausalVAE: disentangled r ...

  9. 八、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-聊天输入框扩展面板的实现

    聊天输入框扩展面板的实现 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入 ...

  10. C++多线程并发---异步编程

    线程同步主要是为了解决对共享数据的竞争访问问题,所以线程同步主要是对共享数据的访问同步化(按照既定的先后次序,一个访问需要阻塞等待前一个访问完成后才能开始).这篇文章谈到的异步编程主要是针对任务或线程 ...