如何在CMake中跨多行拆分字符串?

时间:2011-10-03 16:03:51

标签: cmake

我的项目中通常有一个策略,永远不会在超过80行的文本文件中创建行,因此它们可以在各种编辑器中轻松编辑(你知道这笔交易)。但是使用CMake我遇到的问题是我不知道如何将一个简单的字符串拆分成多行来避免一条巨大的线。请考虑以下基本代码:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
set(MYPROJ_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_EXTRA}")

它已经超过80行限制。那么如何将CMake中的一行分成多行而不会变得冗长(多个list(APPEND ...)之类)?

7 个答案:

答案 0 :(得分:66)

更新 CMake 3.0及更新

\可以继续行。见cmake-3.0-doc

message("\
This is the first line of a quoted argument. \
In fact it is the only line but since it is long \
the source code uses line continuation.\
")

CMake版本的可用性:

Debian Wheezy(2013):2.8.9
Debian Wheezy-backports:2.8.11
Debian Jessy(2015):3.0.2
Ubuntu 14.04(LTS):2.8.12
Ubuntu 15.04:3.0.2
Mac OSX:cmake-3可通过HomebrewMacportsFink提供 Windows:cmake-3可通过Chocolatey

获取

答案 1 :(得分:43)

CMake 3.0及更新版

使用string(CONCAT)命令:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
string(CONCAT MYPROJ_VERSION "${MYPROJ_VERSION_MAJOR}"
                             ".${MYPROJ_VERSION_MINOR}"
                             ".${MYPROJ_VERSION_PATCH}"
                             "-${MYPROJ_VERSION_EXTRA}")

虽然CMake 3.0和更新版支持line continuation of quoted arguments,但如果没有获得字符串中包含的缩进空格,则无法缩进第二行或后续行。

CMake 2.8及更早版

您可以使用列表。列表的每个元素都可以放在一个新行上:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
set(MYPROJ_VERSION_LIST "${MYPROJ_VERSION_MAJOR}"
                        ".${MYPROJ_VERSION_MINOR}"
                        ".${MYPROJ_VERSION_PATCH}"
                        "-${MYPROJ_VERSION_EXTRA}")

没有引号的列表连接在一起,没有空格:

message(STATUS "Version: " ${MYPROJ_VERSION_LIST})
-- Version: 1.0.0-rc1

如果您确实需要字符串,可以先将列表转换为字符串:

string(REPLACE ";" "" MYPROJ_VERSION "${MYPROJ_VERSION_LIST}")
message(STATUS "Version: ${MYPROJ_VERSION}")
-- Version: 1.0.0-rc1

原始字符串中的任何分号都将被视为列表元素分隔符,并被删除。他们必须逃脱:

set(MY_LIST "Hello World "
            "with a \;semicolon")

答案 2 :(得分:8)

它仍然有点冗长,但是如果80个字符限制真的让你烦恼,那么你可以反复追加到同一个变量:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
set(MYPROJ_VERSION "${MYPROJ_VERSION_MAJOR}.")
set(MYPROJ_VERSION "${MYPROJ_VERSION}${MYPROJ_VERSION_MINOR}.")
set(MYPROJ_VERSION "${MYPROJ_VERSION}${MYPROJ_VERSION_PATCH}-")
set(MYPROJ_VERSION "${MYPROJ_VERSION}${MYPROJ_VERSION_EXTRA}")
message(STATUS "version: ${MYPROJ_VERSION}")

提供输出:

$ cmake  ~/project/tmp
-- version: 1.0.0-rc1
-- Configuring done
-- Generating done
-- Build files have been written to: /home/rsanderson/build/temp

答案 3 :(得分:7)

无法在CMakeLists.txt文件或CMake脚本中跨多行拆分字符串文字。如果在字符串中包含换行符,则字符串本身将有一个文字换行符。

