mirror of
https://github.com/Kitware/CMake.git
synced 2026-08-09 09:12:00 +00:00
Add a developer-targeted document explaining the basics of how to use CMake 4.4's new diagnostic framework.
158 lines
7.1 KiB
ReStructuredText
158 lines
7.1 KiB
ReStructuredText
CMake Diagnostics Guide
|
|
***********************
|
|
|
|
The following is a guide on how CMake should issue diagnostics.
|
|
See documentation on `CMake Development`_ for more information.
|
|
|
|
.. _`CMake Development`: README.rst
|
|
|
|
TL;DR Porting Guide (from CMake < 4.4)
|
|
======================================
|
|
|
|
I want to write ``IssueMessage(MessageType::AUTHOR_WARNING, ...``:
|
|
Write ``IssueDiagnostic(cmDiagnostics::CMD_AUTHOR, ...`` instead.
|
|
|
|
I want to write ``IssueMessage(MessageType::DEPRECATION_WARNING, ...``:
|
|
Write ``IssueDiagnostic(cmDiagnostics::CMD_DEPRECATED, ...`` instead.
|
|
|
|
I want to write ``IssueMessage(MessageType::AUTHOR_ERROR, ...``:
|
|
No, you don't. Under the old system, there isn't a meaningful difference
|
|
between ``AUTHOR_WARNING`` and ``AUTHOR_ERROR``; at least, not as arguments
|
|
to ``IssueMessage``.
|
|
|
|
I want to write ``IssueMessage(MessageType::DEPRECATION_ERROR, ...``:
|
|
See ``AUTHOR_ERROR``.
|
|
|
|
History
|
|
=======
|
|
|
|
Prior to CMake 4.4, CMake did not have a formal system for issuing diagnostics.
|
|
The messaging system had message types for author diagnostics and deprecation
|
|
diagnostics which conflated category and severity. Worse, although these types
|
|
*purported* to allow the caller to specify severity, this information is not
|
|
actually honored. Other diagnostics existed which did not use these types.
|
|
|
|
More importantly, the mechanisms for managing severity differed depending on
|
|
the diagnostic. Variables to control a diagnostic might be documented,
|
|
undocumented, or non-existent. Spelling of command-line options to control
|
|
diagnostics was inconsistent, as was the ability to make diagnostics fatal.
|
|
Adding new categories required significant effort, as the logic to handle a
|
|
diagnostic was bespoke at every layer.
|
|
|
|
CMake Diagnostic Framework
|
|
==========================
|
|
|
|
CMake 4.4 introduced a structured framework for issuing and managing
|
|
diagnostics. The ``cmDiagnostics.h`` header enumerates all available
|
|
diagnostic categories. All code to manage diagnostics leverages either this
|
|
table or helper code generated from the same, such that it is the *only*
|
|
non-documentation location that needs to be updated to add a new diagnostic
|
|
category. The framework is also responsible for determining the severity of a
|
|
diagnostic, based on the combination of category defaults and user preferences,
|
|
and for presenting the user with a consistent set of control mechanisms.
|
|
|
|
Numeric identifiers associated with diagnostic categories are only used
|
|
internally and are never persisted. This means that numbers can be reassigned
|
|
at any time. This also permits ensuring that numbers are consecutive, which
|
|
allows iterating over all categories using a simple ``for`` loop. (Note that
|
|
such loops will typically start from ``1``, not ``0``, as ``0`` is reserved
|
|
for the 'NONE' category which is used primarily as a virtual parent.) Where
|
|
necessary, macros provided by ``cmDiagnostics.h`` can generate code for each
|
|
diagnostic category.
|
|
|
|
Refer to ``Help/manual/cmake-diagnostics.7.rst`` for user-facing documentation.
|
|
|
|
Issuing Diagnostics
|
|
===================
|
|
|
|
Diagnostics are the CMake equivalent of compiler warnings, with categorization
|
|
providing both additional information and additional response control to users.
|
|
|
|
Diagnostics are issued via the ``IssueDiagnostic`` method. This method is
|
|
provided on various objects, with ``cmMakefile`` being the most prominent, and
|
|
typically exists alongside an ``IssueMessage`` method. The latter is not
|
|
deprecated, and should still be used to issue messages outside of the
|
|
diagnostic categories, such as hard errors or informational messages.
|
|
|
|
The historic ``{AUTHOR,DEPRECATION}_{WARNING,ERROR}`` message types, however,
|
|
have been removed. These are replaced by ``IssueDiagnostic`` and the
|
|
``CMD_{AUTHOR,DEPRECATED}`` diagnostic categories. Because the methods have
|
|
similar signatures, porting in many cases can be accomplished by replacing the
|
|
method name and first argument (the former message type, newly the diagnostic
|
|
category). For example, where prior versions of CMake wrote:
|
|
|
|
.. code:: c++
|
|
|
|
mf->IssueMessage(MessageType::AUTHOR_WARNING, ...);
|
|
|
|
CMake 4.4 and later should write:
|
|
|
|
.. code:: c++
|
|
|
|
mf->IssueDiagnostic(cmDiagnostics::CMD_AUTHOR, ...);
|
|
|
|
(Note that the ``"cmDiagnostics.h"`` header may need to be newly included.)
|
|
|
|
As previously mentioned, the purported severity was ignored by ``cmMessenger``,
|
|
which instead used its own internal state to decide whether a message should
|
|
be a warning or an error. This logic overrode the severity component of the
|
|
message type as passed into the method. As a result, although the new method
|
|
does not accept a severity, this is actually consistent with the historic
|
|
behavior and does not represent any loss of functionality.
|
|
|
|
.. note::
|
|
|
|
When issuing diagnostics targeted at build-system authors, please consult the
|
|
complete list of available diagnostics, as a more specific category may be
|
|
available. In some cases, it may even make sense to add a new category.
|
|
|
|
Adding Diagnostic Categories
|
|
============================
|
|
|
|
Adding new diagnostic categories involves four steps.
|
|
|
|
1. The new category must be added to ``cmDiagnostics.h``. The diagnostics
|
|
table looks like this:
|
|
|
|
.. code:: c++
|
|
|
|
#define CM_FOR_EACH_DIAGNOSTIC_TABLE(ACTION, SELECT) \
|
|
SELECT(ACTION, Warn, CMD_NONE, CMD_AUTHOR, 12) \
|
|
SELECT(ACTION, Warn, CMD_AUTHOR, CMD_DEPRECATED, 1) \
|
|
...
|
|
|
|
Add a new entry. All entries must begin with ``SELECT(ACTION,``. The
|
|
second argument is the *default* state of the diagnostic and should
|
|
typically be ``Warn``, but may be ``Ignore`` if the diagnostic should be
|
|
opt-in. Defaulting to ``SendError`` would be exceptional, and defaulting
|
|
to ``FatalError`` is not recommended under any circumstances. The third
|
|
argument is the *parent* of the diagnostic (see below). The fourth is the
|
|
actual name of the diagnostic. The fifth and final argument is the CMake
|
|
preset version corresponding to the introduction of the argument, which
|
|
should be the latest preset version as used by the version of CMake under
|
|
development.
|
|
|
|
.. note::
|
|
|
|
In the event that the development version has not already introduced a
|
|
new preset version, adding a new diagnostic will additionally require
|
|
introducing a new preset version.
|
|
|
|
Diagnostics are hierarchical and **must** be listed in order of a
|
|
depth-first search. (If you imagine the order of items in a typical tree
|
|
view which has been fully expanded, that is depth-first order.) Each
|
|
diagnostic has a direct parent. Recursive alterations to a diagnostic will
|
|
also affect all descendant diagnostics.
|
|
|
|
2. A documentation page for the new diagnostic must be created under
|
|
``Help/diagnostic``, and a link to the same added to the Diagnostics
|
|
manual, ``Help/manual/cmake-diagnostics.7.rst``.
|
|
|
|
3. The new presets fields must be mentioned in the CMake presets version
|
|
history, found at the bottom of ``Help/manual/cmake-presets.7.rst``. Note
|
|
that the documentation of the fields themselves is generated.
|
|
|
|
4. The ``Utilities/Scripts/regenerate-presets.py`` script must be run to
|
|
generate the updated presets schema and documentation. Don't forget to
|
|
review and commit the changes made by this script.
|