在https://blog.csdn.net/fengbingchun/article/details/127144948 中介绍了CMake中function的使用,这里介绍下macro的使用,它与function有很多的相似性。

macro的定义格式如下:后面可作为命令供调用

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

其中name是macro的名字,参数为arg1,arg2等。与function一样,macro名称也不区分大小写,但强烈建议使用macro定义中声明的相同名称。通常,macro使用全小写名称。示例代码段如下:

message("1.与function一样,macro名称也不区分大小写,但始终建议使用macro定义中声明的相同名称")
macro(csdn_addr)message("csdn addr: https://blog.csdn.net/fengbingchun")
endmacro()csdn_addr()
CSDN_ADDR()
csdn_ADDR()

macro参数:与function一样,macro也采用两种类型的参数:
      (1).命名参数或关键字参数(named or keyword arguments):是必须的,如果未提供将触发error。参数名称之间不需要逗号。示例代码段如下:

message("2.命名参数是必须的,如果未提供将触发error.参数名称之间不需要逗号")
macro(addr csdn github)message("csdn addr: ${csdn}")message("github addr: ${github}")
endmacro()addr("https://blog.csdn.net/fengbingchun" "https://github.com/fengbingchun")

(2).可选参数(optional arguments):可以使用一些预定义的变量访问可选参数,示例代码段如下:
      ARGC:参数总数(命名参数+可选参数)。
      ARGV:包含命名参数和可选参数的变量列表
      ARGN:仅包含可选参数的变量列表

message("3.可以使用一些预定义的变量访问可选参数:ARGC, ARGV, ARGN")
macro(name_list name1 name2)message("argument count: ${ARGC}")message("all arguments: ${ARGV}")message("optional arguments: ${ARGN}")
endmacro()name_list(Jack Kate Jony Tom)
# only named arguments
name_list(Jack Kate)

除了这三个变量之外,cmake还提供了ARGV0,ARGV1,ARGV2,...,这将具有传入参数的实际值。引用ARGC之外的ARGV#参数将导致未定义的行为。注意:这些在function中起作用,在macro中直接使用无效。在function中,它们是CMake意义上的真变量;在macro中,它们不是,它们是字符串替换,就像C预处理器对macro所做的那样。

message("4.cmake还提供了ARGV0,ARGV1,ARGV2,...,这将具有传入参数的实际值.引用ARGC之外的ARGV#参数将导致未定义的行为.这些在function中起作用,在macro中不作改动无效")
macro(programming_language name1 name2)# 在某些情况下,macro在使用特殊变量时会表现出奇怪的行为,注意:此处与function的差异if(${ARGV0}) # 好像不起作用message("ARGV0: ${ARGV0}")else()message("ARGV0 not defined")endif()math(EXPR last_index "${ARGC}-1")foreach(index RANGE 0 ${last_index})# 在某些情况下,macro在使用特殊变量时会表现出奇怪的行为,注意:此处与function的差异message("argument at index ${index}: ${ARGV${index}}")endforeach()# 通常,使用变量访问命名参数,使用ARGN访问可选参数message("name1: ${name1}")message("name2: ${name2}")# 注意:此处与function的差异set(list_var ${ARGN})#message("list var: ${list_var}")#foreach(arg IN LISTS ${ARGN}) # 好像不起作用foreach(arg IN LISTS list_var)message("optional name: ${arg}")endforeach()
endmacro()programming_language(C++ Python Go Matlab)

通常,使用变量访问命名参数,使用ARGN访问可选参数

使用DEFINED关键字,你可以检查是否定义了给定的变量、缓存变量或环境变量。变量的值无关紧要。在某些情况下,macro在使用特殊变量时会表现出奇怪的行为。

message("5.使用DEFINED关键字,你可以检查是否定义了给定的变量、缓存变量或环境变量.变量的值无关紧要.在function中起作用,在macro中无效")
macro(foo_macro name)# 在某些情况下,macro在使用特殊变量时会表现出奇怪的行为,注意:此处与function的差异if(DEFINED name)message("macro argument name is defined")else()message("macro argument name is not defined")endif()
endmacro()function(foo_func name)if(DEFINED name)message("func argument name is defined")else()message("func argument name is not defined")endif()
endfunction()foo_macro(csdn)
foo_func(csdn)

