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 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_policy() или cmake_minimum_required(). Если она не установлена, CMake предупреждает о неизвестных зависимостях в сборках вне исходного дерева и использует поведение OLD.
Указание политики должно быть в силе в конце файла проекта верхнего уровня CMakeLists.txt, и оно действует глобально.
Примечание
Поведение OLD политики является deprecated by definition и может быть удалено в будущих версиях CMake.
© 2000–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.30/policy/CMP0058.html