web-dev-qa-db-fra.com

Passer une liste à une macro CMake

J'essaie d'écrire une macro qui passe par une liste donnée de bibliothèques. Toutefois, l'appel de message dans la macro imprime uniquement le premier élément de la liste. Qu'est-ce que je fais mal ici?

Code:

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

Production:

message( "outside lib1 lib2 lib3" )
message( "inside lib1" )
44
Paul

Citez la variable lorsque vous la transmettez à la macro:

FindLibs("${LIBRARY_NAMES_LIST}")
67
Jack Kelly

Les réponses fournies par d'autres sont correctes. La meilleure solution est en effet de fournir la liste entre guillemets comme ceci:

FindLibs( "${LIBRARY_NAMES_LIST}" )

Mais si vous ne voulez vraiment pas forcer l'utilisateur à utiliser des guillemets doubles et que vous souhaitez également voir le LIBRARY_NAMES_LIST argument dans votre déclaration de macro, voici comment je le ferais:

macro( FindLibs LIBRARY_NAMES_LIST )
    set( _LIBRARY_NAMES_LIST ${LIBRARY_NAMES_LIST} ${ARGN} ) # Merge them together
    message( "inside ${_LIBRARY_NAMES_LIST}" )
endmacro()

Et il serait utilisé comme ceci (votre attente):

FindLibs( ${LIBRARY_NAMES_LIST} )

C'est bien, car cela obligera l'utilisateur à fournir au moins une bibliothèque. L'appeler comme

FindLibs()

ne fonctionnera pas. CMake signalera l'erreur suivante:

Macro FindLibs invoquée avec des arguments incorrects pour la macro nommée: FindLibs

Si vous utilisez CMake 2.8.3 ou une version plus récente, une autre option consiste à utiliser le CmakeParseArguments, mais il vous faudra mettre un argument mot-clé devant votre liste. Mais cette technique est probablement le moyen le plus simple de gérer plusieurs listes , et offre une grande flexibilité. Pour cette raison, il est très pratique de le savoir. C'est aussi ma façon préférée de le faire. Voici comment procéder:

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

Malheureusement, vous devez faire vous-même l'application de vos arguments, mais au moins cela vous donne la possibilité de choisir quels arguments sont obligatoires et lesquels ne le sont pas (DEPENDS est facultatif dans mon exemple ci-dessus).

Et il serait utilisé comme ceci:

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
)

Et si je fais ça:

FindLibs()

# or that:
FindLibs( DEPENDS ${LIBRARY_DEPENDENCY_LIST} )

Ensuite, je recevrais mon message d'erreur personnalisé:

erreur: FindLibs: Argument 'NAMES' requis.

Et voici le lien vers la documentation CMakeParseArguments si vous voulez en savoir plus.

J'espère que ça aide :-)

8
mchiasson

Votre macro devrait ressembler à ceci:

macro(FindLibs list_var_name)            
    message( "inside ${${list_var_name}}" )
endmacro()

et appelez la macro comme ceci:

FindLibs(LIBRARY_NAMES_LIST)

Donc à l'intérieur de la macro: ${list_var_name} = LIBRARY_NAMES_LIST, ${${list_var_name}} = ${LIBRARY_NAMES_LIST} = your list.

Une autre solution pourrait être (un peu plus obscure):

macro(FindLibs)            
    message( "inside ${ARGN}" )
endmacro()

FindLibs(${LIBRARY_NAMES_LIST})

Dans la première solution, vous ne passez que le nom de la variable de liste à la macro (un argument). Dans la deuxième solution, vous développez la liste avant d'appeler la macro et passez N paramètres (N = longueur de la liste).

8
tamas.kenez

Selon (presque) documentation CMake actuelle , le symbole $ {ARGV} devrait s'étendre à toute la liste des arguments. Cela devrait simplifier les choses à l'emplacement appelant.

1
John