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() для управления командой и заставьте другие цели зависеть от неё). В терминах makefile это создаёт новую цель в следующем виде:
OUTPUT: MAIN_DEPENDENCY DEPENDS
COMMAND
Параметры:
-
APPEND -
Добавьте значения опций
COMMANDиDEPENDSк пользовательской команде для первого указанного вывода. Должна быть уже произведена предыдущая вызов этой команды с тем же выводом.Если в предыдущем вызове вывод был задан с помощью выражения-генератора, то вывод, заданный в текущем вызове, должен совпадать по крайней мере в одной конфигурации после оценки выражений-генераторов. В этом случае добавленные команды и зависимости применяются ко всем конфигурациям.
Опции
COMMENT,MAIN_DEPENDENCY, иWORKING_DIRECTORYв настоящее время игнорируются при использовании APPEND, но могут быть использованы в будущем. -
BYPRODUCTS -
Новая в версии 3.2.
Укажите файлы, которые команда должна создать, но время изменения которых может быть или не быть новее, чем время изменения зависимостей. Если имя побочного продукта является относительным путем, оно будет интерпретировано относительно каталога дерева сборки, соответствующего текущему каталогу исходного кода. Каждый файл побочного продукта будет помечен свойством файла источника
GENERATEDавтоматически.См. политику
CMP0058для мотивации этой функции.Явное указание побочных продуктов поддерживается генератором
Ninjaдля того, чтобы сообщить инструменту сборкиninjaкак перегенерировать побочные продукты, если они отсутствуют. Это также полезно, когда другие правила сборки (например, пользовательские команды) зависят от побочных продуктов. Ninja требует правила сборки для любого сгенерированного файла, от которого зависит другое правило, даже если существуют только зависимости по порядку, чтобы гарантировать, что побочные продукты будут доступны до того, как будут собраны их зависимые правила.Генераторы Makefile Generators удалят
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 -
Отобразить указанное сообщение перед выполнением команд во время сборки.
-
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.Новое в версии 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.
Укажите файл зависимостей, который содержит зависимости для пользовательской команды. Обычно он генерируется самой пользовательской командой. Этот ключевое слово может быть использовано только в том случае, если генератор его поддерживает, как подробно описано ниже.
Ожидаемый формат, совместимый с тем, что генерируется
gccс параметром-M, не зависит от генератора или платформы.Формальный синтаксис, как указано с использованием обозначения БНФ с обычными расширениями, следующий:
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(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 предполагается, если такое ключевое слово не указано, но проекты должны явно предоставить одно из ключевых слов, чтобы сделать ясным ожидаемое поведение.
Примечание
Поскольку выражения генератора могут использоваться в пользовательских командах, можно определить строки или целые пользовательские команды, которые приводят к пустым строкам для определенных конфигураций. Для генераторов 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–2022 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.25/command/add_custom_command.html