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