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]
[JOB_SERVER_AWARE <bool>]
[VERBATIM] [APPEND] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS]
[DEPENDS_EXPLICIT_ONLY])
Это определяет команду для генерации указанных OUTPUT файла(ов). Цель, созданная в той же директории (CMakeLists.txt файл), которая указывает любой вывод пользовательской команды как входной файл, получает правило для генерации файла с помощью команды во время сборки.
Не перечисляйте выходные данные более чем в одной независимой цели, которая может собираться параллельно, или экземпляры правила могут конфликтовать. Вместо этого используйте команду add_custom_target() для управления командой и сделайте другие цели зависимыми от этой.
См. пример ниже Пример: Генерация файлов для нескольких целей.
Доступны следующие параметры:
-
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. Зависимые от целей выражения запрещены.Изменено в версии 3.28: В целях, использующих Наборы файлов, побочные продукты пользовательских команд теперь считаются закрытыми, если они не перечислены в наборе файлов, не являющемся закрытым. См. политику
CMP0154. -
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. -
JOB_SERVER_AWARE -
Новое в версии 3.28.
Укажите, что команда должна учитывать сервер задач GNU Make.
Для генераторов
Unix Makefiles,MSYS MakefilesиMinGW Makefilesэто добавит префикс+к строке рецепта. Для получения дополнительной информации см. документацию GNU Make.Этот параметр будет проигнорирован другими генераторами.
-
MAIN_DEPENDENCY -
Укажите основной входной исходный файл для команды. Он обрабатывается так же, как любое значение, переданное параметру
DEPENDS, но также подсказывает генераторам Visual Studio, где разместить пользовательскую команду. Каждый исходный файл может иметь не более одной команды, определяющей его как основную зависимость. Команда компиляции (т.е. для библиотеки или исполняемого файла) считается неявной главной зависимостью, которая безмолвно перезаписывается указанием пользовательской команды. -
OUTPUT -
Укажите выходные файлы, которые, как ожидается, будут созданы командой. Каждый выходной файл будет автоматически помечен свойством исходного файла
GENERATED. Если результат выполнения пользовательской команды не фактически создаётся как файл на диске, он должен быть помечен свойством исходного файлаSYMBOLIC.Если имя выходного файла является относительным путём, его абсолютный путь определяется относительно:
- каталога сборки, соответствующего текущему каталогу исходных файлов (
CMAKE_CURRENT_BINARY_DIR), или - текущего каталога исходных файлов (
CMAKE_CURRENT_SOURCE_DIR).
Предпочтение отдаётся пути в каталоге сборки, если путь в каталоге исходного дерева не указан как абсолютный путь к исходному файлу в другом месте текущего каталога.
Новое в версии 3.20: Аргументы для
OUTPUTмогут использовать ограниченный наборgenerator expressions. Зависимые от целей выражения не разрешены.Изменено в версии 3.28: В целевых объектах, использующих Наборы файлов, выходные данные пользовательской команды теперь считаются частными, если они не указаны в наборе файлов, не являющемся частным. См. политику
CMP0154. - каталога сборки, соответствующего текущему каталогу исходных файлов (
-
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, независим от генератора или платформы.Формальный синтаксис, определённый с использованием нотации БНФ с регулярными расширениями, следующий:
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.Новое в версии 3.29: Генераторы Ninja теперь будут включать зависимости в свою базу данных "журнала зависимостей", если файл не указан в
OUTPUTSилиBYPRODUCTS.Использование
DEPFILEс генераторами, не перечисленными выше, является ошибкой.Если аргумент
DEPFILEявляется относительным, он должен относиться кCMAKE_CURRENT_BINARY_DIR, и любые относительные пути внутриDEPFILEтакже должны быть относительными кCMAKE_CURRENT_BINARY_DIR. См. политикуCMP0116, которая всегдаNEWдля Генераторов Makefile, Генераторов Visual Studio и генератораXcode.
DEPENDS_EXPLICIT_ONLY
Новое в версии 3.27.
Указывает, что аргумент DEPENDS команды представляет все файлы, необходимые для команды, и неявные зависимости не требуются.
Без этого параметра, если какой-либо целевой объект использует вывод пользовательской команды, CMake будет рассматривать зависимости этого целевого объекта как неявные зависимости для пользовательской команды в случае, если эта пользовательская команда требует файлов, неявно созданных этими целевыми объектами.
Этот параметр можно включить для всех пользовательских команд, установив CMAKE_ADD_CUSTOM_COMMAND_DEPENDS_EXPLICIT_ONLY в ON.
Только Генераторы Ninja фактически используют эту информацию для удаления ненужных неявных зависимостей.
См. также свойство целевого объекта OPTIMIZE_DEPENDENCIES, которое может предоставить другой способ уменьшения влияния зависимостей целевых объектов в некоторых сценариях.
Примеры: Генерация файлов
Пользовательские команды могут использоваться для генерации исходных файлов. Например, код:
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]
[COMMAND_EXPAND_LISTS])
Это определяет новую команду, которая будет связана со сборкой указанного <target>. <target> должен быть определён в текущем каталоге; целевые объекты, определённые в других каталогах, не могут быть указаны.
Когда произойдёт выполнение команды, определяется тем, какой из следующих параметров указан:
-
PRE_BUILD -
Этот параметр имеет уникальное поведение для Генераторов Visual Studio. При использовании одного из генераторов Visual Studio команда будет запущена до выполнения любых других правил внутри целевого объекта. Во всех других генераторах этот параметр ведёт себя так же, как
PRE_LINKвместо. Из-за этого рекомендуется избегать использованияPRE_BUILDза исключением случаев, когда известно, что используется генератор Visual Studio. -
PRE_LINK -
Выполнить после компиляции исходных кодов, но перед линковкой двоичного файла или выполнением инструмента библиотекаря или архиватора статической библиотеки. Это не определено для целевых объектов, созданных командой
add_custom_target(). -
POST_BUILD -
Выполнить после выполнения всех других правил внутри целевого объекта.
Проекты всегда должны указывать один из вышеперечисленных трёх ключевых слов при использовании формы TARGET. По причинам обратной совместимости POST_BUILD предполагается, если такое ключевое слово не указано, но проекты должны явно указать одно из ключевых слов, чтобы сделать ясным ожидаемое поведение.
Примечание
Поскольку выражения генератора могут использоваться в пользовательских командах, возможно определить строки COMMAND или целые пользовательские команды, которые вычисляются как пустые строки для определённых конфигураций. Для генераторов Visual Studio 12 2013 (и более поздних) эти строки команд или пользовательские команды будут опущены для конкретной конфигурации, и не будет добавлена «пустая строка-команда».
Это позволяет добавлять отдельные события сборки для каждой конфигурации.
Новое в версии 3.21: Поддержка зависимых от целевого объекта выражений генератора.
Новое в версии 3.29: <target> может быть целевым объектом-псевдонимом.
Примеры: События сборки
Событие 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–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.29/command/add_custom_command.html