Spec-Zone.ru › CMake 3.22

cmake_path

Новое в версии 3.20.

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

Примечание

Команда cmake_path обрабатывает пути в формате системы сборки (т. е. хост-платформы), а не целевой системы. При кросс-компиляции, если путь содержит элементы, которые не могут быть представлены на хост-платформе (например, букву диска, когда хост — не Windows), результаты будут непредсказуемыми.

Резюме

Conventions

Path Structure And Terminology

Normalization

Decomposition
  cmake_path(GET <path-var> ROOT_NAME <out-var>)
  cmake_path(GET <path-var> ROOT_DIRECTORY <out-var>)
  cmake_path(GET <path-var> ROOT_PATH <out-var>)
  cmake_path(GET <path-var> FILENAME <out-var>)
  cmake_path(GET <path-var> EXTENSION [LAST_ONLY] <out-var>)
  cmake_path(GET <path-var> STEM [LAST_ONLY] <out-var>)
  cmake_path(GET <path-var> RELATIVE_PART <out-var>)
  cmake_path(GET <path-var> PARENT_PATH <out-var>)

Query
  cmake_path(HAS_ROOT_NAME <path-var> <out-var>)
  cmake_path(HAS_ROOT_DIRECTORY <path-var> <out-var>)
  cmake_path(HAS_ROOT_PATH <path-var> <out-var>)
  cmake_path(HAS_FILENAME <path-var> <out-var>)
  cmake_path(HAS_EXTENSION <path-var> <out-var>)
  cmake_path(HAS_STEM <path-var> <out-var>)
  cmake_path(HAS_RELATIVE_PART <path-var> <out-var>)
  cmake_path(HAS_PARENT_PATH <path-var> <out-var>)
  cmake_path(IS_ABSOLUTE <path-var> <out-var>)
  cmake_path(IS_RELATIVE <path-var> <out-var>)
  cmake_path(IS_PREFIX <path-var> <input> [NORMALIZE] <out-var>)
  cmake_path(COMPARE <input1> <OP> <input2> <out-var>)

