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.12.4 предупреждает, когда видит неизвестные зависимости в деревьях внеисходной сборки, если политика не установлена, и затем использует поведение 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.12/policy/CMP0058.html