Ответ 1
Отправьте эту переменную, передавая ее макросу:
FindLibs("${LIBRARY_NAMES_LIST}")
Я пытаюсь написать макрос, который проходит через данный список библиотек. Однако вызов сообщения в макросе выводит только первый элемент списка. Что я здесь делаю неправильно?
код:
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" )
Отправьте эту переменную, передавая ее макросу:
FindLibs("${LIBRARY_NAMES_LIST}")
Ваш макрос должен выглядеть следующим образом:
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 = длина списка).
Предоставленные ответы другими являются правильными. Лучшим решением является предоставление списка в двойных кавычках, подобных этому 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 Macro invoked with incorrect arguments for macro named: 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} )
Затем я получаю свое сообщение об ошибке:
error: FindLibs: 'NAMES' argument required.
И вот ссылка на CMakeParseArguments документацию, если вы хотите узнать больше об этом.
Я надеюсь, что это поможет: -)
Согласно (почти) текущей документации CMake, символ ${ARGV} должен быть расширен во весь список аргументов. Это должно упростить порядок в вызывающем местоположении.