# Don't do this, it won't work, MYPROJ_VERSION will contain newline characters:
set(MYPROJ_VERSION "${VERSION_MAJOR}.
  ${VERSION_MINOR}.${VERSION_PATCH}-
  ${VERSION_EXTRA}")

但是,CMake使用空格来分隔参数,因此您可以将任何参数分隔符的空格更改为您想要的换行符,而不会更改行为。

你可以重新说出这条较长的一行:

set(MYPROJ_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_EXTRA}")

这两条较短的一行:

set(MYPROJ_VERSION
  "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_EXTRA}")

它们完全等效。

答案 4 :(得分:6)

对于那些从How do I split a CMake generator expression to multiple lines?带到这里的人,我想补充一些笔记。

行连续方法无效,CMake无法解析使用空格(缩进)和行连续组成的生成器列表。

虽然string(CONCAT)解决方案将提供一个可以求值的生成器表达式,但是如果结果包含空格,则求值表达式将用引号引起来。

对于要添加的每个单独选项,必须构造一个单独的生成器列表,因此像我在下面所做的那样堆叠选项将导致构建失败:

string(CONCAT WARNING_OPTIONS "$<"
    "$<OR:"
        "$<CXX_COMPILER_ID:MSVC>,"
        "$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>"
    ">:"
    "/D_CRT_SECURE_NO_WARNINGS "
">$<"
    "$<AND:"
        "$<CXX_COMPILER_ID:Clang,GNU>,"
        "$<NOT:$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>"
    ">:"
    "-Wall -Werror "
">$<"
    "$<CXX_COMPILER_ID:GNU>:"
    "-Wno-multichar -Wno-sign-compare "
">")
add_compile_options(${WARNING_OPTIONS})

这是因为生成的选项以引号传递给编译器

/usr/lib64/ccache/c++  -DGTEST_CREATE_SHARED_LIBRARY=1 -Dgtest_EXPORTS -I../ThirdParty/googletest/googletest/include -I../ThirdParty/googletest/googletest -std=c++11 -fno-rtti -fno-exceptions -fPIC    -std=c++11 -fno-rtti -fno-exceptions -Wall -Wshadow -DGTEST_HAS_PTHREAD=1 -fexceptions -Wextra -Wno-unused-parameter -Wno-missing-field-initializers "-Wall -Werror -Wno-multichar -Wno-sign-compare " -fdiagnostics-color -MD -MT ThirdParty/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o -MF ThirdParty/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o.d -o ThirdParty/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o -c ../ThirdParty/googletest/googletest/src/gtest-all.cc
c++: error: unrecognized command line option ‘-Wall -Werror -Wno-multichar -Wno-sign-compare ’

要计算使用string(CONCAT)解决方案表示的冗长的生成器表达式,每个生成器表达式必须求值为单个选项,且不带空格:

string(CONCAT WALL "$<"
    "$<AND:"
        "$<CXX_COMPILER_ID:Clang,GNU>,"
        "$<NOT:$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>"
    ">:"
    "-Wall"
">")
string(CONCAT WERROR "$<"
    "$<AND:"
        "$<CXX_COMPILER_ID:Clang,GNU>,"
        "$<NOT:$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>"
    ">:"
    "-Werror"
">")
message(STATUS "Warning Options: " ${WALL} ${WERROR})
add_compile_options(${WALL} ${WERROR})

这可能与我要发布答案的问题无关,不幸的是,我正在回答的问题被错误地标记为该问题的重复项。

生成器列表的处理和解析方式与字符串不同,因此,必须采取其他措施才能将生成器列表分成多行。

答案 5 :(得分:3)

要在代码中保持良好的缩进,只需执行以下操作即可

message("These strings " "will all be "
        "concatenated. Don't forget "
        "your trailing spaces!")

或直接与

组成字符串
string(CONCAT MYSTR "This and " "that "
                    "and me too!")

,如Douglas' answer中所述,他具有更多详细信息。但是我认为这可能只是要点。

答案 6 :(得分:2)

原始问题中的示例仅涉及相对较短的字符串。对于更长的字符串(包括其他答案中给出的示例),bracket argument可能更好。从文档中:

  

[后面加一个括号,后接零个或多个=,后跟[。相应的右括号写成],后跟相同数量的=,后跟]。支架不嵌套。总是可以选择一个唯一的长度作为开括号和闭括号,以包含其他长度的闭括号。

     

[...]

     

例如:

message([=[
This is the first line in a bracket argument with bracket length 1.
No \-escape sequences or ${variable} references are evaluated.
This is always one argument even though it contains a ; character.
The text does not end on a closing bracket of length 0 like ]].
It does end in a closing bracket of length 1.
]=])```