CMP0058
Новое в версии 3.3.
Ninja требует явного указания побочных продуктов пользовательских команд.
Когда промежуточный файл, сгенерированный во время сборки, используется в дорогостоящей операции или большом дереве зависимостей, можно уменьшить объем работы при инкрементной пересборке, обновляя только метку времени файла, когда его содержимое изменяется. В этом подходе правило генерации должно иметь отдельный выходной файл, который всегда обновляется с новой меткой времени, более поздней, чем любые зависимости правила, чтобы инструмент сборки повторно запускал правило только при изменении входных данных. Мы называем отдельный выходной файл маркером правила, а сгенерированный файл — побочным продуктом правила.
Побочные продукты не могут быть указаны в качестве выходных данных, потому что их метки времени могут быть старше, чем входные данные. Никакие инструменты сборки (например, make), существовавшие при проектировании CMake, не имеют возможности выразить побочные продукты. Поэтому в версиях CMake до 3.2 их указание было невозможно. Проекты обычно не объявляли побочные продукты в правилах, которые их генерируют. Например:
add_custom_command(
OUTPUT witness.txt
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/input.txt
byproduct.txt # timestamp may not change
COMMAND ${CMAKE_COMMAND} -E touch witness.txt
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
)
add_custom_target(Provider DEPENDS witness.txt)
add_custom_command(
OUTPUT generated.c
COMMAND expensive-task -i byproduct.txt -o generated.c
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/byproduct.txt
)
add_library(Consumer generated.c)
add_dependencies(Consumer Provider)
Это работает хорошо для всех генераторов, кроме Ninja. Инструмент сборки Ninja видит правило, перечисляющее byproduct.txt в качестве зависимости, и нет правила, перечисляющего его как выходной файл. Ninja затем жалуется, что нет возможности удовлетворить зависимость и прекращает сборку, хотя существуют зависимости только по порядку, которые гарантируют, что byproduct.txt будет существовать до того, как его потребители нуждаются в нём. Подробное обсуждение этой проблемы см. в вопросе Ninja 760.
Вместо того, чтобы оставлять побочные продукты неопределёнными в правилах, которые их генерируют, Ninja ожидает, что побочные продукты будут перечислены вместе с другими выходными данными. Такие правила могут быть помечены опцией restat, которая сообщает Ninja проверять метки времени выходных данных после выполнения правил. Это предотвращает ненужную пересборку зависимых файлов, если метки времени побочных продуктов не изменились.
Поскольку вышеприведенный подход не сообщает CMake, какая пользовательская команда генерирует byproduct.txt, генератор Ninja не имеет достаточной информации, чтобы добавить побочный продукт как выходное значение любого правила. CMake 2.8.12 и выше обходят эту проблему и позволяют проектам, использующим вышеуказанный подход, создавать файлы сборки phony, чтобы сообщить Ninja, что такие отсутствующие файлы допустимы. Однако это решение обходит проблему и не позволяет Ninja диагностировать реально отсутствующую зависимость. Оно также плохо работает при инкрементной сборке, где каждый зависимый от пользовательской команды файл, даже исходный файл, должен рассматриваться таким образом, поскольку CMake не имеет достаточной информации, чтобы знать, какие файлы генерируются как побочные продукты пользовательских команд.
CMake 3.2 ввёл опцию BYPRODUCTS для команд add_custom_command() и add_custom_target(). Эта опция позволяет явно указывать побочные продукты:
add_custom_command(
OUTPUT witness.txt
BYPRODUCTS byproduct.txt # explicit byproduct specification
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/input.txt
byproduct.txt # timestamp may not change
...
Опция BYPRODUCTS используется генератором Ninja для включения побочных продуктов среди выходных данных пользовательских команд, которые их генерируют, и игнорируется другими генераторами.
CMake 3.3 и выше предпочитают требовать от проектов явного указания побочных продуктов пользовательских команд, чтобы избежать использования обходного правила phony. Политика CMP0058 была введена для обеспечения совместимости с существующими проектами, которым всё ещё нужно это обходное решение.
Эта политика не влияет на генераторы, кроме Ninja. Поведение OLD для этой политики заключается в генерации правил Ninja phony для неизвестных зависимостей в дереве сборки. Поведение NEW для этой политики заключается в том, чтобы не генерировать их и вместо этого потребовать от проектов явного указания пользовательских команд BYPRODUCTS.
Эта политика была введена в CMake версии 3.3. CMake версии 3.21.0-rc3 предупреждает при обнаружении неизвестных зависимостей в деревьях сборки вне исходного каталога, если политика не установлена, а затем использует поведение OLD. Используйте команду cmake_policy() для явного задания политики на OLD или NEW. Настройка политики должна быть в области действия в конце файла проекта верхнего уровня CMakeLists.txt и имеет глобальное действие.
Примечание
Поведение OLD политики — deprecated by definition и может быть удалено в будущих версиях CMake.
© 2000–2021 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.21/policy/CMP0058.html