工具使用——CMake中的函数和宏

一、CMake脚本

CMake应用的过程,其实可以当成一种脚本语言的应用。只不过,CMake脚本相关的应用要比普通脚本更有专业的指向性。或者说,其相对要简单不少。

作为脚本,当然要支持常见的逻辑控制、变量定义及循环操作等等功能。但最重要的,当然是要支持函数和宏的功能即function()和macro()。

二、函数和宏

在CMake中,function()和macro()和普通编程语言中的函数和宏的功能基本类似,只是可能没有高级语言那么强大的应用罢了。

CMake的函数和宏主要是提供逻辑复用,实现封装机制(模块化),从而达到代码的可读性和可维护性。函数和宏既可以在CMake脚本中调用也可以像命令一样调用它们。可以这样理解,函数和宏是CMake开发的重要的基础。

三、分析应用

对于函数和宏,其特点主要包括以下几点:

  1. 作用域的控制
    函数的引入会从函数范围本身和函数参数范围内引入了相关的作用域。不过由于宏本身是一种替换,所以其实际的作用域与最终生成的代码块相关
  2. 参数的处理
    函数的参数是CMake脚本中的变量,这些变量一般和CMake自身变量的功能相同。但宏的参数只是一种简单的替换,不能简单的认为是哪种变量。但在最终实现的代码中,则具有相同的语义
  3. 参数的类别
    参数和宏可以使用CMake提供的自定义变量,如ARGC(参数数量)、ARGV(输入参数列表)、ARGN(未命名参数列表)以及ARG1(每一个参数),ARG2...等。它们可以实现类似于C++中变参处理的效果。
    另外,为了支持多个可选或可选参数结果,CMake还提供了关键字参数。这样开发者就可以通过cmake_parse_arguments()命令来实现动态的扩展处理
  4. 返回值
    与C++中的函数不同在于,CMake中的函数和宏没有返回值直接返回。但可以使用set()与PARENT_SCOPE及类似C++函数中的变量作为参数的方法传递。
    CMake中的return()并不返回值,只是将处理返回到父作用域中。但宏中的return()要与最终实际的代码位置共同决定其返回的作用域
  5. 重载
    函数和宏可以实现命令,当已经存在此命令时,CMake中的函数和宏都不会产生重载,而只会覆盖。注意,即使是函数和宏混合使用亦是如此。但在CMake的内部机制中,它支持将原有的命令增加一个下划线的前缀"_"(如play<=>_play),供在以后区别使用

四、函数和宏的不同

虽然函数和宏在很多的表现上都非常类似,但他们的区别还是不小的:

  1. 作用域的不同
    函数的作用域是显示的,其作用域是独立的,函数内外互不干涉;而宏的作用域是隐式的,对于宏本身没有作用域的说法,只是在最终生成的代码块才会体现出作用域
  2. 变量的实质不同
    函数的变量就是CMake中的变量,不管是任何的类型;而宏的变量只是一种类似于占位符的存在,用来将替换的文本复制到指定的位置
  3. 处理机制不同
    函数中可以通过各种操作进行处理(如列表变量等);而宏的变量只是一个占位的标志,没有处理的意义

五、示例

在CMake中函数和宏的定义一般如下:

复制代码
function(name [arg1 [arg2 [...]]])
  # Function body (i.e. commands) ...
endfunction()
macro(name [arg1 [arg2 [...]]])
  # Macro body (i.e. commands) ...
endmacro()

下面看一些函数和宏的基础应用:

复制代码
#简单定义和应用
#函数
function(display)
  message(" demo function")
  message("end")
endfunction()
# 调用:
display()
#宏
function(func testArg)
  message("testArg = ${testArg}")
endfunction()
macro(macr_fn testArg)
  message("testArg = ${testArg}")
endmacro()
#调用
func(demo)
macr_fn(demo)


#return
macro(first)
  message("use first")
  return() # 不建议在宏内使用,比较危险
  message("unreached")
endmacro()
function(second)
  message("use second")
  first()
  message(" is unreached ")
endfunction()
second()

//处理返回值
# 定义
function(sum_fn n1 n2 ret_var)
    math(EXPR sum "${n1} + ${n2}")
    # 使用PARENT_SCOPE将结果返回到调用者作用域
    set(${ret_var} ${sum} PARENT_SCOPE)
endfunction()

# 变量RESULT存储结果
sum_fn(1 6 RESULT)
message(STATUS "结果和: ${RESULT}") # 结果: 7

//函数覆盖
function(test)
    message("my test")
endfunction()
test()  # 输出:my test

function(test)
    message("my test once")
endfunction()
test()  # 输出:my test once

上面只给出一个很基础的例子,更详细的可以参看CMake的官方文档。

六、总结

CMake中的函数和宏,为开发者提供了模块化封装的机制,让开发者可以更好的进行脚本的功能实现和逻辑控制。特别是在实践的中大规模项目中非常重要。

相关推荐
乐观勇敢坚强的老彭2 小时前
C++信息学奥赛lesson1
java·开发语言·c++
Irissgwe2 小时前
C++ STL关联式容器详解:set、multiset、map、multimap
开发语言·c++·stl·set·map·multiset·关联式容器
Irissgwe2 小时前
string类的模拟实现
c++·string
郝亚军2 小时前
Visual Studio 2022安装for C++桌面开发
c++·ide·visual studio
智者知已应修善业2 小时前
【51单片机初始化D5-D8亮,每按键按下D1到D4全亮,再按下恢复,如此循环】2024-3-26
c++·经验分享·笔记·算法·51单片机
为何创造硅基生物3 小时前
C++ 独占指针被销毁后,堆也会自己销毁
c++
C+-C资深大佬3 小时前
C++ 中的 constexpr与 const区
java·开发语言·c++
Tairitsu_H3 小时前
[LC优选算法#3] 滑动窗口 | 将x减到0的最⼩操作数 | ⽔果成篮 | 字⺟异位词
c++·算法·leetcode·滑动窗口
c++之路3 小时前
CMake 系列教程(一):CMake 基础知识
c语言·开发语言·c++