Spec-Zone.ru › CMake

CMP0058

Предупреждение

Поведение OLD этой политики было удалено в версии CMake 4.0. Эта политика должна быть установлена в NEW вызовом cmake_minimum_required() или cmake_policy().

Добавлено в версии 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 см. в обсуждении этой проблемы в обсуждении проблемы 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 пользовательских команд.

Настройка политики должна действовать в конце файла CMakeLists.txt верхнего уровня проекта и имеет глобальный эффект.

Эта политика была введена в версии CMake 3.3. До её удаления в версии CMake 4.0 её можно было установить с помощью cmake_policy() или cmake_minimum_required(). Если политика не была установлена, CMake выдавал предупреждение при обнаружении неизвестных зависимостей в деревьях сборки вне исходного дерева и использовал поведение OLD.

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

Spec-Zone.ru

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