CMake中macro的使用
在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的使用相关推荐
- CMake中的ARGC ARGV 和ARGN参数意义
编写或者查看一些开源cmake文件中经常遇到在宏(macro)和函数中经常会遇到ARGC ARGV 和ARGN等参数,该参数为cmake中专用变量,分别表示宏或者函数参数中的特殊意义. ARGC AR ...
- CMake中file的使用
CMake中的file命令用于文件操作,其文件格式如下:此命令专用于需要访问文件系统的文件和路径操作 Readingfile(READ <filename> <variable> ...
- CMake中foreach的使用
CMake中的foreach命令为list中的每个值评估一组命令(Evaluate a group of commands for each value in a list),其格式如下:其中< ...
- CMake中option和cmake_dependent_option的使用
CMake中的option命令为用户提供可以选择的布尔选项(boolean option),其格式如下: option(<variable> "<help_text> ...
- CMake中target_compile_features的使用
CMake中的target_compile_features命令用向target添加预期的编译器功能(compiler features),其格式如下: target_compile_features ...
- CMake中include指令用法介绍
转载于: https://blog.csdn.net/liitdar/article/details/81144461 本文主要介绍CMake中include指令的用法. 1 概述 引用CMake官 ...
- CMake中set/unset的使用
CMake中的set命令用于将普通.缓存或环境变量(normal, cache, or environment variable)设置为给定值,其格式如下:指定<value>...占位符( ...
- CMake中include的使用
CMake中的include命令用于从文件或模块(file or module)加载并运行CMake code.其格式如下: include(<file|module> [OPTIONAL ...
- CMake中link_directories/target_link_directories的使用
CMake中的link_directories命令用于添加目录使链接器能在其查找库(add directories in which the linker will look for librarie ...
最新文章
- 【C++】对象实例化/成员函数/成员变量的内存管理
- js添加网页水印和three.js场景中加水印
- 我第一次接私活,就被骗了···
- 精简的shell计算器
- MySQL主从压_mysql主从配置
- Python执行系统命令的四种方法
- python调用chrome插件_Python使用Chrome插件实现爬虫过程图解
- 刑侦高考:如何用SQL解决环环相扣的刑侦推理问题
- linux命令的帮助信息,Linux查询命令帮助信息(知道)
- Cocos2d-X开发中国象棋《三》開始场景的实现
- 路径标记语法 in Windows Presentation Foundation(WPF)
- possible SYN flooding on port 3690 Sending cookies
- php无框架开发web项目,web.framework
- 饭店计算机软件系统FIDlLIL,酒店Opera系统研究
- 200行Python实现连连看辅助
- 如何将自己网络计算机更名,如何将自己的win7电脑变身wifi无线网络热点
- arc120C - Swaps 2
- 华为RH2288H V3服务器raid配置
- H5+Vue2: input(number/tel)唤起数字键盘,踩坑日记
- 甲骨文与谷歌进入第二轮版权之争