add_custom_command
Добавить пользовательское правило сборки в сгенерированную систему сборки.
Существуют две основные сигнатуры для add_custom_command.
Генерация файлов
Первая сигнатура предназначена для добавления пользовательской команды для создания выходного файла:
add_custom_command(OUTPUT output1 [output2 ...]
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[MAIN_DEPENDENCY depend]
[DEPENDS [depends...]]
[BYPRODUCTS [files...]]
[IMPLICIT_DEPENDS <lang1> depend1
[<lang2> depend2] ...]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[DEPFILE depfile]
[JOB_POOL job_pool]
[VERBATIM] [APPEND] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS])
Это определяет команду для генерации указанных OUTPUT файла(ов). Цель, созданная в том же каталоге (CMakeLists.txt файл), которая указывает любой выходной файл пользовательской команды как исходный файл, получает правило для генерации файла с помощью указанной команды во время сборки.
Не перечисляйте выходные файлы более чем в одной независимой цели, которые могут собираться параллельно, иначе экземпляры правила могут конфликтовать. Вместо этого используйте команду add_custom_target() для управления командой и зависимости других целей от этой цели. См. Пример: Генерация файлов для нескольких целей ниже.
Параметры:
-
APPEND -
Добавьте значения опций
COMMANDиDEPENDSк пользовательской команде для первого указанного вывода. Должна быть уже выполненная предыдущая вызов этой команды с тем же выводом.Если предыдущий вызов указал вывод через выражение генератора, вывод, указанный в текущем вызове, должен совпадать по крайней мере в одной конфигурации после вычисления выражений генератора. В этом случае добавленные команды и зависимости применяются ко всем конфигурациям.
Опции
COMMENT,MAIN_DEPENDENCY, иWORKING_DIRECTORYв настоящее время игнорируются при использовании APPEND, но могут быть использованы в будущем. -
BYPRODUCTS -
Новая в версии 3.2.
Укажите файлы, которые команда должна создать, но время изменения которых может быть или не быть новее, чем время изменения зависимостей. Если имя побочного продукта — относительный путь, оно будет интерпретировано относительно каталога дерева сборки, соответствующего текущему каталогу исходного кода. Каждый файл побочного продукта будет автоматически помечен свойством исходного файла
GENERATED.См. политику
CMP0058для мотивации этой функции.Явное указание побочных продуктов поддерживается генератором
Ninja, чтобы сообщить инструменту сборкиninjaкак перегенерировать побочные продукты, если они отсутствуют. Это также полезно, когда другие правила сборки (например, пользовательские команды) зависят от побочных продуктов. Ninja требует правила сборки для любого сгенерированного файла, от которого зависит другое правило, даже если есть только зависимости по порядку, чтобы гарантировать, что побочные продукты будут доступны до начала сборки их зависимостей.Генераторы Makefile удалят
BYPRODUCTSи другие файлыGENERATEDво времяmake clean.Новая в версии 3.20: Аргументы к
BYPRODUCTSмогут использовать ограниченный наборgenerator expressions. Зависимые от целевых выражения не разрешены. -
COMMAND -
Укажите командную строку(и) для выполнения во время сборки. Если указано более одной
COMMAND, они будут выполнены в указанном порядке, но не обязательно составлены в состоятельное оболочку или пакетную скрипт. (Чтобы запустить полную скрипт, используйте командуconfigure_file()или командуfile(GENERATE)для её создания, а затем укажитеCOMMANDдля запуска.) Необязательный аргументARGSиспользуется для обратной совместимости и будет проигнорирован.Если
COMMANDуказывает имя исполняемого целевого объекта (созданного командойadd_executable()), он будет автоматически заменён расположением создаваемого исполняемого файла во время сборки, если выполняется одно из следующих условий:- Целевой объект не компилируется для кросс-платформы (т.е. переменная
CMAKE_CROSSCOMPILINGне установлена в значение true). -
Новая в версии 3.6: Целевой объект компилируется для кросс-платформы и предоставляется эмулятор (т.е. свойство целевого объекта
CROSSCOMPILING_EMULATORустановлено). В этом случае содержимоеCROSSCOMPILING_EMULATORбудет добавлено в начало команды перед расположением исполняемого файла целевого объекта.
Если ни одно из вышеперечисленных условий не выполняется, предполагается, что имя команды — это программа, которая должна быть найдена в
PATHво время сборки.Аргументы к
COMMANDмогут использоватьgenerator expressions. Используйте выражение генератораTARGET_FILE, чтобы сослаться на расположение целевого объекта в командной строке (т. е. в качестве аргумента команды, а не как команды для выполнения).Всякий раз, когда одно из следующих выражений генератора, основанных на целевом объекте, используется в качестве команды для выполнения или упоминается в аргументе команды, автоматически добавляется зависимость на уровне целевого объекта, чтобы указанный целевой объект был собран до любого целевого объекта, использующего эту пользовательскую команду (см. политику
CMP0112).TARGET_FILETARGET_LINKER_FILETARGET_SONAME_FILETARGET_PDB_FILE
Эта зависимость на уровне целевого объекта НЕ добавляет зависимость на уровне файла, которая заставила бы пользовательскую команду повторно выполняться при каждом перекомпилировании исполняемого файла. Перечислите имена целевых объектов с опцией
DEPENDSдля добавления таких зависимостей на уровне файла. - Целевой объект не компилируется для кросс-платформы (т.е. переменная
-
COMMENT -
Отобразить заданное сообщение перед выполнением команд во время сборки.
Новая в версии 3.26: Аргументы к
COMMENTмогут использоватьgenerator expressions. -
DEPENDS -
Укажите файлы, от которых зависит команда. Каждый аргумент преобразуется в зависимость следующим образом:
- Если аргумент — имя целевого объекта (созданного командами
add_custom_target(),add_executable()илиadd_library()), создаётся зависимость на уровне целевого объекта, чтобы убедиться, что целевой объект собран перед любым целевым объектом, использующим эту пользовательскую команду. Кроме того, если целевой объект — исполняемый файл или библиотека, создаётся зависимость на уровне файла, чтобы заставить пользовательскую команду повторно выполняться при каждом перекомпилировании целевого объекта. - Если аргумент — абсолютный путь, создаётся зависимость на уровне файла для этого пути.
- Если аргумент — имя файла исходного кода, который был добавлен в целевой объект или для которого было установлено свойство файла исходного кода, создаётся зависимость на уровне файла для этого исходного файла.
- Если аргумент — относительный путь и он существует в текущем каталоге исходного кода, создаётся зависимость на уровне файла для этого файла в текущем каталоге исходного кода.
- В противном случае создаётся зависимость на уровне файла для этого пути относительно текущего каталога двоичных файлов.
Если какая-либо зависимость является
OUTPUTдругой пользовательской команды в том же каталоге (файлCMakeLists.txt), CMake автоматически включает другую пользовательскую команду в целевой объект, в котором построена данная команда.Новая в версии 3.16: Добавляется зависимость на уровне целевого объекта, если любая зависимость указана как
BYPRODUCTSцелевого объекта или любого из его событий сборки в том же каталоге, чтобы гарантировать доступность побочных продуктов.Если
DEPENDSне указано, команда будет выполняться всякий раз, когдаOUTPUTотсутствует; если команда фактически не создаётOUTPUT, правило будет выполняться всегда.Новая в версии 3.1: Аргументы к
DEPENDSмогут использоватьgenerator expressions. - Если аргумент — имя целевого объекта (созданного командами
-
COMMAND_EXPAND_LISTS -
Новая в версии 3.8.
Списки в
COMMANDаргументах будут расширены, включая те, которые созданы с помощьюgenerator expressions, что позволяетCOMMANDаргументам, таким как${CC} "-I$<JOIN:$<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>,;-I>" foo.cc, быть должным образом расширенными. -
IMPLICIT_DEPENDS -
Запрос сканирования неявных зависимостей входного файла. Указанный язык определяет язык программирования, для которого должен использоваться соответствующий сканер зависимостей. В настоящее время поддерживаются только сканеры зависимостей для языков
CиCXX. Язык должен быть указан для каждого файла в спискеIMPLICIT_DEPENDS. Обнаруженные зависимости из сканирования добавляются к зависимостям пользовательской команды во время сборки. Обратите внимание, что опцияIMPLICIT_DEPENDSв настоящее время поддерживается только для генераторов Makefile и будет проигнорирована другими генераторами.Примечание
Эта опция не может быть указана одновременно с опцией
DEPFILE. -
JOB_POOL
-
Новое в версии 3.15.
Укажите
poolдля генератораNinja. Несовместимо сUSES_TERMINAL, что подразумевает пулconsole. Использование пула, не определённогоJOB_POOLS, приводит к ошибке ninja во время сборки. -
MAIN_DEPENDENCY -
Укажите основной входной файл для команды. Он обрабатывается так же, как любое значение, заданное для параметра
DEPENDS, но также указывает генераторам Visual Studio, где разместить пользовательскую команду. Каждый исходный файл может иметь не более одной команды, указывающей его как основную зависимость. Команда компиляции (например, для библиотеки или исполняемого файла) считается неявной основной зависимостью, которая безмолвно перезаписывается указанием пользовательской команды. -
OUTPUT -
Укажите выходные файлы, которые должна создать команда. Каждый выходной файл будет автоматически помечен свойством исходного файла
GENERATED. Если выход пользовательской команды фактически не создаётся как файл на диске, он должен быть помечен свойством исходного файлаSYMBOLIC.Если имя выходного файла — относительный путь, его абсолютный путь определяется интерпретацией относительно:
- каталога сборки, соответствующего текущему каталогу исходных файлов (
CMAKE_CURRENT_BINARY_DIR), или - текущего каталога исходных файлов (
CMAKE_CURRENT_SOURCE_DIR).
Предпочтение отдаётся пути в каталоге сборки, если путь в дереве исходных файлов не указан как абсолютный путь к файлу исходного кода в другом месте текущего каталога.
Новое в версии 3.20: Аргументы для
OUTPUTмогут использовать ограниченный наборgenerator expressions. Выражения, зависящие от целевых объектов запрещены. - каталога сборки, соответствующего текущему каталогу исходных файлов (
-
USES_TERMINAL -
Новое в версии 3.2.
Команда получит прямой доступ к терминалу, если это возможно. С генератором
Ninja, это помещает команду в пулconsolepool. -
VERBATIM -
Все аргументы команд будут корректно экранированы для средства сборки, чтобы вызванная команда получала каждый аргумент без изменений. Обратите внимание, что один уровень экранирования всё ещё используется процессором языка CMake перед тем, как add_custom_command увидит аргументы. Рекомендуется использовать
VERBATIM, так как это обеспечивает корректное поведение. ЕслиVERBATIMне указан, поведение зависит от платформы, поскольку нет защиты от специфичных для инструмента особых символов. -
WORKING_DIRECTORY -
Выполнить команду с указанным текущим каталогом. Если это относительный путь, он будет интерпретирован относительно каталога сборки, соответствующего текущему каталогу исходных файлов.
Новое в версии 3.13: В аргументах для
WORKING_DIRECTORYможно использоватьgenerator expressions. -
DEPFILE -
Новое в версии 3.7.
Укажите depfile, содержащий зависимости для пользовательской команды. Он обычно создаётся самой пользовательской командой. Этот ключевое слово может быть использовано только в том случае, если генератор его поддерживает, как подробно описано ниже.
Ожидаемый формат, совместимый с тем, что генерируется
gccс параметром-M, независим от генератора или платформы.Формальный синтаксис, определённый с использованием обозначения BNF с обычными расширениями, следующий:
depfile ::= rule* rule ::= targets (':' (separator dependencies?)?)? eol targets ::= target (separator target)* separator* target ::= pathname dependencies ::= dependency (separator dependency)* separator* dependency ::= pathname separator ::= (space | line_continue)+ line_continue ::= '\' eol space ::= ' ' | '\t' pathname ::= character+ character ::= std_character | dollar | hash | whitespace std_character ::= <any character except '$', '#' or ' '> dollar ::= '$$' hash ::= '\#' whitespace ::= '\ ' eol ::= '\r'? '\n'Примечание
В рамках
pathname, любой слэш и обратный слэш интерпретируются как разделитель каталогов.Новое в версии 3.7: Генератор
NinjaподдерживаетDEPFILEс момента добавления ключевого слова.Новое в версии 3.17: Добавил генератор
Ninja Multi-Config, который включил поддержку ключевого словаDEPFILE.Новое в версии 3.20: Добавлена поддержка Генераторов Makefile.
Примечание
DEPFILEне может быть указан одновременно с параметромIMPLICIT_DEPENDSдля Генераторов Makefile.Новое в версии 3.21: Добавлена поддержка Генераторов Visual Studio с VS 2012 и выше, и генератора
Xcode. Также добавлена поддержкаgenerator expressions.Использование
DEPFILEс генераторами, не указанными выше, является ошибкой.Если аргумент
DEPFILEотносительный, он должен быть относительным кCMAKE_CURRENT_BINARY_DIR, и все относительные пути внутриDEPFILEтакже должны быть относительными кCMAKE_CURRENT_BINARY_DIR. См. политикуCMP0116, которая всегдаNEWдля Генераторов Makefile, Генераторов Visual Studio и генератораXcode.
Примеры: Генерирование файлов
Пользовательские команды могут использоваться для генерации исходных файлов. Например, код:
add_custom_command(
OUTPUT out.c
COMMAND someTool -i ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
-o out.c
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
VERBATIM)
add_library(myLib out.c)
добавляет пользовательскую команду для выполнения someTool для генерации out.c и последующей компиляции сгенерированного исходного кода как части библиотеки. Правило генерации будет перевыполняться всякий раз, когда in.txt изменяется.
Новое в версии 3.20: Можно использовать выражения генератора для указания выходных данных по конфигурациям. Например, код:
add_custom_command(
OUTPUT "out-$<CONFIG>.c"
COMMAND someTool -i ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
-o "out-$<CONFIG>.c"
-c "$<CONFIG>"
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
VERBATIM)
add_library(myLib "out-$<CONFIG>.c")
добавляет пользовательскую команду для выполнения someTool для генерации out-<config>.c, где <config> — конфигурация сборки, и последующей компиляции сгенерированного исходного кода как части библиотеки.
Пример: Генерирование файлов для нескольких целевых объектов
Если несколько независимых целевых объектов нуждаются в одном и том же выходе пользовательской команды, его необходимо прикрепить к одному пользовательскому целевому объекту, от которого они все зависят. Рассмотрим следующий пример:
add_custom_command(
OUTPUT table.csv
COMMAND makeTable -i ${CMAKE_CURRENT_SOURCE_DIR}/input.dat
-o table.csv
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/input.dat
VERBATIM)
add_custom_target(generate_table_csv DEPENDS table.csv)
add_custom_command(
OUTPUT foo.cxx
COMMAND genFromTable -i table.csv -case foo -o foo.cxx
DEPENDS table.csv # file-level dependency
generate_table_csv # target-level dependency
VERBATIM)
add_library(foo foo.cxx)
add_custom_command(
OUTPUT bar.cxx
COMMAND genFromTable -i table.csv -case bar -o bar.cxx
DEPENDS table.csv # file-level dependency
generate_table_csv # target-level dependency
VERBATIM)
add_library(bar bar.cxx)
Выход foo.cxx нужен только целевому объекту foo, а выход bar.cxx нужен только целевому объекту bar, но оба целевых объекта нуждаются в table.csv, транзитивно. Так как foo и bar являются независимыми целевыми объектами, которые могут собираться параллельно, мы предотвращаем гонку за генерацию table.csv путём размещения пользовательской команды в отдельном целевом объекте, generate_table_csv. Пользовательские команды, генерирующие foo.cxx и bar.cxx , каждая указывают зависимость на уровне целевого объекта от generate_table_csv, поэтому целевые объекты, использующие их, foo и bar, не будут собираться до тех пор, пока не будет собран целевой объект generate_table_csv.
События сборки
Вторая сигнатура добавляет пользовательскую команду к целевому объекту, такому как библиотека или исполняемый файл. Это полезно для выполнения операции до или после построения целевого объекта. Команда становится частью целевого объекта и будет выполняться только при построении самого целевого объекта. Если целевой объект уже построен, команда не будет выполнена.
add_custom_command(TARGET <target>
PRE_BUILD | PRE_LINK | POST_BUILD
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[VERBATIM] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS])
Это определяет новую команду, которая будет связана с построением указанного <target>. <target> должен быть определён в текущей директории; цели, определённые в других директориях, указать нельзя.
Время выполнения команды определяется тем, какой из следующих параметров указан:
-
PRE_BUILD -
В генераторах Visual Studio выполняется перед выполнением любых других правил внутри целевого объекта. В других генераторах выполняется непосредственно перед
PRE_LINKкомандами. -
PRE_LINK -
Выполняется после того, как исходные файлы были скомпилированы, но перед линковкой бинарного файла или выполнением инструмента сборки или архивации для статической библиотеки. Это не определено для целей, созданных командой
add_custom_target(). -
POST_BUILD -
Выполняется после выполнения всех других правил внутри целевого объекта.
Проекты всегда должны указывать один из вышеперечисленных трёх ключевых слов при использовании TARGET формы. По причинам обратной совместимости POST_BUILD подразумевается, если такое ключевое слово не задано, но проекты должны явно указать одно из ключевых слов, чтобы прояснить ожидаемое поведение.
Примечание
Поскольку в пользовательских командах могут использоваться выражения генератора, возможно определение COMMAND строк или целых пользовательских команд, которые приводят к пустым строкам для определённых конфигураций. Для генераторов Visual Studio 11 2012 (и более поздних) эти строки команд или пользовательские команды будут опущены для конкретной конфигурации, и никакая «команда-пустая строка» не будет добавлена.
Это позволяет добавлять отдельные события сборки для каждой конфигурации.
Новое в версии 3.21: Поддержка выражений генератора, зависящих от целевого объекта.
Примеры: События сборки
Событие POST_BUILD может использоваться для пост-обработки бинарного файла после линковки. Например, код:
add_executable(myExe myExe.c)
add_custom_command(
TARGET myExe POST_BUILD
COMMAND someHasher -i "$<TARGET_FILE:myExe>"
-o "$<TARGET_FILE:myExe>.hash"
VERBATIM)
выполнит someHasher для создания файла .hash рядом с исполняемым файлом после линковки.
Новое в версии 3.20: Можно использовать выражения генератора для указания побочных продуктов по конфигурациям. Например, код:
add_library(myPlugin MODULE myPlugin.c)
add_custom_command(
TARGET myPlugin POST_BUILD
COMMAND someHasher -i "$<TARGET_FILE:myPlugin>"
--as-code "myPlugin-hash-$<CONFIG>.c"
BYPRODUCTS "myPlugin-hash-$<CONFIG>.c"
VERBATIM)
add_executable(myExe myExe.c "myPlugin-hash-$<CONFIG>.c")
выполнит someHasher после линковки myPlugin, например, для создания файла .c содержащего код для проверки хэша myPlugin, который исполняемый файл myExe может использовать для проверки перед загрузкой.
Ninja Multi-Config
Новое в версии 3.20: add_custom_command поддерживает возможности межконфигурационной работы генератора Ninja Multi-Config. Для получения дополнительной информации см. документацию по генератору.
См. также
© 2000–2023 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.26/command/add_custom_command.html