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 см. в обсуждении этой проблемы в Ninja Issue 760.
Вместо того, чтобы оставлять побочные продукты не объявленными в правилах, которые их генерируют, Ninja ожидает, что побочные продукты будут перечислены вместе с другими выходными данными. Такие правила могут быть помечены опцией restat, которая сообщает Ninja проверять метки времени выходных данных после выполнения правил. Это предотвращает ненужную пересборку зависимостей от побочных продуктов, метки времени которых не изменяются.
Поскольку вышеуказанный подход не сообщает CMake, какая пользовательская команда генерирует byproduct.txt, генератор Ninja не имеет достаточной информации, чтобы добавить побочный продукт в качестве выходного значения любого правила. CMake 2.8.12 и выше обходят эту проблему, позволяя проектам, использующим вышеуказанный подход, создавать правила сборки phony для того, чтобы сообщить 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.26.0-rc3 предупреждает о неизвестных зависимостях в сборках вне исходных директорий, если политика не установлена, а затем использует поведение OLD. Используйте команду cmake_policy() для явного задания политики OLD или NEW. Настройка политики должна быть в области действия в конце верхнего CMakeLists.txt файла проекта и действует глобально.
Примечание
Поведение OLD политики deprecated by definition и может быть удалено в будущих версиях CMake.
© 2000–2023 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.26/policy/CMP0058.html