CMake中的函数与宏

Yan*_*Xie 76 cmake

CMake 2.8.12的官方文件说明了这一点macro

调用它时,首先通过用传递的参数替换形式参数($ {arg1})来修改宏中记录的命令,然后作为普通命令调用.

而且 function

调用它时,首先通过用传递的参数替换形式参数($ {arg1})来修改函数中记录的命令,然后将其作为普通命令调用.

显然,两个引号几乎相同但令我困惑.在像宏一样调用函数时,首先替换参数吗?

Yan*_*Xie 82

我在下面写了一个示例代码

set(var "ABC")

macro(Moo arg)
  message("arg = ${arg}")
  set(arg "abc")
  message("# After change the value of arg.")
  message("arg = ${arg}")
endmacro()
message("=== Call macro ===")
Moo(${var})

function(Foo arg)
  message("arg = ${arg}")
  set(arg "abc")
  message("# After change the value of arg.")
  message("arg = ${arg}")
endfunction()
message("=== Call function ===")
Foo(${var})
Run Code Online (Sandbox Code Playgroud)

而输出是

=== Call macro ===
arg = ABC
# After change the value of arg.
arg = ABC
=== Call function ===
arg = ABC
# After change the value of arg.
arg = abc
Run Code Online (Sandbox Code Playgroud)

因此,似乎arg分配了var调用时的值,Foo并且${arg}只是${var}在调用时替换了字符串Moo.

所以我认为上述两个引号很容易让人感到困惑,尽管官方文件也说过

它们是字符串替换,就像C预处理器使用宏一样.如果您想要真正的CMake变量和/或更好的CMake范围控制,您应该查看function命令.

  • @robert 根据帮助中心,允许立即回答您自己的问题(特别是如果这是一个对其他人普遍感兴趣的好的、非重复的问题)。这是为了帮助 SO 成为更好的知识库。您是否阅读了该帮助中心主题中链接的博客文章?https://stackoverflow.blog/2011/07/01/its-ok-to-ask-and-answer-your-own-questions/ (2认同)
  • 使用 `cmake --trace-expand` 运行这样的例子很有启发性 (2认同)

rob*_*ert 30

换句话说,函数推送和弹出新的变量范围(创建和更改的变量仅存在于函数中),宏则不存在.但是,您可以使用命令的PARENT_SCOPE参数覆盖函数默认行为set.


Mar*_*rcH 6

您引用的cmake文档是如此令人误解,以至于基本上是错误的。应该这样澄清/修复:

  • 宏:调用宏时,首先将宏中记录的命令全部修改,然后再通过将形式参数($ {arg1})替换为传递的参数来运行任何命令。

cmake --trace-expand 准确显示发生了什么。

与此相比,cmake 3.13.3文档与2.8.12相比没有变化。