Modification
  cmake_path(SET <path-var> [NORMALIZE] <input>)
  cmake_path(APPEND <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
  cmake_path(APPEND_STRING <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
  cmake_path(REMOVE_FILENAME <path-var> [OUTPUT_VARIABLE <out-var>])
  cmake_path(REPLACE_FILENAME <path-var> <input> [OUTPUT_VARIABLE <out-var>])
  cmake_path(REMOVE_EXTENSION <path-var> [LAST_ONLY] [OUTPUT_VARIABLE <out-var>])
  cmake_path(REPLACE_EXTENSION <path-var> [LAST_ONLY] <input> [OUTPUT_VARIABLE <out-var>])

Generation
  cmake_path(NORMAL_PATH <path-var> [OUTPUT_VARIABLE <out-var>])
  cmake_path(RELATIVE_PATH <path-var> [BASE_DIRECTORY <input>] [OUTPUT_VARIABLE <out-var>])
  cmake_path(ABSOLUTE_PATH <path-var> [BASE_DIRECTORY <input>] [NORMALIZE] [OUTPUT_VARIABLE <out-var>])

Native Conversion
  cmake_path(NATIVE_PATH <path-var> [NORMALIZE] <out-var>)
  cmake_path(CONVERT <input> TO_CMAKE_PATH_LIST <out-var> [NORMALIZE])
  cmake_path(CONVERT <input> TO_NATIVE_PATH_LIST <out-var> [NORMALIZE])

Hashing
  cmake_path(HASH <path-var> <out-var>)

Соглашения

В данном руководстве по команде используются следующие соглашения:

<path-var>

Всегда имя переменной. Для команд, которые ожидают <path-var> в качестве входных данных, переменная должна существовать и содержать единственный путь.

<input>

Строковая константа, которая может содержать путь, фрагмент пути или несколько путей с особым разделителем, в зависимости от команды. Смотрите описание каждой команды для понимания интерпретации.

<input>...

Ноль или более строковых константных аргументов.

<out-var>

Имя переменной, в которую будет записан результат команды.

Структура пути и терминология

Путь имеет следующую структуру (все компоненты необязательны, с некоторыми ограничениями):

root-name root-directory-separator (item-name directory-separator)* filename
root-name

Идентифицирует корень в файловой системе с несколькими корнями (например, "C:" или "//myserver"). Необязательно.

root-directory-separator

Разделитель каталогов, который, если присутствует, указывает, что этот путь абсолютный. Если его нет, и первый элемент, кроме root-name, является item-name, то путь относительный.

item-name

Последовательность символов, которые не являются разделителями каталогов. Это имя может идентифицировать файл, жёсткую ссылку, символическую ссылку или каталог. Распознаются два специальных случая:

  • Имя элемента, состоящее из одного символа точки ., является именем каталога, ссылающимся на текущий каталог.
  • Имя элемента, состоящее из двух символов точки .., является именем каталога, ссылающимся на родительский каталог.

Приведённая выше схема (...)* указывает, что может быть ноль или более имён элементов, с несколькими элементами, разделёнными directory-separator. Символы ()* не являются частью пути.

directory-separator

Единственный распознаваемый разделитель каталогов — символ слэша /. Если этот символ повторяется, он обрабатывается как один разделитель каталогов. Другими словами, /usr///////lib эквивалентно /usr/lib.

filename

Путь имеет filename, если он не заканчивается на directory-separator. filename фактически является последним item-name пути, поэтому он также может быть жёсткой ссылкой, символической ссылкой или каталогом.

У filename может быть расширение. По умолчанию расширение определяется как подстрока, начинающаяся с левой точки (включая точку) и заканчивающаяся в конце filename. В командах, принимающих ключевое слово LAST_ONLY, LAST_ONLY изменяет интерпретацию на подстроку, начинающуюся с правой точки.

Для вышеприведённой интерпретации существуют следующие исключения:

  • Если первый символ в filename — точка, эта точка игнорируется (т. е. filename типа ".profile" обрабатывается как не имеющее расширения).
  • Если filename — либо ., либо .., у него нет расширения.

Основная часть — это часть filename перед расширением.

Некоторые команды ссылаются на root-path. Это конкатенация root-name и root-directory-separator, каждая из которых может быть пустой. relative-part относится к полному пути с удалёнными root-path.

Создание переменной пути

Хотя путь можно создать с осторожностью, используя обычную команду set(), рекомендуется использовать cmake_path(УСТАНОВИТЬ) вместо этого, так как он автоматически преобразует путь в требуемый вид при необходимости. Подкоманда cmake_path(ДОБАВИТЬ) может быть ещё одним подходящим вариантом, когда путь необходимо построить путём соединения фрагментов. Следующий пример сравнивает три метода построения одного и того же пути:

set(path1 "${CMAKE_CURRENT_SOURCE_DIR}/data")

cmake_path(SET path2 "${CMAKE_CURRENT_SOURCE_DIR}/data")

cmake_path(APPEND path3 "${CMAKE_CURRENT_SOURCE_DIR}" "data")

Модификация и Генерация подкоманды могут либо сохранить результат на месте, либо в отдельной переменной, названной после ключевого слова OUTPUT_VARIABLE. Все остальные подкоманды сохраняют результат в обязательной переменной <out-var>.

Нормализация

Некоторые подкоманды поддерживают нормализацию пути. Алгоритм нормализации пути следующий:

  1. Если путь пустой, остановитесь (нормализованная форма пустого пути — тоже пустой путь).
  2. Замените каждый directory-separator, который может состоять из нескольких разделителей, одним / (/a///b  --> /a/b).
  3. Удалите каждую одиночную точку (.) и любой следующий directory-separator (/a/./b/. --> /a/b).
  4. Удалите каждый item-name (кроме ..), который сразу за ним следует directory-separator и .., вместе с любым directory-separator (/a/b/../c --> a/c).
  5. Если есть root-directory, удалите все .. и любой directory-separators сразу за ними. Родитель корневого каталога обрабатывается как всё ещё корневой каталог (/../a --> /a).
  6. Если последний item-name — .., удалите все trailing directory-separator (../ --> ..).
  7. Если путь пустой на этом этапе, добавьте dot (нормальная форма ./ — .).

Разложение

Следующие формы подкоманды GET извлекают разные компоненты или группы компонентов из пути. См. Структура пути и терминология для определения значения каждого компонента пути.

cmake_path(GET <path-var> ROOT_NAME <out-var>)
cmake_path(GET <path-var> ROOT_DIRECTORY <out-var>)
cmake_path(GET <path-var> ROOT_PATH <out-var>)
cmake_path(GET <path-var> FILENAME <out-var>)
cmake_path(GET <path-var> EXTENSION [LAST_ONLY] <out-var>)
cmake_path(GET <path-var> STEM [LAST_ONLY] <out-var>)
cmake_path(GET <path-var> RELATIVE_PART <out-var>)
cmake_path(GET <path-var> PARENT_PATH <out-var>)

Если запрашиваемый компонент отсутствует в пути, в <out-var> будет храниться пустая строка. Например, только системы Windows имеют понятие root-name, поэтому при работе на не-Windows машинах подкоманда ROOT_NAME всегда возвращает пустую строку.

Для PARENT_PATH, если подкоманда HAS_RELATIVE_PART возвращает false, результат — копия <path-var>. Обратите внимание, что это подразумевает, что корневой каталог считается имеющим родителя, который является собой. Если HAS_RELATIVE_PART возвращает true, результат по сути будет <path-var> с одним элементом меньше.

Примеры корней

set(path "c:/a")

cmake_path(GET path ROOT_NAME rootName)
cmake_path(GET path ROOT_DIRECTORY rootDir)
cmake_path(GET path ROOT_PATH rootPath)

message("Root name is \"${rootName}\"")
message("Root directory is \"${rootDir}\"")
message("Root path is \"${rootPath}\"")
Root name is "c:"
Root directory is "/"
Root path is "c:/"

Примеры имён файлов

set(path "/a/b")
cmake_path(GET path FILENAME filename)
message("First filename is \"${filename}\"")

# Trailing slash means filename is empty
set(path "/a/b/")
cmake_path(GET path FILENAME filename)
message("Second filename is \"${filename}\"")
First filename is "b"
Second filename is ""

Примеры расширения и основной части

set(path "name.ext1.ext2")

cmake_path(GET path EXTENSION fullExt)
cmake_path(GET path STEM fullStem)
message("Full extension is \"${fullExt}\"")
message("Full stem is \"${fullStem}\"")

# Effect of LAST_ONLY
cmake_path(GET path EXTENSION LAST_ONLY lastExt)
cmake_path(GET path STEM LAST_ONLY lastStem)
message("Last extension is \"${lastExt}\"")
message("Last stem is \"${lastStem}\"")

# Special cases
set(dotPath "/a/.")
set(dotDotPath "/a/..")
set(someMorePath "/a/.some.more")
cmake_path(GET dotPath EXTENSION dotExt)
cmake_path(GET dotPath STEM dotStem)
cmake_path(GET dotDotPath EXTENSION dotDotExt)
cmake_path(GET dotDotPath STEM dotDotStem)
cmake_path(GET dotMorePath EXTENSION someMoreExt)
cmake_path(GET dotMorePath STEM someMoreStem)
message("Dot extension is \"${dotExt}\"")
message("Dot stem is \"${dotStem}\"")
message("Dot-dot extension is \"${dotDotExt}\"")
message("Dot-dot stem is \"${dotDotStem}\"")
message(".some.more extension is \"${someMoreExt}\"")
message(".some.more stem is \"${someMoreStem}\"")
Full extension is ".ext1.ext2"
Full stem is "name"
Last extension is ".ext2"
Last stem is "name.ext1"
Dot extension is ""
Dot stem is "."
Dot-dot extension is ""
Dot-dot stem is ".."
.some.more extension is ".more"
.some.more stem is ".some"

Примеры относительной части

set(path "c:/a/b")
cmake_path(GET path RELATIVE_PART result)
message("Relative part is \"${result}\"")

set(path "c/d")
cmake_path(GET path RELATIVE_PART result)
message("Relative part is \"${result}\"")

set(path "/")
cmake_path(GET path RELATIVE_PART result)
message("Relative part is \"${result}\"")
Relative part is "a/b"
Relative part is "c/d"
Relative part is ""

Примеры обхода пути

set(path "c:/a/b")
cmake_path(GET path PARENT_PATH result)
message("Parent path is \"${result}\"")

set(path "c:/")
cmake_path(GET path PARENT_PATH result)
message("Parent path is \"${result}\"")
Parent path is "c:/a"
Parent path is "c:/"

Запрос

Каждая из подкоманд GET имеет соответствующую подкоманду HAS_..., которая может быть использована для определения наличия определённого компонента пути. См. Структура пути и терминология для определения значения каждого компонента пути.

cmake_path(HAS_ROOT_NAME <path-var> <out-var>)
cmake_path(HAS_ROOT_DIRECTORY <path-var> <out-var>)
cmake_path(HAS_ROOT_PATH <path-var> <out-var>)
cmake_path(HAS_FILENAME <path-var> <out-var>)
cmake_path(HAS_EXTENSION <path-var> <out-var>)
cmake_path(HAS_STEM <path-var> <out-var>)
cmake_path(HAS_RELATIVE_PART <path-var> <out-var>)
cmake_path(HAS_PARENT_PATH <path-var> <out-var>)

Все вышеперечисленные подкоманды следуют предсказуемой схеме, устанавливая <out-var> в true, если путь содержит соответствующий компонент, или в false в противном случае. Обратите внимание на следующие специальные случаи:

  • Для HAS_ROOT_PATH, результат true будет возвращён только в том случае, если хотя бы один из root-name или root-directory не пуст.
  • Для HAS_PARENT_PATH, корневой каталог также считается имеющим родителя, который будет самим собой. Результат — true, за исключением случаев, когда путь состоит только из имени файла.
cmake_path(IS_ABSOLUTE <path-var> <out-var>)

Устанавливает <out-var> в true, если <path-var> абсолютный. Абсолютный путь — это путь, который однозначно идентифицирует местоположение файла без ссылки на дополнительное начальное местоположение. В Windows это означает, что путь должен иметь и root-name, и root-directory-separator, чтобы считаться абсолютным. На других платформах достаточно root-directory-separator. Обратите внимание, что это означает, что в Windows IS_ABSOLUTE может быть false, в то время как HAS_ROOT_DIRECTORY может быть true.

cmake_path(IS_RELATIVE <path-var> <out-var>)

Это сохранит противоположность IS_ABSOLUTE в <out-var>.

cmake_path(IS_PREFIX <path-var> <input> [NORMALIZE] <out-var>)

Проверяет, является ли <path-var> префиксом <input>.

Если указан параметр NORMALIZE, <path-var> и <input> нормализуются перед проверкой.

set(path "/a/b/c")
cmake_path(IS_PREFIX path "/a/b/c/d" result) # result = true
cmake_path(IS_PREFIX path "/a/b" result)     # result = false
cmake_path(IS_PREFIX path "/x/y/z" result)   # result = false

set(path "/a/b")
cmake_path(IS_PREFIX path "/a/c/../b" NORMALIZE result)   # result = true
cmake_path(COMPARE <input1> EQUAL <input2> <out-var>)
cmake_path(COMPARE <input1> NOT_EQUAL <input2> <out-var>)

Сравнивает лексические представления двух путей, предоставленных в виде строковых констант. Никакая нормализация на этих путях не выполняется. Равенство определяется по следующей логике псевдокода:

if(NOT <input1>.root_name() STREQUAL <input2>.root_name())
  return FALSE

if(<input1>.has_root_directory() XOR <input2>.has_root_directory())
  return FALSE

Return FALSE if a relative portion of <input1> is not lexicographically
equal to the relative portion of <input2>. This comparison is performed path
component-wise. If all of the components compare equal, then return TRUE.

Примечание

В отличие от большинства других подкоманд cmake_path(), подкоманда COMPARE принимает литеральные строки в качестве входных данных, а не имена переменных.

Модификация

cmake_path(SET <path-var> [NORMALIZE] <input>)

Присваивает путь <input> к <path-var>. Если <input> — это системный путь, он преобразуется в путь CMake со слэшами (/). В Windows учитывается маркер длинного имени файла.

Если указан параметр NORMALIZE, путь нормализуется перед преобразованием.

Например:

set(native_path "c:\\a\\b/..\\c")
cmake_path(SET path "${native_path}")
message("CMake path is \"${path}\"")

cmake_path(SET path NORMALIZE "${native_path}")
message("Normalized CMake path is \"${path}\"")

Вывод:

CMake path is "c:/a/b/../c"
Normalized CMake path is "c:/a/c"
cmake_path(APPEND <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])

Добавить все <input> аргументы к <path-var> с использованием / в качестве directory-separator. В зависимости от <input>, предыдущее содержимое <path-var> может быть удалено. Для каждого <input> аргумента применяется следующий алгоритм (псевдокод):

# <path> is the contents of <path-var>

if(<input>.is_absolute() OR
   (<input>.has_root_name() AND
    NOT <input>.root_name() STREQUAL <path>.root_name()))
  replace <path> with <input>
  return()
endif()

if(<input>.has_root_directory())
  remove any root-directory and the entire relative path from <path>
elseif(<path>.has_filename() OR
       (NOT <path-var>.has_root_directory() OR <path>.is_absolute()))
  append directory-separator to <path>
endif()

append <input> omitting any root-name to <path>
cmake_path(APPEND_STRING <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])

Добавить все <input> аргументы к <path-var> без добавления каких-либо directory-separator.

cmake_path(REMOVE_FILENAME <path-var> [OUTPUT_VARIABLE <out-var>])

Удаляет компонент имя файла (как возвращается GET ... FILENAME) из <path-var>. После удаления любой заключительный directory-separator остаётся без изменений, если присутствует.

Если OUTPUT_VARIABLE не указан, то после возврата этой функции HAS_FILENAME возвращает false для <path-var>.

Например:

set(path "/a/b")
cmake_path(REMOVE_FILENAME path)
message("First path is \"${path}\"")

# filename is now already empty, the following removes nothing
cmake_path(REMOVE_FILENAME path)
message("Second path is \"${result}\"")

Вывод:

First path is "/a/"
Second path is "/a/"
cmake_path(REPLACE_FILENAME <path-var> <input> [OUTPUT_VARIABLE <out-var>])

Заменяет компонент имя файла в <path-var> на <input>. Если <path-var> не содержит компонента имени файла (т.е. HAS_FILENAME возвращает false), путь не изменяется. Операция эквивалентна следующему:

cmake_path(HAS_FILENAME path has_filename)
if(has_filename)
  cmake_path(REMOVE_FILENAME path)
  cmake_path(APPEND path input);
endif()
cmake_path(REMOVE_EXTENSION <path-var> [LAST_ONLY]
                                       [OUTPUT_VARIABLE <out-var>])

Удаляет расширение, если оно есть, из <path-var>.

cmake_path(REPLACE_EXTENSION <path-var> [LAST_ONLY] <input>
                             [OUTPUT_VARIABLE <out-var>])

Заменяет расширение на <input>. Его эффект эквивалентен следующему:

cmake_path(REMOVE_EXTENSION path)
if(NOT "input" MATCHES "^\\.")
  cmake_path(APPEND_STRING path ".")
endif()
cmake_path(APPEND_STRING path "input")

Генерация

cmake_path(NORMAL_PATH <path-var> [OUTPUT_VARIABLE <out-var>])

Нормализовать <path-var> согласно шагам, описанным в Нормализация.

cmake_path(RELATIVE_PATH <path-var> [BASE_DIRECTORY <input>]
                                    [OUTPUT_VARIABLE <out-var>])

Изменяет <path-var> так, чтобы оно относилось к аргументу BASE_DIRECTORY. Если BASE_DIRECTORY не указан, по умолчанию будет использоваться базовая директория CMAKE_CURRENT_SOURCE_DIR.

Для справки, алгоритм вычисления относительного пути такой же, как у C++ std::filesystem::path::lexically_relative.

cmake_path(ABSOLUTE_PATH <path-var> [BASE_DIRECTORY <input>] [NORMALIZE]
                                    [OUTPUT_VARIABLE <out-var>])

Если <path-var> — относительный путь (IS_RELATIVE истинно), он вычисляется относительно указанной базовой директории в опции BASE_DIRECTORY . Если BASE_DIRECTORY не указан, по умолчанию будет использоваться базовая директория CMAKE_CURRENT_SOURCE_DIR.

При указании опции NORMALIZE, путь нормализуется после вычисления пути.

Поскольку cmake_path() не обращается к файловой системе, символические ссылки не разрешаются, и любой ведущий символ тильды не расширяется. Чтобы вычислить реальный путь с разрешёнными символическими ссылками и расширенными ведущими тильдами, используйте команду file(REAL_PATH) вместо неё.

Перевод в родной формат

Для команд в этом разделе родной относится к платформе хоста, а не целевой платформе при кросс-компиляции.

cmake_path(NATIVE_PATH <path-var> [NORMALIZE] <out-var>)

Преобразует путь в стиле CMake (<path-var>) в родной путь с платформа-зависимыми слешами (\ на Windows-хостах и / в остальных случаях).

Если указана опция NORMALIZE, путь нормализуется до преобразования.

cmake_path(CONVERT <input> TO_CMAKE_PATH_LIST <out-var> [NORMALIZE])

Преобразует родной путь (<input> путь) в путь в стиле CMake с использованием прямых слешей (/). На Windows-хостах учитывается маркер длинного имени файла. Входные данные могут быть одиночным путём или путём поиска системы, как $ENV{PATH}. Путь поиска будет преобразован в список в стиле CMake, разделённый символами ; (на платформах, отличных от Windows, это означает, что разделители : заменяются на ;). Результат преобразования сохраняется в переменной <out-var>.

Если указана опция NORMALIZE, путь нормализуется перед преобразованием.

Примечание

В отличие от большинства других подкоманд cmake_path(), подкоманда CONVERT принимает в качестве входных данных литеральную строку, а не имя переменной.

cmake_path(CONVERT <input> TO_NATIVE_PATH_LIST <out-var> [NORMALIZE])

Преобразует путь в стиле CMake (<input> путь) в родной путь с платформа-зависимыми слешами (\ на Windows-хостах и / в остальных случаях). Входные данные могут быть одиночным путём или списком в стиле CMake. Список будет преобразован в родной путь поиска (;-разделенный на Windows, :-разделенный на других платформах). Результат преобразования сохраняется в переменной <out-var>.

Если указана опция NORMALIZE, путь нормализуется перед преобразованием.

Примечание

В отличие от большинства других подкоманд cmake_path(), подкоманда CONVERT принимает в качестве входных данных литеральную строку, а не имя переменной.

Например:

set(paths "/a/b/c" "/x/y/z")
cmake_path(CONVERT "${paths}" TO_NATIVE_PATH_LIST native_paths)
message("Native path list is \"${native_paths}\"")

Вывод на Windows:

Native path list is "\a\b\c;\x\y\z"

Вывод на всех остальных платформах:

Native path list is "/a/b/c:/x/y/z"

Хэширование

cmake_path(HASH <path-var> <out-var>)

Вычислить значение хэша для <path-var>, так что для двух путей p1 и p2, которые сравниваются как равные (COMPARE ... EQUAL), значение хэша для p1 равно значению хэша для p2. Путь всегда нормализуется перед вычислением хэша.

© 2000–2021 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.22/command/cmake_path.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API