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