Подтвердить что ты не робот

Как разделить строки на несколько строк в 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 ...) или тому подобное)?

4b9b3361

Ответ 1

Обновление для 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 доступен через Homebrew, Macports и Fink
Windows: cmake-3 доступен через Chocolatey

Ответ 2

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

Ответ 3

Это все еще немного подробный, но если ограничение 80 char действительно вызывает ошибки, вы можете многократно добавлять к одной и той же переменной:

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

Ответ 4

Невозможно разбить строковый литерал на несколько строк в файлах 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

Пример в оригинальном вопросе касается только относительно короткой строки. Для более длинных строк (включая примеры, приведенные в других ответах) аргумент в скобках может быть лучше. Из документации:

Открывающая скобка написана [, за которой следует ноль или более =, а затем [. Соответствующая закрывающая скобка написана ], за которой следует то же число =, за которым следует ]. Скобы не гнездятся. Всегда можно выбрать уникальную длину для открывающих и закрывающих скобок, чтобы они содержали закрывающие скобки другой длины.

[...]

For example:

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