What is the best way to join a list in CMake into a string?
By joining I mean convert SET(somelist "a" "b" "c\;c") to "a:b:c;c" where the glue string (":") is choosable. The following code works but it is REALLY long, is there a better way?
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"
Unfortunately using STRING(REPLACE ...) does not work:
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"
Usually this task is solved with simple string REPLACE
command. You can find a number of such replaces in scripts coming with cmake. But if you really need to care about semicolons inside you values, then you can use the following code:
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
CMake 3.12 is poised to finally add this upstream:
https://github.com/Kitware/CMake/commit/a58158727be4585f9fd71449e9cc9e801c59a009
https://github.com/Kitware/CMake/commit/689eeb67cb87a9ed1d91a4971806488d00e68f42
You can use the string REPLACE function:
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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With