Найти в Дзене
coding style

CMake - Практическое руководство. Глава 14. Отладка и диагностика (Крэйг Скотт, перевод на русский язык)

Когда сборка идет нормально, пользователи, как правило, не обращают особого внимания на вывод, генерируемый CMake. Однако для разработчиков, работающих над проектом, диагностический вывод и возможности отладки очень важны. CMake всегда предоставлял базовую функциональность для вывода сообщений, но улучшения, добавленные в версиях 3.15-3.18, значительно расширили доступные возможности. CMake всегда поддерживал вывод текстовых сообщений с помощью команды message(), которая была кратко представлена в разделе 6.7, «Печать значений переменных». Более общая форма этой команды такова: Если указано более одного msg, они будут объединены в одну строку без разделителей. Чтобы сохранить пробелы, точки с запятой или новую строку, окружите сообщение кавычками (подробное объяснение причин см. в разделе 9.8, «Проблемы с обработкой аргументов»). На вывод сообщения могут влиять необязательный аргумент mode, параметры командной строки cmake и значение нескольких переменных на момент вызова. В следующих
Оглавление

Когда сборка идет нормально, пользователи, как правило, не обращают особого внимания на вывод, генерируемый CMake. Однако для разработчиков, работающих над проектом, диагностический вывод и возможности отладки очень важны. CMake всегда предоставлял базовую функциональность для вывода сообщений, но улучшения, добавленные в версиях 3.15-3.18, значительно расширили доступные возможности.

14.1. Команда message()

CMake всегда поддерживал вывод текстовых сообщений с помощью команды message(), которая была кратко представлена в разделе 6.7, «Печать значений переменных». Более общая форма этой команды такова:

-2

Если указано более одного msg, они будут объединены в одну строку без разделителей. Чтобы сохранить пробелы, точки с запятой или новую строку, окружите сообщение кавычками (подробное объяснение причин см. в разделе 9.8, «Проблемы с обработкой аргументов»).

На вывод сообщения могут влиять необязательный аргумент mode, параметры командной строки cmake и значение нескольких переменных на момент вызова. В следующих подразделах мы подробно рассмотрим их.

14.1.1. Уровни логгирования

Команда message() принимает необязательное ключевое слово mode, которое предоставляет информацию о типе выдаваемого сообщения. Оно влияет на то, как и куда будет выведено сообщение, будет ли оно выведено вообще, а в некоторых случаях может остановить работу CMake. Возможные значения для mode следующие (порядок определяет уровень значимости):

  • FATAL_ERROR Обозначает критическую ошибку. Обработка будет остановлена сразу после вывода сообщения, а в журнал обычно записывается местоположение команды message().
  • SEND_ERROR Тоже что и FATAL_ERROR, за исключением того, что обработка будет продолжена до завершения этапа конфигурирования, но генерация не будет выполнена. Это может запутать пользователей, поэтому проекты должны избегать этого режима и предпочитать использовать вместо него FATAL_ERROR.
  • WARNING Обозначает предупреждение. В журнал обычно записывается местоположение команды message(), вызвавшей предупреждение. Обработка будет продолжена.
  • AUTHOR_WARNING Как и WARNING, но показывается только в том случае, если предупреждения разработчика включены (чтобы отключить их, используйте опцию -Wno-dev в командной строке cmake). Проекты не часто используют этот тип сообщений, обычно они генерируются самим CMake.
  • DEPRECATION Специальная категория, используемая для регистрации сообщения об устаревании. Если переменная CMAKE_ERROR_DEPRECATED имеет значение true, сообщение будет рассматриваться как ошибка. Если переменная CMAKE_WARN_DEPRECATED имеет значение true, сообщение будет рассматриваться как предупреждение. Если ни одна из этих переменных не установлена, сообщение будет показано для CMake 3.5 или более поздних версий и скрыто для более ранних.
  • NOTICE Это ключевое слово распознается только в CMake 3.15 или более поздней версии, но для всех версий это значение используется по умолчанию, если не указано ключевое слово mode. Это ключевое слово было добавлено для единообразия и для того, чтобы проекты могли более четко определять смысл таких сообщений. Избегайте использования этого значения, если сообщение не требует никаких действий от пользователя (см. далее).
  • STATUS Лаконичная информация о состоянии, обычно занимающая одну строку. Предпочтительнее использовать этот режим сообщений, а не NOTICE для чисто информационных сообщений.
  • VERBOSE (только для CMake 3.15 или более поздних версий) Более подробная информация, которая обычно не представляет интереса, но может быть полезна пользователям проекта при поиске более глубокого понимания происходящего.
  • DEBUG (только CMake 3.15 или более поздняя версия) Не предназначены для пользователей проекта, а скорее для разработчиков, работающих над самим проектом. В них могут быть записаны внутренние детали реализации, которые не будут интересны тем, кто просто хочет собрать проект.
  • TRACE (только CMake 3.15 или более поздняя версия) Очень низкий уровень детализации, используется почти исключительно для временных сообщений во время разработки проекта.

