我一直在使用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()
问题是ARGN正在从define_build_unit宏中替换,而不是从相应的函数中替换。我已经尝试了所有宏/功能组合,似乎没有任何效果。
所以,问题是:对于cmake中的变量参数是否有比ARGN全局变量更好的方法?像宏(my_macro args ......)之类的东西?如果没有,有人知道有同样的方法来实现同样的目标吗?
答案 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