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]
[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. Выражения, зависящие от целевых объектов не допускаются. -
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.
Укажите файл зависимостей, содержащий зависимости для пользовательской команды. Обычно он создаётся самой пользовательской командой. Этот ключевое слово может быть использовано только если генератор его поддерживает, как подробно описано ниже.
Ожидаемый формат, совместимый с тем, что генерируется
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.
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 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–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.27/command/add_custom_command.html