Сообщения уровня STATUS и до TRACE выводятся в stdout, а NOTICE и выше - в stderr. Это может привести к тому, что сообщения разных уровней журнала иногда будут появляться в выводе не по порядку. Кроме того, сообщения на stderr обычно означают наличие проблемы или чего-то, что пользователь должен исследовать, поэтому NOTICE обычно плохо подходит для чисто информационных сообщений, которые не требуют продолжения. Для таких сообщений используйте STATUS или ниже.

Сообщения от STATUS до TRACE также могут иметь автоматический префикс из двух дефисов и пробела. Приложение CMake GUI и инструмент ccmake не добавляют этот префикс, в то время как текущая версия инструмента cmake добавляет его. Будущие версии CMake могут полностью отказаться от этого префикса, поэтому не рассчитывайте на его наличие. Для сообщений уровня NOTICE и выше такой префикс не добавляется.

В CMake 3.15 также была добавлена возможность установить минимальный уровень логгирования с помощью опции командной строки --loglevel=.... В CMake 3.16 эта опция была переименована в --log-level из соображений единообразия, но --loglevel по-прежнему принимается для обратной совместимости. Опция задает желаемый уровень, и будут показаны только сообщения этого уровня или выше. Если опция --log-level не указана, будут записываться только сообщения уровня STATUS или выше.

-3

В CMake 3.17 добавлена возможность указывать уровень логгирования по умолчанию с помощью переменной CMAKE_MESSAGE_LOG_LEVEL. Она переопределяется опцией командной строки --log-level, если присутствуют обе. Переменная уровня кэша предназначена только для разработчиков, проекты не должны пытаться читать или изменять ее.

Если проект хочет выполнять какие-то действия только на определенных уровнях журнала, то в CMake 3.24 и более ранних версиях нет возможности сделать это надежно. Переменная CMAKE_MESSAGE_LOG_LEVEL не является надежным индикатором текущего уровня журнала. Опция --log-level могла быть передана в командной строке cmake, и она переопределяет переменную, если заданы оба параметра (значение переменной не обновляется, чтобы отразить настройку командной строки). В CMake 3.25 и более поздних версиях текущий уровень журнала можно надежно получить с помощью команды cmake_language(GET_MESSAGE_LOG_LEVEL). При этом учитывается как переменная, так и опция командной строки, возвращая активный уровень журнала на момент вызова. Пример использования:

-4

14.1.2. Отступы в сообщениях

Когда проект делает большое количество сообщений, добавление некоторой структуры может помочь пользователю лучше понять, к какой части проекта относится каждое сообщение. Одним из способов сделать это является использование переменной CMAKE_MESSAGE_INDENT. При использовании CMake 3.16 или более поздней версии содержимое этой переменной на момент вызова message() будет конкатенировано и добавлено к сообщению для уровней NOTICE и ниже. Если сообщение содержит перевод строки, содержимое CMAKE_MESSAGE_INDENT будет добавлено к каждой новой строке вывода.

-5
-6

Хотя приведенный выше пример демонстрирует, как работает эта функция, у нее есть проблемы. Обычно предполагается, что элементы одного списка в CMAKE_MESSAGE_INDENT будут содержать только пробельные символы, обычно по два пробела. Это не является требованием, но отклонение от него, скорее всего, будет раздражать пользователей. Проекты также никогда не должны использовать set() для переменной, они должны только добавлять значений к ней, обычно вызывая list(APPEND). Это позволяет избежать любых предположений о содержимом переменной и всегда сохранять существующие отступы. Это особенно важно для вывода иерархических проектов (подробно рассматривается в главе 39, FetchContent) или при использовании отступов внутри вызовов функций.

