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 терпимо относился к таким отсутствующим файлам. Однако это решение обходит проблему, не позволяя 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.6.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.6/policy/CMP0058.html