Spec-Zone.ru › CMake

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

Подкоманды Modification и Generation могут либо сохранять результат на месте, либо в отдельной переменной с именем, содержащим ключевое слово 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, корневой каталог также считается имеющим родительский каталог, который является самим собой. Результат — 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 \"${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 которые равны (COMPARE ... EQUAL), значение хеша p1 было равно значению хеша p2. Путь всегда нормализуется перед вычислением хеша.

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

Spec-Zone.ru

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