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 удалят
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, независим от генератора или платформы.Формальная синтаксическая конструкция, описанная с использованием обозначений 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.
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: Поддержка зависимых от целевых объектов выражений генератора.
Примеры: События сборки
Событие 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.28/command/add_custom_command.html