如何在cmake中定义宏内的函数

时间:2014-06-14 23:06:27

标签: cmake

我一直在使用cmake的软件项目,文件结构看起来像这样:

  • cmake的
  • 测试
  • 构建
  • SRC
    • 模块1
    • 模块2
    • 单词数
      • submod1
      • submod2
        • IMPL
          • backend1
          • 后端2

每个文件夹都包含一个CMakeLists.txt,它基本上将更多文件添加到src文件夹中存在的CMakeLists.txt中定义的源代码文件列表中。问题是,使用PARENT_SCOPE在范围堆栈中传递所有这些变量是不切实际的,所以我们使用了属性。

在我们决定简化测试之前,它运行良好,将每个子模块构建在静态库上会很有用。所以我一直在使用一个看起来像这样的宏:

macro(define_build_unit unit_name unit_root)
  function(${unit_name}_add_sources)
    message(STATUS ${ARGN})
    file(RELATIVE_PATH _relPath ${unit_root} "${CMAKE_CURRENT_SOURCE_DIR}")
    foreach(_src ${ARGN})
      if(_relPath)
        list(APPEND ${unit_name}_SRCS "${_relPath}/${_src}")
      else()
        list(APPEND ${unit_name}_SRCS "${_src}")
      endif()
    endforeach()
    if(_relPath)
      set_property(GLOBAL APPEND PROPERTY ${unit_name}_SRCS ${${unit_name}_SRCS})
    endif()
  endfunction()

  function(${unit_name}_add_link_deps)
    foreach(_dep ${ARGN})
      list(APPEND ${unit_name}_DEPS "${_dep}")
    endforeach()
    set_property(GLOBAL APPEND PROPERTY ${unit_name}_DEPS ${${unit_name}_DEPS})
  endfunction()

  function(${unit_name}_add_include_dirs)
    foreach(_inc ${ARGN})
      list(APPEND ${unit_name}_INC_DIRS "${_inc}")
    endforeach()
    set_property(GLOBAL APPEND PROPERTY ${unit_name}_INC_DIRS ${${unit_name}_INC_DIRS})
  endfunction()
endmacro()

问题是ARGN正在从define_build_unit宏中替换,而不是从相应的函数中替换。我已经尝试了所有宏/功能组合,似乎没有任何效果。

所以,问题是:对于cmake中的变量参数是否有比ARGN全局变量更好的方法?像宏(my_macro args ......)之类的东西?如果没有,有人知道有同样的方法来实现同样的目标吗?

2 个答案:

答案 0 :(得分:3)

这个问题已被接受,但在我的情况下,我确实需要在宏内部具有函数定义。原因?我想以编程方式生成基于宏参数的专用函数。这意味着利用宏的文本替换功能,同时生成一个动态创建的函数,然后可以在构建的其余部分中使用。

macro(build_my_func func_name)
    message(${ARGV})
    function(my_${func_name})
        set(func_ARGV ARGV)
        message(${${func_ARGV}})
    endfunction()
endmacro()

"技巧"是在包含要访问的变量的NAME的函数内设置变量,在本例中为ARGV。然后,它可以作为变量变量访问,即:${${func_ARGV}}。在这个例子中,内部变量${func_ARGV}被替换为ARGV,最终解析为${ARGV}

这是一个解决方法,但可以是访问外部宏可能会压出的任何变量的有用方法。它还可以用于将宏参数缓存为要在函数中使用的值以自定义其行为。

答案 1 :(得分:1)

将外部宏也更改为function

来自CMake macro documentation

  

请注意,宏的参数和ARGN等值不是   通常的CMake意义上的变量。它们很多都是字符串替换   就像C预处理器可以用宏做的那样。

这意味着,在实例化宏时,宏中的${ARGN}引用的所有将被宏的参数替换。对于嵌套函数内的任何事件,尤其如此。

宏是一种奇怪的野兽,因为它们的语法表明它们像普通函数一样工作,但它们处理参数的机制与通常的CMake变量完全不同。如果可以的话,你应尽可能坚持functions以避免这些陷阱。

function(build_my_function func_name)
    message(${ARGV})
    function(my_${func_name})
        message(${ARGV})
    endfunction()
endfunction()

build_my_function(foo bar)  # prints "foobar", the arguments to the outer function
my_foo(baz)                 # prints "baz", the arguments to the inner function