Следующий пример демонстрирует вышеупомянутые рекомендации и то, как их можно применить на практике.

-7
-8

Обратите внимание, что отступы вывода функций funcA() и funcB() различаются в зависимости от стека вызовов. Особенность примера заключается в том, что, поскольку функции вводят собственную область видимости переменных, нет необходимости удалять отступ перед возвратом. Вызывающая функция имеет свою отдельную копию переменной CMAKE_MESSAGE_INDENT, поэтому с ее точки зрения значение переменной не меняется в результате вызова функции.

Проекты могут добавлять поддержку отступов, даже если их минимальная версия CMake меньше 3.16. В более старых версиях CMake отступы будут просто игнорироваться, и результат останется неизменным.

14.1.3. Контексты сообщений

В CMake 3.17 поддержка метаданных сообщений расширена еще больше. Подобно тому, как CMAKE_MESSAGE_INDENT может использоваться для обеспечения отступов, переменная CMAKE_MESSAGE_CONTEXT может использоваться для предоставления информации о контексте, в котором генерируется каждое сообщение. В нее можно записать, например, имя проекта или какую-то логическую часть в проекте. Пользователи могут указать CMake выводить информацию о контексте вместе с каждым сообщением, включив в командную строку cmake параметр --log-context.

Если задана опция --log-context и CMAKE_MESSAGE_CONTEXT не пуст, то для каждой строки вывода при вызове message() будет сгенерирован префикс. Этот префикс будет представлять собой конкатенацию элементов в CMAKE_MESSAGE_CONTEXT, причем каждый элемент будет разделен точкой. Результат будет заключен в квадратные скобки, а в конце префикса будет добавлен пробел. Для сообщений, регистрируемых на уровне STATUS или ниже, контекст следует после любых ведущих дефисов, которые могут быть добавлены cmake.

CMakeLists.txt:

-9

networking/CMakeLists.txt:

-10

graphics/CMakeLists.txt:

-11

Запуск cmake --log-context для вышеупомянутой команды приведет к следующему результату:

-12

Проверки возможностей компилятора запускаются вызовом project(), поэтому Coolio добавляется к CMAKE_MESSAGE_CONTEXT перед этим вызовом, чтобы гарантировать, что вывод проверки содержит информацию о контексте. Последние несколько строк в конце вывода, которые фиксируют завершение различных этапов выполнения, всегда не будут содержать контекста.

Обычно предполагается, что при включении вывода контекстной информации этот вывод будет подвергаться некоторой постобработке, а не показываться непосредственно пользователю. Например, инструмент IDE может использовать это, чтобы получить представление о структуре вывода и предложить пользователю возможности фильтрации. IDE может поддерживать расширение и свертывание, показ и скрытие частей вывода cmake в соответствии с их интересами.

Другим вариантом использования могут быть скриптовые сборки. Они могут использовать такие команды Unix, как tee и awk, для сохранения полного журнала в файл, но при этом показывать вывод без деталей, чтобы его можно было отслеживать в реальном времени. Сохраненный файл может быть просмотрен позже, чтобы найти конкретные строки, представляющие интерес. Ниже приведен один из способов выполнения этой задачи в оболочке bash на Unix-подобной системе (он также удаляет любой ведущий префикс дефиса вместе с информацией о контексте):

-13

Затем можно извлечь из сохраненного файла журнала только сообщения, связанные с работой в сети, с помощью инструмента типа grep:

-14

CMake накладывает определенные ограничения на то, что проект может использовать в качестве имен контекстов. Допустимые имена контекста (т.е. каждый элемент списка CMAKE_MESSAGE_CONTEXT) - это те, которые могут быть использованы в качестве имени переменной CMake. По большей части это означает буквы, цифры и символы подчеркивания. Кроме того, CMake считает имена контекстов, начинающиеся с cmake_ или ведущего символа подчеркивания, зарезервированными для собственного использования.

