如何将CMake以分号分隔的列表转换为换行符分隔?

时间:2017-01-13 11:33:53

标签: cmake

E.g:

set (txt "Hello" "There" "World")
# TODO
message (txt) # Prints "Hello\nThere\nWorld" (i.e. each list item on a new line

我应该代替TODO?

2 个答案:

答案 0 :(得分:5)

CMake的列表以分号分隔。因此"Hello" "There" "World"在内部表示为Hello;There;World。因此,一个简单的解决方案是用换行符替换分号:

string (REPLACE ";" "\n" txt "${txt}")

这适用于此示例,但是让我们尝试一个更复杂的示例:

set (txt "" [[\;One]] "Two" [[Thre\;eee]] [[Four\\;rrr]])

[[ ]]是一个原始字符串,因此\将被传递到列表的CMake内部表示中不变。内部表示为:;\;One;Two;Thre\;eee;Four\\;rrr。我们希望它能打印出来:

<blank line>
;One
Two
Thre;eee
Four\\;rrr

我实际上并非100%确定Four\\;rrr,但我认为这是正确的。无论如何,我们实际上得到了这个:

<blank line>
\
One
Two
Thre\
eee
Four\\
rrr

这是因为它不知道不转换转义的实际分号。解决方案是使用正则表达式:

string (REGEX REPLACE "[^\\\\];" "\\1\n" txt "${txt}")

即。如果前面有非;字符(并将该字符放在替换中),则仅替换\几乎有效,但它不处理第一个空元素,因为分号前面没有任何内容。最后的答案是允许字符串的开始:

string (REGEX REPLACE "(^|[^\\\\]);" "\\1\n" txt "${txt}")

哦,\\\\是因为CMake处理字符串文字而另一个级别的转义被正则表达式引擎删除。你也可以这样做:

string (REGEX REPLACE [[(^|[^\\]);]] "\\1\n" txt "${txt}")

但我不认为这更清楚。

也许有一种比这更简单的方法,但我无法找到它。无论如何,女士们,先生们,为什么你不应该使用字符串作为你唯一的类型,或者做带内字符串分隔。不过,可能会更糟 - 至少他们没有像Bash那样使用空格作为分隔符!

答案 1 :(得分:2)

我只是想添加一些替代方案,我只是使用message()确实在最后放置换行的事实:

  1. 只需使用for_each()迭代列表:

    set (txt "Hello" "There" "World")
    foreach(line IN LISTS txt)
        message("${line}")
    endforeach() 
    
  2. 基于function()的替代方案,我提出看起来更复杂:

    function(message_cr line)
        message("${line}")
        if (ARGN)
            message_cr(${ARGN})
        endif()
    endfunction()        
    
    set(txt "Hello" "There" "World")
    message_cr(${txt})
    
  3. 这些方法的更通用版本如下:

    1. for_each()字符串

      set(txt "Hello" "There" "World")
      foreach(line IN LISTS txt)
          string(APPEND multiline "${line}\n")
      endforeach() 
      message("${multiline}")
      
    2. function()字符串

      function(stringify_cr var line)
          if (ARGN)
              stringify_cr(${var} ${ARGN})
          endif()
          set(${var} "${line}\n${${var}}" PARENT_SCOPE)
      endfunction()
      
      set(txt "Hello" "There" "World")
      stringify_cr(multiline ${txt})
      message(${multiline})
      
    3. 如果您不喜欢最后添加的换行符,请添加string(STRIP "${multiline}" multiline)