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