我正在尝试编写一个遍历给定库列表的宏。但是,宏中的消息调用仅打印列表的第一项。我在这里做错了什么?
代码:
macro( FindLibs LIBRARY_NAMES_LIST )
message( "inside ${LIBRARY_NAMES_LIST}" )
endmacro()
set( LIBRARY_NAMES_LIST lib1 lib2 lib3)
message( "outside ${LIBRARY_NAMES_LIST}" )
FindLibs(${LIBRARY_NAMES_LIST})
输出:
message( "outside lib1 lib2 lib3" )
message( "inside lib1" )
答案 0 :(得分:56)
在将变量传递给宏时引用变量:
FindLibs("${LIBRARY_NAMES_LIST}")
答案 1 :(得分:8)
您的宏应如下所示:
macro(FindLibs list_var_name)
message( "inside ${${list_var_name}}" )
endmacro()
并像这样调用宏:
FindLibs(LIBRARY_NAMES_LIST)
所以在宏内:${list_var_name} = LIBRARY_NAMES_LIST, ${${list_var_name}} = ${LIBRARY_NAMES_LIST} = your list.
另一个解决方案可能(有些更模糊):
macro(FindLibs)
message( "inside ${ARGN}" )
endmacro()
FindLibs(${LIBRARY_NAMES_LIST})
在第一个解决方案中,只将list-variable的名称传递给宏(一个参数)。在第二个解决方案中,您在调用宏之前展开列表并传递N个参数(N =列表的长度)。
答案 2 :(得分:6)
其他人提供的答案是正确的。确实最好的解决方案是用双引号提供这样的列表:
FindLibs( "${LIBRARY_NAMES_LIST}" )
但是如果你真的不想强迫用户使用双引号并想在你的宏声明中看到LIBRARY_NAMES_LIST
参数,那么我就是这样做的:
macro( FindLibs LIBRARY_NAMES_LIST )
set( _LIBRARY_NAMES_LIST ${LIBRARY_NAMES_LIST} ${ARGN} ) # Merge them together
message( "inside ${_LIBRARY_NAMES_LIST}" )
endmacro()
它会像这样使用(你的期望):
FindLibs( ${LIBRARY_NAMES_LIST} )
这很好,因为它会强制用户提供至少一个库。称之为
FindLibs()
不起作用。 CMake将报告以下错误:
使用不正确的宏参数调用FindLibs宏,名为:FindLibs
如果您使用的是CMake 2.8.3或更高版本,则另一个选项是使用CmakeParseArguments
,但它需要您在列表前放置一个关键字参数。但这种技术可能是管理多个列表的最简单方法,并提供了高度的灵活性。因此,知道它非常方便。这也是我喜欢的方式。这是如何做到的:
include( CMakeParseArguments )
macro( FindLibs )
set( _OPTIONS_ARGS )
set( _ONE_VALUE_ARGS )
set( _MULTI_VALUE_ARGS NAMES DEPENDS )
cmake_parse_arguments( _FINDLIBS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} )
# Mandatory
if( _FINDLIBS_NAMES )
message( STATUS "inside NAMES=${_FINDLIBS_NAMES}" )
else()
message( FATAL_ERROR "FindLibs: 'NAMES' argument required." )
endif()
# Optional
if( _FINDLIBS_DEPENDS )
message( STATUS "inside DEPENDS=${_FINDLIBS_DEPENDS}" )
endif()
endmacro()
不幸的是,你必须自己执行你的论证,但至少它允许你选择哪些参数是必需的,哪些不是(DEPENDS
在上面的例子中是可选的。)
它会像这样使用:
FindLibs( NAMES ${LIBRARY_NAMES_LIST} )
FindLibs( NAMES ${LIBRARY_NAMES_LIST} DEPENDS ${LIBRARY_DEPENDENCY_LIST} )
# You can change the order
FindLibs( DEPENDS ${LIBRARY_DEPENDENCY_LIST} NAMES ${LIBRARY_NAMES_LIST} )
# You can even build your lists on the fly
FindLibs(
NAMES
zlib
png
jpeg
DEPENDS
otherProject1
otherProject2
)
如果我这样做:
FindLibs()
# or that:
FindLibs( DEPENDS ${LIBRARY_DEPENDENCY_LIST} )
然后我会收到我的自定义错误消息:
错误:FindLibs:需要'NAMES'参数。
如果您想了解更多信息,请点击CMakeParseArguments文档的链接。
我希望它有所帮助: - )
答案 3 :(得分:1)
根据(几乎)current CMake documentation,$ {ARGV}符号应扩展到整个参数列表。这应该可以使呼叫位置更简单。