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).
Предпочтение отдаётся пути в каталоге построения, если путь в дереве исходных файлов не указан как абсолютный путь к исходному файлу в другом месте текущего каталога.
Путь к выходному файлу не может содержать символы
<или>.New in version 3.20: Аргументы к
OUTPUTмогут использовать ограниченный наборgenerator expressions. Зависимые от целевых выражения запрещены.Изменено в версии 3.28: В целевых объектах, использующих Наборы файлов, выходные данные пользовательских команд теперь считаются закрытыми, если они не перечислены в не закрытом наборе файлов. См. политику
CMP0154.Изменено в версии 3.30: Теперь путь к выходному файлу может использовать символы
#, за исключением использования генератораBorland Makefiles. - каталога построения, соответствующего текущему каталогу исходных файлов (
-
USES_TERMINAL -
New in version 3.2.
Команда получит прямой доступ к терминалу, если это возможно. С генератором
Ninjaэто помещает команду вconsoleпул задачpool. -
VERBATIM -
Все аргументы команд будут правильно экранированы для инструмента сборки, чтобы вызванная команда получала каждый аргумент неизменным. Обратите внимание, что один уровень экранирования всё ещё используется процессором языка CMake перед тем, как add_custom_command даже увидит аргументы. Рекомендуется использование
VERBATIM, так как оно обеспечивает правильное поведение. ЕслиVERBATIMне указано, поведение зависит от платформы, так как нет защиты от специальных символов, специфичных для инструмента. -
WORKING_DIRECTORY -
Выполнить команду с указанным текущим рабочим каталогом. Если это относительный путь, он будет интерпретирован относительно каталога сборки, соответствующего текущему каталогу исходных файлов.
New in version 3.13: Аргументы к
WORKING_DIRECTORYмогут использоватьgenerator expressions. -
DEPFILE -
New in version 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, все косые черты и обратные косые черты интерпретируются как разделители каталогов.New in version 3.7: Генератор
NinjaподдерживаетDEPFILEс момента добавления ключа.New in version 3.17: Добавлен генератор
Ninja Multi-Config, который включил поддержку ключаDEPFILE.New in version 3.20: Добавлена поддержка Генераторов Makefile.
Примечание
DEPFILEне может быть указан одновременно с опциейIMPLICIT_DEPENDSдля Генераторов Makefile.New in version 3.21: Добавлена поддержка Генераторов Visual Studio с VS 2012 и выше, и генератора
Xcode. Также была добавлена поддержкаgenerator expressions.New in version 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
New in version 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.30/command/add_custom_command.html