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>.
Нормализация
Некоторые подкоманды поддерживают нормализацию пути. Алгоритм нормализации пути следующий:
- Если путь пуст, остановить (нормализованная форма пустого пути — тоже пустой путь).
- Заменить каждый
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является.., удалить любые последующиеdirectory-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, истинный результат будет возвращён только в том случае, если хотя бы один из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 равно true), он вычисляется относительно заданной базовой директории, указанной параметром 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–2022 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.23/command/cmake_path.html