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—.., удалить все завершающие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>. Обратите внимание, что это подразумевает, что корневой каталог считается имеющим родителя, который сам по себе и есть.
Примеры корней
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 может быть ложным, в то время как HAS_ROOT_DIRECTORY может быть истинным.
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, которые сравниваются как равные (COMPARE ... EQUAL), значение хеша для p1 равно значению хеша для p2. Путь всегда нормализуется перед вычислением хеша.
© 2000–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.30/command/cmake_path.html