CMake之宏和函数

macro

macro(<name> [<arg1> ...])
  <commands>
endmacro()

定义一个名为name的宏(命名推荐使用全小写),参数为arg1, arg2, …,参数一般为下划线开头,是为了表明这些参数只能在宏中访问

function

function(<name> [<arg1> ...])
  <commands>
endfunction()

定义一个名为name的函数(命名推荐使用全小写),参数为arg1, arg2, …,参数一般为下划线开头,是为了表明这些参数只能在函数中访问

marco和function对比

共同点

参数

  • ${ARGC} 传递的参数个数
  • ${ARGV} 所有参数的列表,${ARGV0}, ${ARGV1}, ${ARGV2}, … 为真正的传进来的参数,在使用${ARGV#}时最好判断${ARGC},否则有可能出现未定义行为
  • ${ARGN} 保存了最后一个参数之后的参数列表

验证:

macro(xinling _name _time) # macro和function相同
    message(STATUS "${ARGC} arguments: ${ARGV}")
    message(STATUS "arguments: ${ARGV0}, ${ARGV1}, ${ARGV2}, ${ARGV3}, ${ARGV4}, ${ARGV5}")
    message(STATUS "The last parameter list: ${ARGN}")
endmacro()

输出:
在这里插入图片描述
从结果可以看出:

  • ${ARGV#}超过参数个数的部分没有打印输出
  • ${ARGV}${ARGN}都是以";"分隔输出

调用方式

macro/function(foo)
  <commands>
endmacro()/endfunction()

都可以通过以下几种方式调用

foo() # 推荐和定义时的命名保持一致
Foo()
FOO()
cmake_language(CALL foo)  # 3.18之后新增命令

差异

宏和函数之间的区别在于他们的变量范围。宏在调用者的范围内执行,而函数有自己的变量范围,换句话说,类似C++等编程语言,宏只是做替换,所以可以修改变量,但在函数中修改父作用域变量,但这必须通过PARENT_SCOPE显式表示:set(variable "any value" PARENT_SCOPE),否则函数内对父作用域的变量的修改只在函数的作用域内生效。

适用场景

什么时候用function或macro?需要仔细考虑变量的作用范围,如果功能可以使用函数实现,就尽量使用函数,因为它对父范围状态提供了更多的默认控制。

CMake模块中定义

在这里插入图片描述
在sub_cmake.cmake模块中定义函数或宏:

macro(define_macro)
    message("start define colors")
    # any command
endmacro()

在CMakeLists.txt中调用模块中的宏或函数
include方式一:通过设置CMAKE_MODULE_PATH,include命令指示CMake搜索${CMAKE_MODULE_PATH},查找名称为sub_cmake.cmake的模块

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(sub_cmake)  
define_macro() # 调用include进来的模块中的函数或宏

include方式二:显式包含
include(cmake/colors.cmake)

两个命令:

  1. include
include(<file|module> [OPTIONAL] [RESULT_VARIABLE <var>] [NO_POLICY_SCOPE])

加载和运行file或module,会指示CMake搜索 ${CMAKE_MODULE_PATH}, 查找模块

  1. include_guard
include_guard([DIRECTORY|GLOBAL])

类似C中的#pragma once,防止多次包含模块,可选的参数为:

  • DIRECTORY:应用于当前目录
  • GLOBAL:应用于全局

指定参数宏或函数

命令cmake_parse_arguments

用来解析宏或函数的参数

cmake_parse_arguments(<prefix> <options> <one_value_keywords>
                      <multi_value_keywords> <args>...)

参数说明:(cmake官方文档中"<>"里的参数都是必须的)

  • prefix:这个用来在取参数的时候用到,名字可以随意
  • options:这个参数是相对独立的,就是说调用时有这个参数那么它的值为TRUE,否则就是FALSE。options就是这种参数的集合
  • one_value_keywords:指定只有一个值的参数的集合
  • multi_value_keywords:指定有多个值的参数的集合

取值:_keywordName,这里的keywordName就是options、one_value_keywords、multi_value_keywords中指定的参数
示例代码:

function(my_install)
    set(options OPTIONAL FAST)  # 注意:如果这里不使用set,请看下例
    set(oneValueArgs DESTINATION RENAME)
    set(multiValueArgs TARGETS CONFIGURATIONS)
    cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN} )
    message(STATUS "OPTIONAL: ${MY_INSTALL_OPTIONAL}")
    message(STATUS "FAST: ${MY_INSTALL_FAST}")
    message(STATUS "DESTINATION: ${MY_INSTALL_DESTINATION}")
    message(STATUS "RENAME: ${MY_INSTALL_RENAME}")
    message(STATUS "TARGETS: ${MY_INSTALL_TARGETS}")
    message(STATUS "CONFIGURATIONS: ${MY_INSTALL_CONFIGURATIONS}")
endfunction()

my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)

输出:
在这里插入图片描述
不使用set设置参数关键字的示例:

function(my_install)
    set(multiValueArgs TARGETS CONFIGURATIONS)
    cmake_parse_arguments(MY_INSTALL "OPTIONAL;FAST" "DESTINATION RENAME" "${multiValueArgs}" ${ARGN} )
    ...
    # 其他内容和上例相同
my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)

输出:
在这里插入图片描述
所以不使用set的话在cmake_parse_arguments中用";"分隔关键字

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值