guia - Pasar una lista a una macro CMake
qgis manual (4)
Estoy tratando de escribir una macro que pasa por una lista dada de bibliotecas. Sin embargo, la llamada al mensaje en la macro solo imprime el primer elemento de la lista. ¿Qué estoy haciendo mal aquí?
Código:
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})
Salida:
message( "outside lib1 lib2 lib3" )
message( "inside lib1" )
Cita la variable a medida que la pasas a la macro:
FindLibs("${LIBRARY_NAMES_LIST}")
De acuerdo con la documentación CMake (casi) actual , el símbolo $ {ARGV} debería expandirse a toda la lista de argumentos. Esto debería simplificar las cosas en la ubicación de la llamada.
Las respuestas provistas por otros son correctas. La mejor solución es proporcionar la lista entre comillas dobles como esta:
macro( FindLibs LIBRARY_NAMES_LIST )
set( _LIBRARY_NAMES_LIST ${LIBRARY_NAMES_LIST} ${ARGN} ) # Merge them together
message( "inside ${_LIBRARY_NAMES_LIST}" )
endmacro()
Pero si realmente no desea obligar al usuario a usar comillas dobles y también desea ver el argumento LIBRARY_NAMES_LIST
en su declaración de macro, así es como lo haría:
FindLibs( ${LIBRARY_NAMES_LIST} )
Y se usaría así (su expectativa):
FindLibs()
Esto es bueno, porque obligará al usuario a proporcionar al menos una biblioteca. Llamarlo como
FindLibs Macro invoked with incorrect arguments for macro named: FindLibs
no funcionará CMake informará el siguiente error:
FindLibs Macro invocada con argumentos incorrectos para macro llamada: FindLibs
Si está utilizando CMake 2.8.3 o posterior, otra opción es usar CmakeParseArguments
, pero requerirá poner un argumento de palabra clave en frente de su lista. Pero esta técnica es probablemente la forma más fácil de administrar más de una lista , y proporciona una gran flexibilidad. Por esa razón, es muy útil saberlo. También es mi forma preferida de hacerlo. He aquí cómo hacerlo:
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()
Desafortunadamente, usted tiene que hacer su aplicación de argumento usted mismo, pero al menos le da la opción de elegir qué argumentos son obligatorios y cuáles no ( DEPENDS
es opcional en mi ejemplo anterior).
Y se usaría así:
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
)
Y si hago esto:
FindLibs()
# or that:
FindLibs( DEPENDS ${LIBRARY_DEPENDENCY_LIST} )
Entonces obtendría mi mensaje de error personalizado:
error: FindLibs: se requiere el argumento ''NAMES''.
Y aquí el enlace a la documentación CMakeParseArguments si desea obtener más información al respecto.
Espero que ayude :-)
Tu macro debería verse así:
macro(FindLibs list_var_name)
message( "inside ${${list_var_name}}" )
endmacro()
y llame a la macro de esta manera:
FindLibs(LIBRARY_NAMES_LIST)
Entonces dentro de la macro: ${list_var_name} = LIBRARY_NAMES_LIST, ${${list_var_name}} = ${LIBRARY_NAMES_LIST} = your list.
Otra solución podría ser (algo más oscura):
macro(FindLibs)
message( "inside ${ARGN}" )
endmacro()
FindLibs(${LIBRARY_NAMES_LIST})
En la primera solución, solo pasa el nombre de la variable de lista a la macro (un argumento). En la segunda solución, expande la lista antes de llamar a la macro y pasar los parámetros N (N = longitud de la lista).