【问题标题】:How to define function inside macro in cmake如何在cmake中定义宏内的函数
【发布时间】:2014-06-14 23:06:26
【问题描述】:

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

  • cmake
  • 测试
  • 构建
    • 模块1
    • 模块2
    • 模块3
      • submod1
      • submod2
        • 实现
          • 后端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_build_unit 宏中替换的,而不是从相应的函数中替换的。我已经尝试了所有宏/函数的组合,但似乎没有任何效果。

所以,问题是:cmake 中的变量参数是否有比 ARGN 全局变量更好的方法?像宏(my_macro args ...)之类的东西?如果没有,有人知道完成相同任务的等效方法吗?

【问题讨论】:

    标签: cmake


    【解决方案1】:

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

    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}

    这是一种解决方法,但对于访问外部宏可能删除的任何变量可能是一种有用的方法。它还可以用于将宏参数作为值缓存在函数中以自定义其行为。

    【讨论】:

      【解决方案2】:

      将外部宏也更改为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
      

      【讨论】:

        猜你喜欢
        • 2011-10-09
        • 1970-01-01
        • 2014-08-09
        • 1970-01-01
        • 1970-01-01
        • 2020-11-22
        • 1970-01-01
        • 1970-01-01
        • 2018-11-12
        相关资源
        最近更新 更多