CMake에서 문자열을 여러 줄로 분할하는 방법은 무엇입니까?


96

일반적으로 프로젝트에는 행 길이가 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 ...)무엇입니까?

답변:


88

CMake 3.0 이상 업데이트 :

줄 연속은 \. 참조 cmake-3.0-문서를

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 백 포트 : 2.8.11
Debian Jessy (2015) : 3.0.2
Ubuntu 14.04 (LTS) : 2.8.12
Ubuntu 15.04 : 3.0.2
Mac OSX : Homebrew를 통해 cmake-3 사용 가능 , MacportsFink
Windows : Chocolatey를 통해 cmake-3 사용 가능


20
CMake 3.0 접근 방식의 문제점은 들여 쓰기를 무시하지 않는다는 것입니다. 즉, 나머지 코드에서는 여러 줄 문자열을 들여 쓸 수 없습니다.
void.pointer

@ void.pointer 같은 문제가 발생했습니다. 여러 줄로 들여 쓰기하는 방법을 알아 냈습니까?
user3667089

또한 들여 쓰기를 사용하고 80 자 제한이있는 경우 다른 방법은 다음과 같이하는 것입니다. <code> message ( "This is the value of the variable :"<br> "$ {varValue}") </ code>
munsingh

54

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 이상 에서는 인용 된 인수의 줄 연속을 지원하지만 문자열에 들여 쓰기 공백이 포함되지 않으면 두 번째 또는 후속 줄을 들여 쓸 수 없습니다.

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")

1
매우 긴 줄의 경우 변수 이름 뒤의 줄 바꿈은이 패턴을 더욱 향상시킵니다 (이 예에서는 필요하지 않음).
sage

호기심 , 또한 백 슬래시로 이스케이프해야하는 문자열이 큰 따옴표를 추측하기 올바른 것, 그래서 백 슬래시가 필요 문자열에서 문자로 표시 않는다?
Jonathan Leffler 2018

@JonathanLeffler 예, 그들은 탈출이 필요합니다. 언어 규칙은 다음과 같습니다. cmake.org/cmake/help/latest/manual/… 하지만 혼란스러워집니다. 참조 : stackoverflow.com/a/40728463
Douglas Royds

9

여전히 약간 장황하지만 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

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}")

그들은 완전히 동일합니다.


5

원래 질문의 예는 상대적으로 짧은 문자열에 관한 것입니다. 더 긴 문자열 (다른 답변에 제공된 예제 포함)의 경우 대괄호 인수 가 더 좋을 수 있습니다. 문서에서 :

개구부 브래킷 기입되어 [제로이어서 이상의 =하였다 [. 해당하는 닫는 대괄호 ]뒤에 같은 번호가 =옵니다 ]. 대괄호는 중첩되지 않습니다. 여는 대괄호와 닫는 대괄호에 다른 길이의 닫는 대괄호를 포함하도록 항상 고유 한 길이를 선택할 수 있습니다.

[...]

예를 들면 :

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.
]=])```

이것을 올바르게 이해하면 소스의 줄 바꿈도 문자열에 줄 바꿈을 도입합니다. 예를 들어 "length 1"뒤에 \ n이 있습니다. 그것을 피할 방법이 있습니까?
Lukas Schmelzeisen

맞습니다 \n. s 가있을 것 입니다. 당신이 그것을 원하지 않는다면 대괄호 인수가 당신의 해결책이라고 생각하지 않습니다.
ingomueller.net

BTW, 2.x가 아닌 3.x 버전에서 유효합니다
Maxim Suslov

4

여기에서 가져온 사람들을 위해 위해 CMake 생성기 표현식을 여러 줄로 어떻게 분할합니까? 몇 가지 메모를 추가하고 싶습니다.

줄 연속 방법은 작동하지 않으며 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})

이것은 제가 답변을 게시하는 질문과 관련이 없을 수 있습니다. 불행히도 제가 답변하는 질문이이 질문의 중복으로 잘못 표시되어 있습니다.

생성자 목록은 문자열과 같은 방식으로 처리 및 구문 분석되지 않으며, 이로 인해 생성자 목록을 여러 줄로 분할하기 위해 취해야하는 추가 조치가 있습니다.


링크 된 "중복"에이 답변의 버전을 게시하는 것도 가치가있을 것입니다. 이것이 제가 그것을 발견했을 때 찾던 대답이었습니다.
Keith Prussing

3

코드에서 좋은 들여 쓰기를 유지하기 위해 간단합니다.

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

또는 직접 문자열을 형성하십시오.

string(CONCAT MYSTR "This and " "that "
                    "and me too!")

더 자세한 내용을 가진 Douglas의 답변 에서와 같이 . 그러나 나는 이것이 본질적인 요점을 요약 할 수 있다고 생각했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.