Лучший / самый короткий способ присоединиться к списку в CMake - PullRequest
13 голосов
/ 24 августа 2011

Каков наилучший способ объединить список в CMake в строку?

Под объединением я подразумеваю преобразование SET (somelist "a" "b" "c \; c") в "a: b: c; c", где можно выбрать строку склейки (":").Следующий код работает, но он ДЕЙСТВИТЕЛЬНО длинный, есть ли лучший способ?

FUNCTION(JOIN LISTNAME GLUE OUTPUT)
SET(_TMP_STR "")
  FOREACH(VAL ${${LISTNAME}})
    SET(_TMP_STR "${_TMP_STR}${GLUE}${VAL}")
  ENDFOREACH(VAL ${${LISTNAME}})
  STRING(LENGTH "${GLUE}" GLUE_LEN)
  STRING(LENGTH "${_TMP_STR}" OUT_LEN)
  MATH(EXPR OUT_LEN ${OUT_LEN}-${GLUE_LEN})
  STRING(SUBSTRING "${_TMP_STR}" ${GLUE_LEN} ${OUT_LEN} _TMP_STR) 
  SET(${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
ENDFUNCTION()

#USAGE:
SET(somelist "a" "b" "c\;c")
JOIN(somelist ":" output)
MESSAGE("${output}") # will output "a:b:c;c"

К сожалению, использование STRING (REPLACE ...) не работает:

function(JOINSTRREPLACE VALUES GLUE OUTPUT)
  string (REPLACE ";" "${GLUE}" _TMP_STR "${VALUES}")
  set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
endfunction()
JOINSTRREPLACE("${somelist}" ":" output)
MESSAGE(${output}) # will output "a:b:c\:c"

Ответы [ 4 ]

10 голосов
/ 27 августа 2011

Обычно эта задача решается с помощью простой команды string REPLACE. Вы можете найти множество таких замен в скриптах, поставляемых с cmake. Но если вам действительно нужно позаботиться о точках с запятой внутри ваших значений, то вы можете использовать следующий код:

function(JOIN VALUES GLUE OUTPUT)
  string (REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}")
  string (REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping
  set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
endfunction()

SET( letters "" "\;a" b c "d\;d" )
JOIN("${letters}" ":" output)
MESSAGE("${output}") # :;a:b:c:d;d
7 голосов
/ 31 марта 2018
6 голосов
/ 24 августа 2011

Вы можете использовать строку REPLACE :

function(JOIN VALUES GLUE OUTPUT)
  string (REPLACE ";" "${GLUE}" _TMP_STR "${VALUES}")
  set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
endfunction()

#USAGE:
SET(somelist a b c)
JOIN("${somelist}" ":" output)
MESSAGE("${output}") # will output "a:b:c"
5 голосов
/ 05 августа 2015

Ответы выше нормальны, когда вы не используете точки с запятой или когда вы можете (и хотите) избежать их.Я предпочитаю не использовать точку с запятой, поэтому я написал следующую функцию:

function(JOIN OUTPUT GLUE)
    set(_TMP_RESULT "")
    set(_GLUE "") # effective glue is empty at the beginning
    foreach(arg ${ARGN})
        set(_TMP_RESULT "${_TMP_RESULT}${_GLUE}${arg}")
        set(_GLUE "${GLUE}")
    endforeach()
    set(${OUTPUT} "${_TMP_RESULT}" PARENT_SCOPE)
endfunction()

Преимущество состоит в том, что список может быть пустым и не обязательно должен быть в переменной (но может быть записан вместо вызова).

Использование:

set(SOME_LIST a b c d)
join(RESULT "/" ${SOME_LIST})
message(STATUS "RESULT='${RESULT}'") # outputs RESULT='a/b/c/d'
# or
join(RESULT " " e f g h)
message(STATUS "RESULT='${RESULT}'") # outputs RESULT='e f g h'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...