How to call a function in CMake whose name is stor

2019-05-12 00:27发布

问题:

Is there a way to call a function in CMake using the name that is stored in a variable (for passing functions to functions, etc)?

Here is what I have tried:

cmake_minimum_required(VERSION 3.0)

function(doThing)
endfunction()

set(FuncVar doThing)

${FuncVar}()

Which fails with this error:

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

I can't see why this shouldn't work, but then again I am new to CMake so what do I know.

Thank you for any help!

回答1:

I have solved this with a workaround using files.

Lets say you have:

function(do what)
  ...
endfunction()

You want to call different specializations depending on 'what'. You can then do:

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

And in file do-something.cmake:

function(do_dynamic)
  ...
endfunction()

You can create as many specialization files as you want...



回答2:

Hi I have written eval for cmake (and it is as fast as i can make it) here and here is the code as it is part of my cmakepp library.

I have written two versions of eval (eval and eval_ref because the first does not give you access to the PARENT_SCOPE whereas the latter does)

however this will only help if your use cmakepp and as that might be a dealbreaker for you I modified it to work with 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:

Without workarounds, CMake itself does not support function pointers or indirect calls. For example someone asked on the CMake mailing list in 2011 about a call function to achieve what you wanted to do: https://cmake.org/pipermail/cmake/2011-September/046124.html



标签: cmake