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