Spec-Zone.ru › CMake 3.17

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 будет существовать до того, как его потребители его потребуют. Подробное обсуждение этой проблемы можно найти в Проблеме 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.17.5 предупреждает при обнаружении неизвестных зависимостей в сборках вне исходного дерева, если политика не установлена, и затем использует поведение 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.17/policy/CMP0058.html

Spec-Zone.ru

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