变量作用域(variable scope):与function不同,macro不会引入新的作用域在macro中声明的变量(参数除外)将在调用后可用。function在调用时始终引入新作用域(new scope)。对于macro,macro调用将替换为marco主体(macro body),并使用字符串替换(string substitution)替换参数。因此,在某些情况下,function和macro的行为不同。

message("6.与function不同,macro不会引入新的作用域.在macro中声明的变量(参数除外)将在调用后可用")
set(development_language "C++")macro(set_development_language name)message("macro param: ${name}")message("macro name: ${development_language}")set(new_language "Python")set(development_language "Matlab")message("macro new language: ${new_language}")
endmacro()set_development_language("Go")
message("development_language: ${development_language}")
message("new language: ${new_language}")

return()命令:由于macro不会创建任何新作用域,因此调用return()将退出当前作用域

message("7.由于macro不会创建任何新作用域,因此调用return()将退出当前作用域,这里是退出当前的.cmake文件,注意与在function里的差异:退出当前的function")
macro(early_return)message("csdn")return()message("github") # it will not be printed
endmacro()early_return() # 退出当前cmake文件
message("will never be executed")

如果定义了一个已经存在的macro时,将覆盖上一个macro。可以使用"_"加macro name的方式访问上一个macro。如果再次重新定义同一个macro,"_"加macro name版本将调用先前定义的macro。原始macro将永远不可用。如果开发人员在编写macro时不知道该macro已用于某些cmake库macro,则原始macro有可能永远隐藏。

message("8.如果定义了一个已经存在的macro时,将覆盖上一个macro.可以使用\"_\"加macro name的方式访问上一个macro.如果再次重新定义同一个macro,\"_\"加macro name版本将调用先前定义的macro.原始macro将永远不可用.")
macro(csdn_addr)message("csdn addr: https://github.com/fengbingchun")
endmacro()csdn_addr() # csdn addr: https://github.com/fengbingchun
_csdn_addr() # csdn addr: https://blog.csdn.net/fengbingchunmacro(csdn_addr)message("csdn addr: https://www.baidu.com/")
endmacro()csdn_addr() # csdn addr: https://www.baidu.com/
_csdn_addr() # csdn addr: https://github.com/fengbingchun

也可通过cmake的预定义的命令cmake_parse_arguments来解析macro的参数。

function和macro的不同
      (1).变量作用域不同:function会引入新的作用域,而macro不会,即,默认,function内新增的变量外部不可见;而macro内新增的变量外部可见。
      (2).cmake提供的变量ARGV0,ARGV1,ARGV2,...,在function中有效,在macro中无效。在某些情况下,macro中的ARGN也不会生效,在macro中,它们是字符串替换,就像C预处理器对macro所做的那样。
      (3).function内调用return()命令是退出当前function;而macro内调用return()是退出当前cmake文件。建议在macro中完全避免使用return()。
      (4).CMAKE_CURRENT_FUNCTION, CMAKE_CURRENT_FUNCTION_LIST_DIR, CMAKE_CURRENT_FUNCTION_LIST_FILE, CMAKE_CURRENT_FUNCTION_LIST_LIN这些变量应用于function中而不是macro中。

测试代码组织结构如下:

build.sh内容如下:

