Подтвердить что ты не робот

Передача списка макросу cmake

Я пытаюсь написать макрос, который проходит через данный список библиотек. Однако вызов сообщения в макросе выводит только первый элемент списка. Что я здесь делаю неправильно?

код:

    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" )
4b9b3361

Ответ 1

Отправьте эту переменную, передавая ее макросу:

FindLibs("${LIBRARY_NAMES_LIST}")

Ответ 2

Ваш макрос должен выглядеть следующим образом:

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 = длина списка).

Ответ 3

Предоставленные ответы другими являются правильными. Лучшим решением является предоставление списка в двойных кавычках, подобных этому 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 документацию, если вы хотите узнать больше об этом.

Я надеюсь, что это поможет: -)

Ответ 4

Согласно (почти) текущей документации CMake, символ ${ARGV} должен быть расширен во весь список аргументов. Это должно упростить порядок в вызывающем местоположении.