Merge topic 'cmake-diagnostics-doc'

95f7f84609 Help: Fix CMD_INSTALL_ABSOLUTE_DESTINATION documentation
a882ec84ec cmDocumentation: Add diagnostics
97d13c3053 Help: Improve diagnostics documentation
3cccce8ca2 Help: Add developer documentation for new diagnostics
ffe4c2a8ff Help: Fix developer documentation

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard <robertjmaynard@gmail.com>
Merge-request: !11996
This commit is contained in:
Brad King
2026-05-04 10:32:28 -04:00
committed by Kitware Robot
18 changed files with 409 additions and 82 deletions
+2 -3
View File
@@ -61,9 +61,8 @@ signatures that specify them. The common options are:
but not recommended.
.. versionadded:: 4.4
The :ref:`CMD_INSTALL_ABSOLUTE_DESTINATION <CMD_INSTALL_ABSOLUTE_DESTINATION>`
diagnostic can be enabled to warn or error out when an absolute destination
is provided.
The :diagnostic:`CMD_INSTALL_ABSOLUTE_DESTINATION` diagnostic can be
enabled to warn or error out when an absolute destination is provided.
When a relative path is given, it is interpreted relative to the value
of the :variable:`CMAKE_INSTALL_PREFIX` variable.
+2
View File
@@ -41,12 +41,14 @@ CMake developer documentation is provided by the following documents:
* The `CMake Testing Guide`_.
* The `CMake Experimental Features Guide`_.
* The `CMake Debugging Guide`_.
* The `CMake Diagnostics Guide`_.
.. _`CMake Source Code Guide`: source.rst
.. _`CMake Documentation Guide`: documentation.rst
.. _`CMake Testing Guide`: testing.rst
.. _`CMake Experimental Features Guide`: experimental.rst
.. _`CMake Debugging Guide`: debug.rst
.. _`CMake Diagnostics Guide`: diagnostics.rst
Maintainer Documentation
========================
+157
View File
@@ -0,0 +1,157 @@
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.
+2 -2
View File
@@ -37,7 +37,7 @@ When activated, this experimental feature provides the following:
* The package name associated with specific targets may be specified
using the ``CMAKE_EXPORT_FIND_PACKAGE_NAME`` variable and/or
``EXPORT_FIND_PACKAGE_NAME`` target property.
``EXPORT_FIND_PACKAGE_NAME`` target property.
Export |CPS| Package Information for ``install(EXPORT)``
========================================================
@@ -102,7 +102,7 @@ When activated, this experimental feature provides the following:
* Targets with the property set to a true value will have their C++ build
information exported to the build database.
Software Bill Of Materials |SBOM|
Software Bill Of Materials (SBOM)
=================================
In order to activate support for the :command:`install(SBOM)` command,
+2 -2
View File
@@ -287,10 +287,10 @@ These are:
* ``<cmext/type_traits>``:
* ``cm::is_pair``:
Checks if a type is a std::pair<> type.
Checks if a type is a std::pair<> type.
* ``cm::is_tuple``:
Checks if a type is a std::tuple<> type.
Checks if a type is a std::tuple<> type.
* ``cm::is_container``:
Checks if a type is a container type.
+16
View File
@@ -0,0 +1,16 @@
CMD_AUTHOR
----------
.. diagnostic::
:default: warn
Warn about a build system's incorrect use of CMake, or of a CMake interface
provided by a dependency. This is the category triggered by
:command:`message(AUTHOR_WARNING)`. It is also the ancestor of many other
diagnostic categories.
The most important aspect of this category is that it represents issues with
a project's build system which typically require alteration to the same.
This is to say that users simply trying to build a project obtained elsewhere
will typically not be interested in these warnings, except to perhaps report
them to the project's developer(s).
+9
View File
@@ -0,0 +1,9 @@
CMD_DEPRECATED
--------------
.. diagnostic::
:default: warn
:parent: CMD_AUTHOR
Warn about use of a deprecated function or package. This is the category
triggered by :command:`message(DEPRECATION)`.
@@ -0,0 +1,10 @@
CMD_INSTALL_ABSOLUTE_DESTINATION
--------------------------------
.. diagnostic::
:default: ignore
:parent: CMD_AUTHOR
Warn when an :command:`install` command specifies an absolute ``DESTINATION``
path. Absolute destinations are typically undesirable because they prevent
the installation prefix from being overridden at install time.
+7
View File
@@ -0,0 +1,7 @@
CMD_UNINITIALIZED
-----------------
.. diagnostic::
:default: ignore
Warn if an uninitialized variable is dereferenced.
+12
View File
@@ -0,0 +1,12 @@
CMD_UNUSED_CLI
--------------
.. diagnostic::
:default: ignore
Warn about variables that are declared on the command line, but not used.
This diagnostic is issued outside of the configuration / generation phases.
Accordingly, while the action of this warning category can be queried as
usual, the :command:`cmake_diagnostic` command is unable to affect the action
of this diagnostic.
+52 -61
View File
@@ -32,71 +32,62 @@ issues in several categories:
* Issues that may impact the ability of the project
to be built with newer versions of CMake.
Diagnostic Actions
------------------
Controlling Diagnostics
=======================
The action taken when a particular diagnostic is triggered depends on the
diagnostic category. Most categories will warn by default. The
:command:`cmake_diagnostic` command and :option:`-W <cmake -W>` options can be
used to control what action occurs when a diagnostic of a particular category
is triggered. The possible actions are described in the documentation of the
same.
Each diagnostic category has an associated action to be taken when that
diagnostic is triggered. Most categories will warn by default. The available
actions are described in the :command:`cmake_diagnostic` command documentation.
CMake maintains a diagnostic state stack that is similar to the policy state.
The initial state of the stack is determined by four factors, which are, in
order of precedence:
* The default action associated with the diagnostic.
* The action associated with the diagnostic stored in the CMake variable cache,
which is used to persist the initial state between CMake runs.
* The :preset:`configurePresets.warnings` and :preset:`configurePresets.errors`
fields of :manual:`CMake Presets <cmake-presets(7)>`.
* The :option:`-W[no-][error=] <cmake -W>` command line arguments.
.. note::
Because command line arguments operate both recursively and in the order
specified, some combinations of diagnostic arguments may result in later
arguments completely overwriting the action of earlier arguments. For
example, ``-Wno-child -Wparent`` will result in the ``child`` warning being
enabled, because ``-Wparent`` promotes both ``parent`` and ``child`` to at
least ``WARN`` severity. CMake presets are evaluated in order from most
ancestral to least ancestral.
During script execution, the :command:`cmake_diagnostic` command can be used to
query or alter the state, or to perform limited stack manipulations.
When a diagnostic is issued at configure time (or during script execution, when
CMake is running in script mode), the current diagnostic state controls the
action. Diagnostics issued at generate time, or outside of the configuration
and generation phases must make use of recorded state information. While CMake
strives to preserve this information in a way that matches the recorded state
to the state as of the CMake command which ultimately causes a diagnostic to be
issued, CMake may sometimes fall back to the state when processing of a
subdirectory completed, or even the root state. This may limit the ability of
the :command:`cmake_diagnostic` command to control such diagnostics, especially
if called from a function or included file. This is especially the case for
diagnostics that are not directly coupled to a CMake command.
Diagnostic Categories
=====================
The following categories are defined.
The following categories are defined:
``CMD_AUTHOR`` (``-Wauthor``)
-----------------------------
.. toctree::
:maxdepth: 1
:Default: Warn
Warn about a build system's incorrect use of CMake, or of a CMake interface
provided by a dependency. This is the category triggered by
:command:`message(AUTHOR_WARNING)`. It is also the ancestor of many other
diagnostic categories.
The most important aspect of this category is that it represents issues with
a project's build system which typically require alteration to the same. This
is to say that users simply trying to build a project obtained elsewhere will
typically not be interested in these warnings, except to perhaps report them
to the project's developer(s).
``CMD_DEPRECATED`` (``-Wdeprecated``)
-------------------------------------
:Default: Warn
:Parent: ``CMD_AUTHOR``
Warn about use of a deprecated function or package. This is the category
triggered by :command:`message(DEPRECATION)`.
``CMD_UNINITIALIZED`` (``-Wuninitialized``)
-------------------------------------------
:Default: Ignore
Warn if an uninitialized variable is dereferenced.
``CMD_UNUSED_CLI`` (``-Wunused-cli``)
-------------------------------------
:Default: Warn
Warn about variables that are declared on the command line, but not used.
Although the action of this warning category can be queried as usual, changes
made using the :command:`cmake_diagnostic` command have no effect.
.. _CMD_INSTALL_ABSOLUTE_DESTINATION:
``CMD_INSTALL_ABSOLUTE_DESTINATION`` (``-Winstall-absolute-destination``)
-------------------------------------------------------------------------
:Default: Ignore
Warn when an :command:`install` command specifies an absolute
``DESTINATION`` path. Absolute destinations are typically undesirable
because they prevent the installation prefix from being overridden at
install time.
/diagnostic/CMD_AUTHOR
/diagnostic/CMD_DEPRECATED
/diagnostic/CMD_INSTALL_ABSOLUTE_DESTINATION
/diagnostic/CMD_UNINITIALIZED
/diagnostic/CMD_UNUSED_CLI
@@ -3,8 +3,10 @@ install-absolute-dest-configure-time
* CMake gained the ability to diagnose :command:`install` commands that
specify an absolute ``DESTINATION`` path via the
:ref:`CMD_INSTALL_ABSOLUTE_DESTINATION <CMD_INSTALL_ABSOLUTE_DESTINATION>`
diagnostic category. This diagnostic may be controlled with the
:option:`-Winstall-absolute-destination <cmake -W>` command-line option, the
``installAbsoluteDestination`` field in a :manual:`cmake-presets(7)`
``warnings`` object, or the :command:`cmake_diagnostic` command.
:diagnostic:`CMD_INSTALL_ABSOLUTE_DESTINATION` diagnostic category.
This diagnostic may be controlled with the
:option:`-Winstall-absolute-destination <cmake -W>` command-line option,
the ``installAbsoluteDestination`` field in a
:manual:`CMake Presets <cmake-presets(7)>`
:preset:`configurePresets.warnings` object,
or the :command:`cmake_diagnostic` command.
@@ -11,8 +11,7 @@ running the script, it may get fatal error messages from the script.
.. versionadded:: 4.4
The :ref:`CMD_INSTALL_ABSOLUTE_DESTINATION <CMD_INSTALL_ABSOLUTE_DESTINATION>`
diagnostic can be used to to generate errors for absolute install destinations
at generate time.
The :diagnostic:`CMD_INSTALL_ABSOLUTE_DESTINATION` diagnostic can be used to
generate errors for absolute install destinations at generate time.
See also :variable:`CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION`.
@@ -10,8 +10,7 @@ warning messages from the script.
.. versionadded:: 4.4
The :ref:`CMD_INSTALL_ABSOLUTE_DESTINATION <CMD_INSTALL_ABSOLUTE_DESTINATION>`
diagnostic can be used to to generate warnings for absolute install destinations
at generate time.
The :diagnostic:`CMD_INSTALL_ABSOLUTE_DESTINATION` diagnostic can be used to
generate warnings for absolute install destinations at generate time.
See also :variable:`CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION`.
+44 -1
View File
@@ -26,7 +26,7 @@
#include "cmVersion.h"
namespace {
cmDocumentationEntry const cmDocumentationStandardOptions[21] = {
cmDocumentationEntry const cmDocumentationStandardOptions[] = {
{ "-h,-H,--help,-help,-usage,/?", "Print usage information and exit." },
{ "--version[=json-v1],-version[=json-v1],/V[=json-v1],/version[=json-v1] "
"[<file>]",
@@ -39,6 +39,12 @@ cmDocumentationEntry const cmDocumentationStandardOptions[21] = {
{ "--help-command-list [<file>]",
"List commands with help available and exit." },
{ "--help-commands [<file>]", "Print cmake-commands manual and exit." },
{ "--help-diagnostic <diag> [<file>]",
"Print help for one diagnostic and exit." },
{ "--help-diagnostic-list [<file>]",
"List diagnostics with help available and exit." },
{ "--help-diagnostics [<file>]",
"Print cmake-diagnostics manual and exit." },
{ "--help-module <mod> [<file>]", "Print help for one module and exit." },
{ "--help-module-list [<file>]",
"List modules with help available and exit." },
@@ -164,6 +170,8 @@ bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os)
return this->PrintHelpOneManual(os);
case cmDocumentation::OneCommand:
return this->PrintHelpOneCommand(os);
case cmDocumentation::OneDiagnostic:
return this->PrintHelpOneDiagnostic(os);
case cmDocumentation::OneModule:
return this->PrintHelpOneModule(os);
case cmDocumentation::OnePolicy:
@@ -176,6 +184,8 @@ bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os)
return this->PrintHelpListManuals(os);
case cmDocumentation::ListCommands:
return this->PrintHelpListCommands(os);
case cmDocumentation::ListDiagnostics:
return this->PrintHelpListDiagnostics(os);
case cmDocumentation::ListModules:
return this->PrintHelpListModules(os);
case cmDocumentation::ListProperties:
@@ -377,6 +387,11 @@ bool cmDocumentation::CheckOptions(int argc, char const* const* argv,
cmSystemTools::Message(
"Warning: --help-compatcommands no longer supported");
return true;
} else if (strcmp(argv[i], "--help-diagnostics") == 0) {
help.HelpType = cmDocumentation::OneManual;
help.Argument = "cmake-diagnostics.7";
i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-full") == 0) {
help.HelpType = cmDocumentation::Full;
i += int(get_opt_argument(i + 1, help.Filename));
@@ -393,6 +408,12 @@ bool cmDocumentation::CheckOptions(int argc, char const* const* argv,
i += int(get_opt_argument(i + 1, help.Filename));
help.Argument = cmSystemTools::LowerCase(help.Argument);
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-diagnostic") == 0) {
help.HelpType = cmDocumentation::OneDiagnostic;
i += int(get_opt_argument(i + 1, help.Argument));
i += int(get_opt_argument(i + 1, help.Filename));
help.Argument = cmSystemTools::UpperCase(help.Argument);
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-module") == 0) {
help.HelpType = cmDocumentation::OneModule;
i += int(get_opt_argument(i + 1, help.Argument));
@@ -421,6 +442,9 @@ bool cmDocumentation::CheckOptions(int argc, char const* const* argv,
} else if (strcmp(argv[i], "--help-command-list") == 0) {
help.HelpType = cmDocumentation::ListCommands;
i += int(get_opt_argument(i + 1, help.Filename));
} else if (strcmp(argv[i], "--help-diagnostic-list") == 0) {
help.HelpType = cmDocumentation::ListDiagnostics;
i += int(get_opt_argument(i + 1, help.Filename));
} else if (strcmp(argv[i], "--help-module-list") == 0) {
help.HelpType = cmDocumentation::ListModules;
i += int(get_opt_argument(i + 1, help.Filename));
@@ -622,6 +646,25 @@ bool cmDocumentation::PrintHelpListCommands(std::ostream& os)
return true;
}
bool cmDocumentation::PrintHelpOneDiagnostic(std::ostream& os)
{
std::string dname = cmSystemTools::UpperCase(this->CurrentArgument);
if (this->PrintFiles(os, cmStrCat("diagnostic/", dname))) {
return true;
}
// Argument was not a command. Complain.
os << "Argument \"" << this->CurrentArgument
<< "\" to --help-command is not a CMake diagnostic. "
"Use --help-diagnostic-list to see all diagnostics.\n";
return false;
}
bool cmDocumentation::PrintHelpListDiagnostics(std::ostream& os)
{
this->PrintNames(os, "diagnostic/*");
return true;
}
bool cmDocumentation::PrintHelpOneModule(std::ostream& os)
{
std::string mname = this->CurrentArgument;
+4
View File
@@ -30,6 +30,7 @@ public:
Full,
ListManuals,
ListCommands,
ListDiagnostics,
ListModules,
ListProperties,
ListVariables,
@@ -38,6 +39,7 @@ public:
OneArbitrary,
OneManual,
OneCommand,
OneDiagnostic,
OneModule,
OneProperty,
OneVariable,
@@ -124,12 +126,14 @@ private:
bool PrintHelpOneArbitrary(std::ostream& os);
bool PrintHelpOneManual(std::ostream& os);
bool PrintHelpOneCommand(std::ostream& os);
bool PrintHelpOneDiagnostic(std::ostream& os);
bool PrintHelpOneModule(std::ostream& os);
bool PrintHelpOnePolicy(std::ostream& os);
bool PrintHelpOneProperty(std::ostream& os);
bool PrintHelpOneVariable(std::ostream& os);
bool PrintHelpListManuals(std::ostream& os);
bool PrintHelpListCommands(std::ostream& os);
bool PrintHelpListDiagnostics(std::ostream& os);
bool PrintHelpListModules(std::ostream& os);
bool PrintHelpListProperties(std::ostream& os);
bool PrintHelpListVariables(std::ostream& os);
+2 -2
View File
@@ -20,7 +20,7 @@ cmRST::cmRST(std::ostream& os, std::string docroot)
: OS(os)
, DocRoot(std::move(docroot))
, CMakeDirective("^.. (cmake:)?("
"command|envvar|genex|signature|variable"
"command|diagnostic|envvar|genex|signature|variable"
")::")
, CMakeModuleDirective("^.. cmake-module::[ \t]+([^ \t\n]+)$")
, ParsedLiteralDirective("^.. parsed-literal::[ \t]*(.*)$")
@@ -34,7 +34,7 @@ cmRST::cmRST(std::ostream& os, std::string docroot)
, ModuleRST(R"(^#\[(=*)\[\.rst:$)")
, CMakeRole("(:cmake)?:("
"cref|"
"command|cpack_gen|generator|genex|"
"command|cpack_gen|diagnostic|generator|genex|"
"variable|envvar|module|policy|"
"prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|"
"prop_test|prop_tgt|"
+77
View File
@@ -234,6 +234,7 @@ class _cmake_index_entry:
_cmake_index_objs = {
'command': _cmake_index_entry('command'),
'cpack_gen': _cmake_index_entry('cpack generator'),
'diagnostic': _cmake_index_entry('diagnostic'),
'envvar': _cmake_index_entry('envvar'),
'generator': _cmake_index_entry('generator'),
'genex': _cmake_index_entry('genex'),
@@ -523,6 +524,79 @@ class CMakeSignatureObject(CMakeObject):
return super().run()
class CMakeDiagnosticObject(CMakeObject):
object_type = 'diagnostic'
required_arguments = 0
optional_arguments = 0
DEFAULT_CHOICES = {'ignore', 'warn', 'error'}
def default_option(argument):
return directives.choice(
argument, CMakeDiagnosticObject.DEFAULT_CHOICES)
option_spec = {
'default': default_option,
'parent': directives.unchanged,
}
def __init__(self, *args, **kwargs):
self.targetname = None
super().__init__(*args, **kwargs)
def _preset_name(self) -> str:
sep = False
out = ''
for c in self.targetname[4:]:
if c == '_':
sep = True
elif sep:
out += c
sep = False
else:
out += c.lower()
return out
def _build_field(self, name: str, content: str | list[Node]) -> Node:
if type(content) is not list:
content = self.parse_text_to_nodes(content)
name_node = nodes.field_name(text=name)
body_node = nodes.field_body('', *content)
return nodes.field('', name_node, body_node)
def _build_cli(self) -> list[Node]:
cname = self.targetname[4:].lower().replace('_', '-')
ctext = f'-W[no-][error=]{cname}'
return self.parse_text_to_nodes(f':option:`{ctext} <cmake -W>`')
def _build_preset_refs(self) -> list[Node]:
p = self._preset_name()
w = f':preset:`warnings.{p} <configurePresets.warnings.{p}>`'
e = f':preset:`errors.{p} <configurePresets.errors.{p}>`'
return self.parse_text_to_nodes(f'{w}, {e}')
def run(self) -> list[Node]:
self.domain, self.objtype = self.name.split(':', 1)
doc = self.state.document
self.targetname = doc.next_node(nodes.title).astext()
default = self.options['default'].capitalize()
parent = self.options.get('parent')
headers = nodes.field_list()
headers += self._build_field('Command Line', self._build_cli())
headers += self._build_field('Presets', self._build_preset_refs())
headers += self._build_field('Default', default)
if parent:
parentRef = self.parse_text_to_nodes(f':diagnostic:`{parent}`')
headers += self._build_field('Parent', parentRef)
content = self.parse_content_to_nodes()
return [headers] + content
class CMakeReferenceRole:
# See sphinx.util.nodes.explicit_title_re; \x00 escapes '<'.
_re = re.compile(r'^(.+?)(\s*)(?<!\x00)<(.*?)>$', re.DOTALL)
@@ -680,6 +754,7 @@ class CMakeDomain(Domain):
object_types = {
'command': ObjType('command', 'command'),
'cpack_gen': ObjType('cpack_gen', 'cpack_gen'),
'diagnostic': ObjType('diagnostic', 'diagnostic'),
'envvar': ObjType('envvar', 'envvar'),
'generator': ObjType('generator', 'generator'),
'genex': ObjType('genex', 'genex'),
@@ -700,6 +775,7 @@ class CMakeDomain(Domain):
directives = {
'command': CMakeObject,
'envvar': CMakeObject,
'diagnostic': CMakeDiagnosticObject,
'genex': CMakeGenexObject,
'signature': CMakeSignatureObject,
'variable': CMakeObject,
@@ -710,6 +786,7 @@ class CMakeDomain(Domain):
'cref': CMakeCRefRole(),
'command': CMakeXRefRole(fix_parens=True, lowercase=True),
'cpack_gen': CMakeXRefRole(),
'diagnostic': CMakeXRefRole(),
'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
'genex': CMakeXRefRole(),