Spec-Zone.ru › CMake 3.23

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 работает таким образом.

Вместо того, чтобы оставлять продукты не объявленными в правилах, которые их генерируют, 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.23.3 предупреждает при обнаружении неизвестных зависимостей в деревьях сборки вне исходных каталогов, если политика не задана, а затем использует OLD поведение. Используйте команду cmake_policy(), чтобы явно установить политику в OLD или NEW. Настройка политики должна быть в области действия в конце файла верхнего уровня CMakeLists.txt проекта и имеет глобальное действие.

Примечание

Поведение OLD политики deprecated by definition и может быть удалено в будущей версии CMake.

© 2000–2022 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.23/policy/CMP0058.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API