Контексты сообщений особенно эффективны, когда вызовы message() задают соответствующие уровни логгирования. Например, проекты могут предоставлять более подробную информацию, используя уровень VERBOSE, но только довольно минимальный вывод на уровне STATUS или выше. В этом случае вывод по умолчанию не будет загроможден, но использование параметра --log-level VERBOSE обеспечит дополнительную детализацию при необходимости. Пользователи могут сосредоточиться на нужных им деталях путем поиска интересующего их контекста сообщения.

14.1.4. Проверочные сообщения

Еще одна полезная функция, доступная в CMake 3.17 или более поздней версии - поддержка сообщений, которые выводят статус некоторой проверки. Синтаксис по сути тот же, что и у основной формы команды message(), но значение первого аргумента отличается:

-15

Ожидается, что аргумент checkState будет иметь одно из следующих значений:

  • CHECK_START Означает начало проверки. Сообщение должно быть коротким, в идеале не более нескольких слов. Оно будет повторено как часть сообщения о прохождении или отказе в конце проверки.
  • CHECK_PASS Проверка завершена успешно.
  • CHECK_FAIL Проверка завершилась с ошибкой.

Сообщения о запуске, прохождении и неудаче всегда выводятся с уровнем STATUS. Значение успеха или неудачи зависит от логики проекта, и неудача не обязательно означает ошибку. Например, проект может проверять несколько связанных вещей и останавливаться при первом успешном обнаружении.

По завершении проверки (успех или провал) команда message() повторит сообщение из последнего CHECK_START, а затем «забудет» это сообщение. Вывод результатов вложенных проверок работает интуитивно понятно и с минимальными усилиями. В сочетании с соответствующими отступами с помощью CMAKE_MESSAGE_INDENT читабельность и согласованность вывода особенно хороши.

-16

В результате будут выведены строки, похожие на следующие:

-17

Начиная с CMake 3.26, сообщения от различных проверок записываются в файл в формате YAML, предназначенный для чтения как человеком, так и скриптами. Имя и расположение файла могут измениться в будущих версиях CMake, но, по крайней мере, сейчас его можно найти по адресу <buildDir>/CMakeFiles/CMakeConfigureLog.yaml. В большинстве случаев разработчикам не нужно знать об этом файле, но он может быть использован для выявления проблем, когда проверки ведут себя не так, как ожидалось. Команда message() позволяет записывать записи в этот лог-файл в форме message(CONFIGURE_LOG «...»). Такая возможность требуется редко и предназначена только для случаев, когда в проекте реализуется особый вид проверки, не основанный на try_compile() или try_run(). Обратитесь к официальной документации команды message(), чтобы узнать, как и когда использовать эту специальную форму.

14.2. Цвет сообщений

Некоторые компиляторы поддерживают отображение предупреждений и ошибок цветным текстом. Когда вывод сборки длинный или пользовательские задачи генерируют много менее интересных результатов, отображение предупреждений и ошибок разными цветами помогает привлечь внимание к более важной информации. Это может быть очень полезно для разработчиков в их повседневной работе.

Цветной вывод обычно осуществляется путем вставки в вывод кодов форматирования ANSI. Эти коды затем интерпретируются потребителем, применяя инструкции по раскраске, которые они представляют, вместо того чтобы показывать необработанные символы. Соглашения для кодов ANSI очень старые и устоявшиеся, но они поддерживаются не во всех сценариях. Компиляторы, предлагающие такую функциональность, обычно пытаются автоматически определить, поддерживает ли их вызывающая среда, и добавляют ANSI-коды только в том случае, если это безопасно. К сожалению, такое автоматическое обнаружение часто нарушается способом вызова компилятора. Вывод компилятора может передаваться между процессами, он может буферизироваться инструментом сборки, или IDE может перехватывать вывод и показывать его в компоненте GUI. В подобных сценариях у компилятора нет терминала для опроса его возможностей, поэтому вывод цвета обычно отключается.

Компиляторы обычно предлагают возможность отменить автоопределение, но флаги командной строки зависят от компилятора. В CMake 3.24 и более поздних версиях переменная CMAKE_COLOR_DIAGNOSTICS может быть установлена для определения поведения, не зависящего от компилятора. Установка этой переменной в true включит вывод цвета для компиляторов, которые его поддерживают, а установка в false отключит вывод цвета (полезно, если автоопределение компилятора неверно определило, что вывод цвета поддерживается). Если переменная не установлена, будет использоваться автоопределение компилятора, что соответствует поведению CMake 3.23 и более ранних версий.

