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

如何在cmake中定义宏内部的函数,cmake,Cmake,我一直在一个使用cmake的软件项目中工作,其中的文件结构如下所示: 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})

我一直在一个使用cmake的软件项目中工作,其中的文件结构如下所示:

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()
  • 克马克
  • 测验
  • 建造
  • src
    • 模块1
    • 模块2
    • 模块3
      • 子模块1
      • 子模块2
        • 恳求
          • 后端1
          • 后端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\u build\u unit宏替换的,而不是从相应的函数替换的。我尝试了所有宏/函数的组合,但似乎没有任何效果


所以,问题是:cmake中的变量参数是否有比ARGN全局变量更好的方法?类似宏(my_宏参数…)的东西?如果没有,是否有人知道实现相同功能的等效方法?

将外部宏也更改为
函数

从CMake:

请注意,宏的参数和ARGN等值不可用 通常CMake意义上的变量。它们是字符串的替代品 就像C预处理器处理宏一样

这意味着,在实例化宏时,宏中对
${ARGN}
的所有引用都将替换为宏的参数。对于嵌套函数中的任何引用,这一点尤其正确

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

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

这个问题已经被接受了,但是,在我的例子中,我确实需要在宏中定义函数。原因是什么?我想根据宏参数以编程方式生成专门的函数。这意味着利用宏的文本替换功能,同时生成一个动态创建的函数,该函数可以在构建的其余部分中使用

macro(build_my_func func_name)
    message(${ARGV})
    function(my_${func_name})
        set(func_ARGV ARGV)
        message(${${func_ARGV}})
    endfunction()
endmacro()
“技巧”是在函数中设置一个变量,该变量包含要访问的变量的名称,在本例中为
ARGV
。然后,它可以作为变量访问,即:
${${func_ARGV}}
。在本例中,内部变量
${func_ARGV}
被ARGV替换,最终解析为
${ARGV}

这是一个有点变通的方法,但对于访问外部宏可能消除的任何变量来说,它都是一种有用的方法。它还可用于将宏参数缓存为值,以便在函数中用于自定义其行为