我一直在一个使用 cmake 的软件项目中工作,其中文件结构如下所示:
每个文件夹都包含一个 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()
Run Code Online (Sandbox Code Playgroud)
问题是 ARGN 是从 Define_build_unit 宏中替换的,而不是从相应的函数中替换的。我已经尝试了宏/函数的所有组合,但似乎没有任何效果。
所以,问题是:cmake 中的变量参数是否有比 ARGN 全局变量更好的方法?像宏(my_macro args ...)之类的东西?如果没有,有人知道完成相同任务的等效方法吗?
小智 6
这个问题已经被接受,但是,就我而言,我确实需要在宏内部包含函数定义。原因?我想根据宏参数以编程方式生成专用函数。这意味着利用宏的文本替换功能,同时生成动态创建的函数,然后可以在构建的其余部分中使用该函数。
macro(build_my_func func_name)
message(${ARGV})
function(my_${func_name})
set(func_ARGV ARGV)
message(${${func_ARGV}})
endfunction()
endmacro()
Run Code Online (Sandbox Code Playgroud)
“技巧”是在函数内设置一个变量,其中包含要访问的变量的名称,在本例中为ARGV。然后,它可以作为变量-变量来访问,即:${${func_ARGV}}。在本例中,内部变量${func_ARGV}被替换为 ARGV,最终解析为${ARGV}。
这是一种解决方法,但可以是访问外部宏可能消除的任何变量的有用方法。它还可用于将宏参数缓存为要在函数中使用的值,以自定义其行为。