一. 简介
前面学习了 CMakeLists.txt语法中是如何定义函数,本文继续学习 cmake中的宏定义。
二. cmake进阶:宏定义
cmake 提供了定义宏的方法,cmake 中函数 function 和宏定义 macro 在某种程度上来说是一样的,都是创建一段有名字的代码可以在后面被调用,还可以传参数。
通过 macro()命令定义宏,如下所示:
macro(<name> [arg1 [arg2 [arg3 ...]]])
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endmacro(<name>)
endmacro 括号中的 <name> 可写可不写,如果写了,就必须和 macro 括号中的<name>一致。
参数
name 表示宏定义的名字。
在宏定义中也可以使用前面给大家介绍的
ARGVX(X 是一个数字)、ARGC、ARGV、 ARGN
这些变量,所以这些也是宏定义的内部变量。
在 顶层 CMakeLists.txt 文件中添加如下代码
:
# macro 宏定义测试
macro(XYZ arg1 arg2)
message("ARGC: ${ARGC}")
message("ARGV: ${ARGV}")
message("ARGN: ${ARGN}")
message("ARGV0: ${ARGV0}")
message("ARGV1: ${ARGV1}")
# 循环打印出各个参数
set(i 0)
foreach(loop ${ARGV})
message("arg${i}: " ${loop})
math(EXPR i "${i} + 1")
endforeach()
endmacro()
# 使用宏
XYZ(A B C D E)
进入 build目录下,执行"cmake .."命令后打印信息如下:
从定义上看他们貌似一模一样,宏和函数确实差不多,但还是有区别的。
譬如,宏的参数和诸如 ARGV、ARGC、ARGN 之类的值不是通常 CMake 意义上的变量,它们是字符串替换,就像 C 语言预处理器对宏所做的一样,因此,您将无法使用以下命令:
if(ARGV1) # ARGV1 is not a variable
if(DEFINED ARGV2) # ARGV2 is not a variable
if(ARGC GREATER 2) # ARGC is not a variable
foreach(loop_var IN LISTS ARGN) # ARGN is not a variable
因为在宏定义中,宏的参数和诸如
ARGC
、
ARGV
、
ARGN
等这些值并不是变量,它们是字符串替换。
也就是说,当
cmake
执行宏定义时,会先将宏的参数和
ARGC
、
ARGV
、
ARGN
等这些值进行字符串替换,
然后再去执行这段宏,其实就像是
C
语言中的预处理步骤,这是与函数不同的地方。
我们来进行测试:
# macro 宏
macro(abc arg1 arg2)
if(DEFINED ARGC)
message(true)
else()
message(false)
endif()
endmacro()
# function 函数
function(xyz arg1 arg2)
if(DEFINED ARGC)
message(true)
else()
message(false)
endif()
endfunction()
# 调用宏
abc(A B C D)
# 调用函数
xyz(A B C D)
上面的代码中,我们定义了一个宏
abc
和一个函数
xyz
,它们俩的代码是一样的,都是在内部使用
if() 判断
ARGC
是不是一个变量,如果是打印
true
,如果不是打印
false
;
下面会分别调用宏
abc
和函数
xyz
,打
印信息如下所示:
从打印信息可知,在宏定义中,
ARGC
确实不是变量,其实在执行宏之前,会将
ARGC
进行替换,如下所示:
if(DEFINED 4)
message(true)
else()
message(false)
endif()
把
ARGC
替换为
4
(因为我们实际传入了
4
个参数)。
当然,除此之外,cmake 中函数和宏定义还有其它的区别,譬如函数有自己的作用域、而宏定义是没有作用域的概念。
关于 cmake的宏定义暂时学习到这里。