Browse Source

Utilities/Sphinx: Allow explicit target for genex

Split the genex directive into its own class, allowing a slight
simplification of CMakeObject. Add ability to specify an explicit target
name for the same.

Use this to provide a target for the `$<TARGET_PROPERTY:prop>` generator
expression which is otherwise missing one (due to overlap with
`$<TARGET_PROPERTY:tgt,prop>`).  With this one can write:

    :genex:`$<TARGET_PROPERTY:prop> <TARGET_PROPERTY:prop>`

to link the second variant.

Fixes: #24573
Matthew Woehlke 2 years ago
parent
commit
2e37a20f02

+ 4 - 0
Help/dev/documentation.rst

@@ -241,6 +241,10 @@ Document a "genex" object:
 
 The directive requires a single argument, the generator expression name.
 
+The optional ``:target:`` option allows a custom target name to be specified.
+Because this will affect the ability to reference the "genex" object using the
+``:genex:`` role, this option should be used very sparingly.
+
 ``signature`` directive
 ^^^^^^^^^^^^^^^^^^^^^^^
 

+ 1 - 0
Help/manual/cmake-generator-expressions.7.rst

@@ -1418,6 +1418,7 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
     expression is being evaluated.
 
 .. genex:: $<TARGET_PROPERTY:prop>
+  :target: TARGET_PROPERTY:prop
 
   Value of the property ``prop`` on the target for which the expression
   is being evaluated. Note that for generator expressions in

+ 29 - 5
Utilities/Sphinx/cmake.py

@@ -286,19 +286,20 @@ class CMakeTransform(Transform):
             domain.note_object(objtype, targetname, targetid, targetid)
 
 class CMakeObject(ObjectDescription):
+    def __init__(self, *args, **kwargs):
+        self.targetname = None
+        super().__init__(*args, **kwargs)
 
     def handle_signature(self, sig, signode):
         # called from sphinx.directives.ObjectDescription.run()
         signode += addnodes.desc_name(sig, sig)
-        if self.objtype == 'genex':
-            m = CMakeXRefRole._re_genex.match(sig)
-            if m:
-                sig = m.group(1)
         return sig
 
     def add_target_and_index(self, name, sig, signode):
         if self.objtype == 'command':
             targetname = name.lower()
+        elif self.targetname:
+            targetname = self.targetname
         else:
             targetname = name
         targetid = '%s:%s' % (self.objtype, targetname)
@@ -316,6 +317,29 @@ class CMakeObject(ObjectDescription):
         if make_index_entry:
             self.indexnode['entries'].append(make_index_entry(name, targetid))
 
+
+class CMakeGenexObject(CMakeObject):
+    option_spec = {
+        'target': directives.unchanged,
+    }
+
+    def handle_signature(self, sig, signode):
+        name = super().handle_signature(sig, signode)
+
+        m = CMakeXRefRole._re_genex.match(sig)
+        if m:
+            name = m.group(1)
+
+        return name
+
+    def run(self):
+        target = self.options.get('target')
+        if target is not None:
+            self.targetname = target
+
+        return super().run()
+
+
 class CMakeSignatureObject(CMakeObject):
     object_type = 'signature'
 
@@ -507,7 +531,7 @@ class CMakeDomain(Domain):
     directives = {
         'command':    CMakeObject,
         'envvar':     CMakeObject,
-        'genex':      CMakeObject,
+        'genex':      CMakeGenexObject,
         'signature':  CMakeSignatureObject,
         'variable':   CMakeObject,
         # Other `object_types` cannot be created except by the `CMakeTransform`