Если переменная CMAKE_COLOR_DIAGNOSTICS не определена при первом запуске CMake в каталоге сборки, она инициализируется из одноименной переменной окружения, если она установлена. Это в первую очередь предназначено для IDE, чтобы они могли включать цветовую диагностику по умолчанию для инициируемых ими вызовов CMake.

Переменная CMAKE_COLOR_DIAGNOSTICS также может включить цветной вывод некоторых инструментов сборки. Она заменяет гораздо более старую переменную CMAKE_COLOR_MAKEFILE, которая больше не нужна. CMAKE_COLOR_DIAGNOSTICS является более общей и управляет цветовой диагностикой для более широкого спектра инструментов, поэтому ей следует отдать предпочтение.

14.3. CMakePrintHelpers

Модуль CMakePrintHelpers предоставляет два макроса, которые делают вывод значений свойств и переменных более удобной во время разработки. Они не предназначены для постоянного использования, а больше направлены на то, чтобы помочь разработчикам быстро и легко выводить временную информацию, чтобы помочь исследовать проблемы в проекте.

-18

Эта команда, по сути, объединяет get_property() и message() в один вызов. Необходимо указать только один из типов свойств, и каждое из названных свойств будет выведено для каждой сущности, указанной в списке. Это особенно удобно для регистрации значений нескольких сущностей или свойств.

-19
-20

Модуль также предоставляет аналогичную функцию для вывода значения одной или нескольких переменных:

-21

Это работает для всех переменных, независимо от того, были ли они явно заданы в проекте, автоматически заданы CMake или не были заданы вообще.

-22
-23

14.4. Отслеживание доступа к переменным

Еще одним механизмом отладки использования переменных является команда variable_watch(). Она предназначена для более сложных проектов, где может быть неясно, как переменная получила то или иное значение. Когда переменная находится под наблюдением, все попытки прочитать или изменить ее записываются в журнал.

-24

В подавляющем большинстве случаев достаточно указать переменную, за которой нужно следить, без дополнительной команды, так как в этом случае выводятся сведения обо всех обращениях к переменной. Для более настраиваемой степени контроля можно задать команду, которая будет выполняться каждый раз, когда переменная будет прочитана или изменена. Предполагается, что команда будет именем функции или макроса CMake, который получит следующие аргументы:

  • Имя переменной
  • Тип доступа
  • Значение переменной
  • Имя текущего CMake файла
  • Стек вызовов со списком CMake файлов

На практике указание команды для variable_watch() встречается крайне редко. Сообщения по умолчанию обычно достаточно, чтобы помочь диагностировать ситуации, в которых обычно используется variable_watch(). Сообщение по умолчанию также содержит больше деталей о стеке вызовов, чем доступно в последнем аргументе.

14.5. Отладка генераторных выражений

Генераторные выражения могут сильно усложняться, и подтвердить их правильность бывает непросто. Поскольку они оцениваются только во время генерации, их результаты недоступны на этапе конфигурирования и поэтому не могут быть выведены с помощью команды message().

Одним из способов отладки значения генераторного выражения является использование команды file(GENERATE), которая рассматривается в разделе 21.3, «Чтение и запись файлов напрямую». Генераторное выражение может быть записано во временный файл и проверено по завершении выполнения CMake. Например:

-25

Другой подход заключается в создании временной пользовательской цели, команда которой печатает значение генераторного выражения (см. раздел 20.1, «Пользовательские цели»). Сборка этой цели выводит результат выражения.

-26

Построение этой цели и вывод может выглядеть следующим образом:

-27

Эта техника особенно полезна для генераторных выражений, специфичных для конкретной конфигурации, а также при использовании мультиконфиговых генераторов, таких как Xcode, Visual Studio и Ninja Multi-Config:

-28

Для мультиконфиговых генераторов, собираемая конфигурация может быть задана следующим образом

-29
-30

14.6. Профилирование вызовов CMake

В CMake 3.18 добавлена возможность профилирования обработки проекта самим CMake. Для больших и сложных проектов, где этап конфигурирования занимает много времени, это может дать ценную информацию о том, на что тратится время. Когда профилирование включено, каждый вызов команды CMake записывается в вывод профилирования.