#! /bin/bash# supported input parameters
params=(function macro)usage()
{echo "Error: $0 needs to have an input parameter"echo "supported input parameters:"for param in ${params[@]}; doecho "  $0 ${param}"doneexit -1
}if [ $# != 1 ]; thenusage
fiflag=0
for param in ${params[@]}; doif [ $1 == ${param} ]; thenflag=1breakfi
doneif [ ${flag} == 0 ]; thenecho "Error: parameter \"$1\" is not supported"usageexit -1
fiif [[ ! -d "build" ]]; thenmkdir buildcd build
elsecd build
fiecho "==== test $1 ===="
cmake -DTEST_CMAKE_FEATURE=$1 ..

CMakeLists.txt内容如下:

CMAKE_MINIMUM_REQUIRED(VERSION 3.13)
PROJECT(cmake_feature_usage)if(TEST_CMAKE_FEATURE STREQUAL "function")include(test_function.cmake)
elseif(TEST_CMAKE_FEATURE STREQUAL "macro")include(test_macro.cmake)
endif()message("==== test finish ====")

test_macro.cmake内容:为上面所示代码段

执行结果如下图所示:

GitHub:https://github.com/fengbingchun/Linux_Code_Test

CMake中macro的使用相关推荐

  1. CMake中的ARGC ARGV 和ARGN参数意义

    编写或者查看一些开源cmake文件中经常遇到在宏(macro)和函数中经常会遇到ARGC ARGV 和ARGN等参数,该参数为cmake中专用变量,分别表示宏或者函数参数中的特殊意义. ARGC AR ...

  2. CMake中file的使用

    CMake中的file命令用于文件操作,其文件格式如下:此命令专用于需要访问文件系统的文件和路径操作 Readingfile(READ <filename> <variable> ...

  3. CMake中foreach的使用

    CMake中的foreach命令为list中的每个值评估一组命令(Evaluate a group of commands for each value in a list),其格式如下:其中< ...

  4. CMake中option和cmake_dependent_option的使用

    CMake中的option命令为用户提供可以选择的布尔选项(boolean option),其格式如下: option(<variable> "<help_text> ...

  5. CMake中target_compile_features的使用

    CMake中的target_compile_features命令用向target添加预期的编译器功能(compiler features),其格式如下: target_compile_features ...

  6. CMake中include指令用法介绍

    转载于:  https://blog.csdn.net/liitdar/article/details/81144461 本文主要介绍CMake中include指令的用法. 1 概述 引用CMake官 ...

  7. CMake中set/unset的使用

    CMake中的set命令用于将普通.缓存或环境变量(normal, cache, or environment variable)设置为给定值,其格式如下:指定<value>...占位符( ...

  8. CMake中include的使用

    CMake中的include命令用于从文件或模块(file or module)加载并运行CMake code.其格式如下: include(<file|module> [OPTIONAL ...

  9. CMake中link_directories/target_link_directories的使用

    CMake中的link_directories命令用于添加目录使链接器能在其查找库(add directories in which the linker will look for librarie ...

最新文章

  1. 【C++】对象实例化/成员函数/成员变量的内存管理
  2. js添加网页水印和three.js场景中加水印
  3. 我第一次接私活,就被骗了···
  4. 精简的shell计算器
  5. MySQL主从压_mysql主从配置
  6. Python执行系统命令的四种方法
  7. python调用chrome插件_Python使用Chrome插件实现爬虫过程图解
  8. 刑侦高考:如何用SQL解决环环相扣的刑侦推理问题
  9. linux命令的帮助信息,Linux查询命令帮助信息(知道)
  10. Cocos2d-X开发中国象棋《三》開始场景的实现
  11. 路径标记语法 in Windows Presentation Foundation(WPF)
  12. possible SYN flooding on port 3690 Sending cookies
  13. php无框架开发web项目,web.framework
  14. 饭店计算机软件系统FIDlLIL,酒店Opera系统研究
  15. 200行Python实现连连看辅助
  16. 如何将自己网络计算机更名,如何将自己的win7电脑变身wifi无线网络热点
  17. arc120C - Swaps 2
  18. 华为RH2288H V3服务器raid配置
  19. H5+Vue2: input(number/tel)唤起数字键盘,踩坑日记
  20. 甲骨文与谷歌进入第二轮版权之争

热门文章

  1. 微信支付发放现金红包
  2. PorterDuffXfermode的初级使用
  3. Javaweb JAVA JSP大学生贷款管理系统贷款管理系统jsp大学生助学金贷款管理
  4. 移动硬盘无法停止通用卷
  5. NOTE:2014-12-24
  6. ubuntu18.04 systemd配置学习手册(1) --相关概念
  7. 【案例】揭秘Netflix个性化推荐系统,你看到哪版电影海报?由算法决定
  8. 大家知道1GHz的周期等于多少秒吗
  9. 0x00000050解决方法
  10. 微信视频号攻略:转发视频号的视频到自己的视频号上