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