将列表传递给CMake宏

ljsrvy3e  于 2022-11-11  发布在  其他
关注(0)|答案(4)|浏览(216)

我试图写一个宏,它遍历一个给定的库列表。然而,宏中的消息调用只打印列表的第一项。我在这里做错了什么?
编码:

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" )
a6b3iqyw

a6b3iqyw1#

在将变量传递给宏时,将变量用引号括起来:

FindLibs("${LIBRARY_NAMES_LIST}")
gajydyqb

gajydyqb2#

其他人提供的答案是正确的。最好的解决方案确实是用双引号提供如下列表:

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宏时使用了不正确的参数,宏名为:查找库
如果你使用的是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} )

然后,我会收到我的自定义错误消息:
错误:查找库:需要'NAMES'参数。
如果您想了解更多有关CMakeParseArguments文档的信息,请单击此处的链接。
我希望这能有所帮助:-)

dxpyg8gm

dxpyg8gm3#

您的宏应如下所示:

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})

在第一个解决方案中,只将列表变量的名称传递给宏(一个参数)。在第二个解决方案中,在调用宏之前展开列表,并传递N个参数(N =列表的长度)。

6tr1vspr

6tr1vspr4#

根据(几乎)当前的CMake文档,${ARGV}符号应该扩展到整个参数列表。这应该使调用位置的事情变得更简单。

相关问题