如何在名称存储在变量中的CMake中调用函数

时间:2015-12-21 22:06:43

标签: cmake

有没有办法使用存储在变量中的名称来调用CMake中的函数(用于将函数传递给函数等)?

以下是我的尝试:

cmake_minimum_required(VERSION 3.0)

function(doThing)
endfunction()

set(FuncVar doThing)

${FuncVar}()

哪个失败并出现此错误:

Parse error.  Expected a command name, got unquoted argument with text "${FuncVar}".
-- Configuring incomplete, errors occurred!

我无法理解为什么这不起作用,但我又是新来的CMake,所以我知道什么。

感谢您的帮助!

5 个答案:

答案 0 :(得分:7)

我已经使用文件解决了这个问题。

让我们说:

function(do what)
  ...
endfunction()

您希望根据“内容”调用不同的专精。然后你可以这样做:

function(do what)
  include("do-${what}.cmake")
  do_dynamic()
endfunction()

在文件do-something.cmake中:

function(do_dynamic)
  ...
endfunction()

您可以根据需要创建任意数量的专业化文件......

答案 1 :(得分:3)

快速更新:似乎CMake通过cmake_language命令,语法在当前的3.18版本中添加了此功能:

cmake_language(CALL <command> [<args>...])
cmake_language(EVAL CODE <code>...)

cmake_language的参考 https://cmake.org/cmake/help/v3.18/command/cmake_language.html#command:cmake_language

答案 2 :(得分:2)

您好我已经为cmake撰写了eval(它的速度和我一样快) herehere是代码,因为它是我的cmakepp库的一部分。

我写了两个版本的evalevaleval_ref,因为第一个版本不允许您访问PARENT_SCOPE而后者不会访问

然而,这只会对你使用cmakepp有所帮助,因为这可能是你的破解者我修改它以使用vanilla cmake:

## evals the specified cmake code.
## WARNING: there is no way to set(<var> <value> PARENT_SCOPE) 
## because of the extra function scope defined by eval.
## WARNING: allowing eval can of course be dangerous.
function(eval __eval_code)

  # one file per execution of cmake (if this file were in memory it would probably be faster...)
  # this is where the temporary eval file will be stored.  it will only be used once per eval
  # and since cmake is not multihreaded no race conditions should occure.  however if you start 
  # two cmake processes in the same project this could lead to collisions
  set(__eval_temp_file "${CMAKE_CURRENT_BINARY_DIR}/__eval_temp.cmake")


  # write the content of temp file and include it directly, this overwrite the 
  # eval function you are currently defining (initializer function pattern)
  file(WRITE "${__eval_temp_file}" "
function(eval __eval_code)
  file(WRITE ${__eval_temp_file} \"\${__eval_code}\")
  include(${__eval_temp_file})
endfunction()
  ")

include("${__eval_temp_file}")
## now eval is defined as what was just written into __eval_temp_file


## since we are still in first definition we just need to execute eval now
## (which calls the second definition of eval).
eval("${__eval_code}")


endfunction()

答案 3 :(得分:0)

没有变通方法,CMake本身不支持函数指针或间接调用。例如,有人在2011年的CMake邮件列表中询问了if let aps = userInfo["aps"] as? [String:Any], let alertDict = aps["alert"] as? [String:String] { print("body :", alertDict["body"]!) } 功能,以实现您的目标:https://cmake.org/pipermail/cmake/2011-September/046124.html

答案 4 :(得分:0)

我有自己的实现方式

https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/cmake/tacklelib/Eval.cmake

优点:

  • 通过函数实现,结果是,对于宏,函数具有一阶段扩展阶段而不是两阶段扩展的参数,因此您无需在调用函数之前对参数进行转义(任何一个)。
  • 所有本地设置/未设置的变量都会自动传播到父范围,而无需显式执行。
  • 通过Windows或Linux中临时文件存储中的临时唯一目录实现,因此可以在任何模式(脚本或构建)中并行调用该函数,而无需使用二进制目录作为临时存储。
  • 因为评估字符串是在函数的上下文中执行的,所以不需要像return()这样的命令之前就需要特殊的清除逻辑。
  • 内部转义$\;之类的字符。
  • 直接访问临时目录(tkl_begin* + <pre process> + tkl_eval_end中正在执行的包含文件,因此您可以在调用tkl_eval_end之前对其进行预处理并制作另一个文件,例如,通过调用configure_file命令来替换文件或其他内容中的@-变量。
  • 对库中的cmake模块进行CMake测试:https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/cmake_tests

缺点:

  • return在函数上下文中执行,结果tkl_eval("return()")不执行任何操作,但是return()本身仍然可以用于在评估字符串或文件中分支逻辑。

整个项目目前都是实验性的。