2011-08-24 94 views
12

將CMake中的列表加入字符串的最佳方式是什麼?在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" 

回答

10

通常這個任務是解決簡單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 
6

可以使用string 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" 
+0

哦,是的,謝謝,這工作。但是這是否意味着我不能擁有一個元素包含分號的列表? – Geli

+1

我更新了問題以包含一個含有分號的元素的列表。 – Geli

+0

您原來的函數JOIN也無法處理分號。它使用cmake 2.8.5在Windows下輸出「a:b:cc」。 – sakra

5

的答案是好的,當你不使用分號或當你可以(並且要)逃生他們。 我不想逃避分號,所以我寫了下面的功能:

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'