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