Чтобы включить профилирование, необходимо указать оба следующих параметра командной строки:

--profiling-output=fileName Данные профилирования будут записаны в указанный файл

--profiling-format=fmt Здесь указывается формат данных профилирования. Единственным поддерживаемым значением fmt является google-trace, но в будущих версиях CMake это значение может быть расширено для включения других форматов.

Для формата google-trace выходной файл может быть загружен непосредственно в веб-браузер Chrome (перейдите по URL about:tracing) или некоторые IDE (например, Qt Creator). Использование расширения .json для имени выходного файла может облегчить его поиск и загрузку в инструменты, которые понимают формат google-trace.

-31

Результаты профилирования часто показывают, что большую часть времени выполнения занимают такие вызовы, как try_compile() и execute_process(). Вместо того чтобы сосредоточиться конкретно на этих двух вызовах, проанализируйте стеки вызовов, которые привели к этим командам. Возможно, есть возможности сократить частоту вызова этих двух команд за счет отказа от ненужной или слишком пессимистичной логики выше в стеке вызовов.

14.7. Отмена результатов

При попытке отследить неправильное поведение логики CMake в проекте, рекомендуемый шаг отладки - удалить все кэшированные результаты из существующего каталога сборки, а затем проверить, сохраняется ли проблема. Для небольших проектов удаление всего каталога сборки часто является самым простым способом достижения этой цели. Для очень больших проектов потеря всех скомпилированных объектных файлов и других артефактов сборки может оказаться неприемлемой. Может потребоваться более хирургический подход к удалению меньшего подмножества файлов и каталогов.

Файл CMakeCache.txt в верхней части каталога сборки является основным местом, где кэшируется информация. В некоторых сценариях разработчику может понадобиться удалить этот файл, чтобы пересчитать кэшированную информацию или отменить ручные изменения. Примеры, когда этот файл следует удалить, включают:

  • Зависимость может быть обновлена или удалена
  • Переменная кэша, которую разработчик добавил или временно изменил, может быть больше не нужна, и вместо нее следует использовать значения по умолчанию
  • Компилятор или другие инструменты сборки, могли быть обновлены или изменены

Если что-то в цепочке инструментов изменилось, каталог CMakeFiles также должен быть удален. Здесь CMake кэширует информацию о цепочке инструментов после выполнения различных проверок при первом запуске.

В CMake 3.24 и более поздних версиях в командной строке cmake можно передать опцию --fresh. Эта опция указывает CMake удалить как файл CMakeCache.txt, так и каталог CMakeFiles. Это в основном удобство для разработчиков, дополнительным преимуществом которого является то, что не нужно запоминать детали того, где CMake кэширует те или иные файлы. Эта же функция была доступна в графическом интерфейсе CMake для гораздо более ранних версий CMake. Ее можно найти в меню «Файл» в виде действия «Удалить кэш...».

14.8. Интерактивная отладка

В CMake 3.27 добавлена поддержка подключения CMake к отладчику на стадии конфигурирования с помощью стандартного протокола Debug Adapter Protocol. Эта возможность предназначена для IDE, которые могут обеспечить интерактивную отладку, подобную традиционным отладчикам для таких языков, как C и C++. Такие отладчики позволяют построчно выполнять файл CMakeLists.txt на этапе конфигурирования. Переменные и свойства доступны для чтения, могут быть установлены точки останова и так далее.

Поскольку это относительно новая функция CMake, IDE потребуется некоторое время, чтобы разработать и стабилизировать ее поддержку. Уже есть несколько IDE с начальной поддержкой, но следует ожидать пробелов в функциональности и ошибок, пока эта поддержка не станет более зрелой.

Обратите внимание, что интерактивная отладка CMake охватывает только этап конфигурирования CMake. Она не может выполнять такие действия, как оценка генераторных выражений, поскольку они могут быть вычислены только после завершения фазы конфигурирования. Техники для таких сценариев см. в разделе 14.5, «Отладка генераторных выражений».

14.9. Рекомендуемые практики

