Spec-Zone.ru › CMake 3.31

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, результат 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>])

Удаляет компонент имя файла (как возвращается получить ... ИМЯ_ФАЙЛА) из <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 \"${path}\"")

Вывод:

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, которые сравниваются как равные (СРАВНИТЬ ... РАВНО), значение хеша для p1 было равно значению хеша для p2 Путь всегда нормализуется перед вычислением хеша.

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

Spec-Zone.ru

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