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>.
Нормализация
Некоторые подкоманды поддерживают нормализацию пути. Алгоритм нормализации пути следующий:
- Если путь пустой, остановитесь (нормализованная форма пустого пути — тоже пустой путь).
- Замените каждый
directory-separator, который может состоять из нескольких разделителей, одним/(/a///b --> /a/b). - Удалите каждую одиночную точку (
.) и любой следующийdirectory-separator(/a/./b/. --> /a/b). - Удалите каждый
item-name(кроме..), который сразу за ним следуетdirectory-separatorи.., вместе с любымdirectory-separator(/a/b/../c --> a/c). - Если есть
root-directory, удалите все..и любойdirectory-separatorsсразу за ними. Родитель корневого каталога обрабатывается как всё ещё корневой каталог (/../a --> /a). - Если последний
item-name—.., удалите все trailingdirectory-separator(../ --> ..). - Если путь пустой на этом этапе, добавьте
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