Общая проблема многих проектов заключается в том, что на этапе конфигурирования в консоль выводится чрезмерное количество данных. Это приучает пользователей игнорировать вывод, что, в свою очередь, означает, что важные сообщения и предупреждения легко пропустить. Когда вывод достаточно минимален, а предупреждение все же возникает, пользователи, как правило, обращают на него внимание и выясняют причину. Поэтому старайтесь минимизировать объем вывода в режиме логгирования STATUS, делая более подробный вывод для режима VERBOSE или ниже. Если вы поддерживаете CMake версии старше 3.15, в которой уровни логгирования ниже STATUS недоступны, подумайте о том, чтобы сохранить опцию включения подробного вывода в кэш переменную, которая должна быть отключена по умолчанию.

Для сообщений, которые должны будут оставаться в проекте, старайтесь всегда указывать уровень логгирования в качестве первого аргумента команды message(). Если сообщение носит общий информационный характер, предпочтите использовать STATUS вместо пропуска аргумента, чтобы вывод сообщений не выглядел неупорядоченным. Временные отладочные сообщения часто указываются без первого аргумента для удобства, но если они останутся частью проекта на какое-то время, лучше, чтобы они тоже имели уровень логгирования.

Для нетривиальных проектов рассмотрите возможность добавления информации о контексте сообщений, чтобы пользователи могли отфильтровать вывод журнала и сосредоточиться только на тех сообщениях, которые их интересуют. Никогда не удаляйте существующее содержимое переменной CMAKE_MESSAGE_CONTEXT, всегда используйте list(APPEND) перед началом нового контекста сообщений. Если контекст сообщений должен завершиться до конца текущей области видимости, используйте list(POP_BACK). Не делайте никаких предположений о том, что содержит переменная, кроме использования техники APPEND/POP_BACK. Рассмотрите возможность добавления имени проекта в качестве контекста сообщения непосредственно перед первым вызовом project() в файле CMakeLists.txt верхнего уровня, чтобы проверки возможностей компилятора также имели контекст сообщения.

Аналогичным образом рассмотрите возможность использования переменной CMAKE_MESSAGE_INDENT для придания логической структуры выводимым сообщениям. Предпочтительно добавлять два пробела для отступа. Хотя допускаются и другие отступы, следование этому соглашению сделает вывод более последовательным, особенно в иерархических проектах, использующих внешние зависимости. Используйте list(APPEND) для добавления к существующему отступу, никогда не заменяйте и не отбрасывайте существующее содержимое переменной CMAKE_MESSAGE_INDENT. При необходимости list(POP_BACK) может быть использован для повторного уменьшения отступа до конца текущей области видимости.

Переменные CMAKE_MESSAGE_CONTEXT и CMAKE_MESSAGE_INDENT могут быть установлены проектом независимо от минимальной поддерживаемой версии CMake. Если используется более ранняя версия CMake, которая не знает об этих переменных, она просто проигнорирует их, и вывод не пострадает. Поэтому используйте эти возможности, даже если проект должен поддерживать более ранние версии CMake. Обратите внимание, что команда list(POP_BACK) требует CMake 3.15 или более поздней версии, поэтому если проекту требуется поддержка более ранних версий, он должен использовать альтернативные команды для достижения того же эффекта, где это необходимо. Однако в большинстве случаев новый контекст сообщения или уровень отступа будет применяться до конца текущей области видимости, и в этом случае удаление последнего значения из конца переменной командой list не потребуется.

Рассмотрите возможность использования формы CHECK_START, CHECK_PASS и CHECK_FAIL команды message() для записи подробностей проверок. Это уменьшает дублирование сообщений и улучшает читаемость. Это особенно эффективно в сочетании с поддержкой отступов, обеспечиваемой переменной CMAKE_MESSAGE_INDENT.

Если этап конфигурирования проекта занимает много времени, запустите cmake с опциями --profiling-output и --profiling-format, чтобы выяснить, на что тратится время. Доступные в CMake 3.18 или более поздней версии, эти опции позволяют генерировать информацию о профилировании на уровне команд, которую можно просмотреть с помощью таких инструментов, как веб-браузер Chrome или IDE, например Qt Creator и CLion.

В разделе 34.7, «Отладка вызовов find_...()», также обсуждаются дополнительные возможности отладки, добавленные в CMake 3.17 и более поздних версиях. Эти возможности связаны с поиском файлов, пакетов и других вещей, что подробно рассматривается в главе 34 «Поиск вещей».

Это был ознакомительный фрагмент книги Professional CMake: A Practical Guide by Craig Scott