Spec-Zone.ru › CMake 3.27

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(SET) вместо этого, так как он автоматически преобразует путь в требуемый формат при необходимости. Команда cmake_path(APPEND) может быть ещё одним подходящим вариантом, когда путь нужно создать, объединив фрагменты. Следующий пример сравнивает три метода создания одного и того же пути:

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 это .., удалить все завершающие 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, истинный результат будет возвращён только если хотя бы один из root-name или root-directory не пустой.
  • Для HAS_PARENT_PATH, корневой каталог также считается имеющим родительский каталог, который будет самим собой. Результат — истина, за исключением случая, когда путь состоит только из имени файла.
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–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.27/command/cmake_path.html

Spec-Zone.ru

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