如何在CMake中跨多行拆分字符串?
在我的项目中,我通常有一个策略,就是永远不要在文本文件中创建超过80行的行,这样它们就可以在各种编辑器中轻松编辑(你知道这是怎么回事)。但是有了CMake,我遇到了一个问题,我不知道如何将一个简单的字符串分割成多行,以避免一个巨大的行。考虑这个基本代码:如何在CMake中跨多行拆分字符串?,cmake,Cmake,在我的项目中,我通常有一个策略,就是永远不要在文本文件中创建超过80行的行,这样它们就可以在各种编辑器中轻松编辑(你知道这是怎么回事)。但是有了CMake,我遇到了一个问题,我不知道如何将一个简单的字符串分割成多行,以避免一个巨大的行。考虑这个基本代码: set(MYPROJ_VERSION_MAJOR "1") set(MYPROJ_VERSION_MINOR "0") set(MYPROJ_VERSION_PATCH "0") se
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中的一行拆分为多行而不进行详细处理(multiple
list(APPEND…
或诸如此类)?仍然有点详细,但是如果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
在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}")
它们完全相同。CMake 3.0及更新版本
使用字符串(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和更新版本支持缩进,但如果字符串中没有缩进空格,则无法缩进第二行或后续行
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")
更新CMake 3.0及更新版本: 使用
\
可以继续行。看
CMake版本的可用性:
Debian哮喘病(2013):2.8.9Debian哮喘病后遗症: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可通过和
Windows:cmake-3可通过获得原始问题中的示例仅涉及相对较短的字符串。对于较长的字符串(包括其他答案中给出的示例),a可能更好。从文件中: 开头的括号写为
[
后接零个或多个=
后接[
。相应的结尾括号写为]
后接相同数量的=
后接]
。括号不能嵌套。打开和关闭支架可始终选择唯一长度,以包含其他长度的关闭支架
[……]
例如:
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.
]=])```
对于那些从这里带来的人,我想补充一些说明 行延续方法将不起作用,CMake无法解析由空格(缩进)和行延续组成的生成器列表 虽然字符串(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})
要计算使用字符串(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})
字符串(混凝土墙“$”)
字符串(CONCAT-WERROR“$”)
消息(状态“警告选项:${WALL}${WERROR})
添加编译选项(${WALL}${WERROR})
这可能与我发布答案的问题无关,不幸的是,我回答的问题被错误地标记为该问题的副本
生成器列表的处理和解析方式与字符串不同,因此,必须采取额外的措施将生成器列表拆分为多行。要在代码中保持良好的缩进,只需简单地执行即可
message("These strings " "will all be "
"concatenated. Don't forget "
"your trailing spaces!")
或者直接用
string(CONCAT MYSTR "This and " "that "
"and me too!")
就像世卫组织有更多细节一样。然而,我认为这可能只是总结了要点。CMake 3.0方法的问题在于它没有忽略缩进。这意味着多行字符串不能与代码的其余部分缩进。@void.pointer我遇到了同样的问题,您是否知道如何使用多行缩进?另外,如果要使用缩进并限制为80个字符,则另一种方法是这样做:
消息(“这是变量的值:
”${varValue}“
对于非常长的行,变量名后面的换行符甚至进一步改进了这种模式(在本例中不需要)。当然,猜测字符串中的双引号也需要用反斜杠转义是正确的,任何需要在字符串中显示为字符的反斜杠也需要用反斜杠转义吗?@JonathanLeffler是的,它们需要转义。语言规则如下:但确实令人困惑。另请参阅:如果我理解正确,请参阅e source还将在字符串中引入换行符。例如,“长度1”后面将有一个“\n”。有什么办法可以避免吗?没错,会有\n
s。如果你不想这样,我不认为括号参数是你的解决方案。顺便说一句,它适用于3.x版,而不是2.xIt版。我可能值得在链接的“副本”上发布此答案的版本。这就是我遇到它时一直在寻找的答案。
message("These strings " "will all be "
"concatenated. Don't forget "
"your trailing spaces!")
string(CONCAT MYSTR "This and " "that "
"and me too!")