Передача списка в макрос CMake - PullRequest
40 голосов
/ 09 марта 2011

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

Код:

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

Ответы [ 4 ]

58 голосов
/ 10 марта 2011

Заключайте переменную в кавычки при передаче ее в макрос:

FindLibs("${LIBRARY_NAMES_LIST}")
8 голосов
/ 01 мая 2014

Ваш макрос должен выглядеть так:

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

6 голосов
/ 30 мая 2015

Ответы других участников верны. Лучшее решение - это предоставить список в двойных кавычках:

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 вызван с неверными аргументами для макроса с именем: 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} )

Тогда я получу свое сообщение об ошибке:

ошибка: FindLibs: необходим аргумент 'NAMES'.

А здесь ссылка на документацию CMakeParseArguments , если вы хотите узнать больше об этом.

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

1 голос
/ 02 июля 2013

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...