Parcourir la source

Merge topic 'doc-LINK_LIBRARY_genex'

d185f7c0a8 Help: Rework $<LINK_LIBRARY>, $<LINK_GROUP> and related docs

Acked-by: Kitware Robot <[email protected]>
Merge-request: !7413
Craig Scott il y a 3 ans
Parent
commit
51dd0d758d

+ 148 - 140
Help/manual/cmake-generator-expressions.7.rst

@@ -1370,229 +1370,237 @@ Output-Related Expressions
 
   .. versionadded:: 3.24
 
-  Manage how libraries are specified during the link step.
-  This expression may be used to specify how to link libraries in a target.
-  For example:
+  Specify a set of libraries to link to a target, along with a ``feature``
+  which provides details about *how* they should be linked.  For example:
 
   .. code-block:: cmake
 
     add_library(lib1 STATIC ...)
     add_library(lib2 ...)
-    target_link_libraries(lib2 PRIVATE "$<LINK_LIBRARY:load_archive,lib1>")
-
-  This specify to use the ``lib1`` target with feature ``load_archive`` for
-  linking target ``lib2``. The feature must have be defined by
-  :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` variable or, if
-  :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` is false,
-  by :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variable.
-
-  .. note::
-
-    The evaluation of this generator expression will use, for the following
-    variables, the values defined at the level of the creation of the target:
-
-    * :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
-    * :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>`
-    * :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
-    * :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>`
-
-  This expression can only be used to specify link libraries (i.e. part of
-  :command:`link_libraries` or :command:`target_link_libraries` commands and
-  :prop_tgt:`LINK_LIBRARIES` or :prop_tgt:`INTERFACE_LINK_LIBRARIES` target
-  properties).
+    target_link_libraries(lib2 PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,lib1>")
 
-  .. note::
-
-    If this expression appears in the :prop_tgt:`INTERFACE_LINK_LIBRARIES`
-    property of a target, it will be included in the imported target generated
-    by :command:`install(EXPORT)` command. It is the responsibility of the
-    environment consuming this import to define the link feature used by this
-    expression.
+  This specifies that ``lib2`` should link to ``lib1`` and use the
+  ``WHOLE_ARCHIVE`` feature when doing so.
 
-  The ``library-list`` argument can hold CMake targets or external libraries.
-  Any CMake target of type :ref:`OBJECT <Object Libraries>` or
-  :ref:`INTERFACE <Interface Libraries>` will be ignored by this expression and
-  will be handled in the standard way.
+  Feature names are case-sensitive and may only contain letters, numbers and
+  underscores.  Feature names defined in all uppercase are reserved for CMake's
+  own built-in features.  The pre-defined built-in library features are:
 
-  Each target or external library involved in the link step must have only one
-  kind of feature (the absence of feature is also incompatible with any
-  feature). For example:
-
-  .. code-block:: cmake
-
-    add_library(lib1 ...)
+  .. include:: ../variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt
 
-    add_library(lib2 ...)
-    target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature1,lib1>")
+  Built-in and custom library features are defined in terms of the following
+  variables:
+
+  * :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
+  * :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>`
+  * :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
+  * :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>`
+
+  The value used for each of these variables is the value as set at the end of
+  the directory scope in which the target was created.  The usage is as follows:
+
+  1. If the language-specific
+     :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` variable
+     is true, the ``feature`` must be defined by the corresponding
+     :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` variable.
+  2. If no language-specific ``feature`` is supported, then the
+     :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` variable must be
+     true and the ``feature`` must be defined by the corresponding
+     :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variable.
+
+  The following limitations should be noted:
+
+  * The ``library-list`` can specify CMake targets or libraries.
+    Any CMake target of type :ref:`OBJECT <Object Libraries>`
+    or :ref:`INTERFACE <Interface Libraries>` will ignore the feature aspect
+    of the expression and instead be linked in the standard way.
+
+  * The ``$<LINK_LIBRARY:...>`` generator expression can only be used to
+    specify link libraries.  In practice, this means it can appear in the
+    :prop_tgt:`LINK_LIBRARIES` and :prop_tgt:`INTERFACE_LINK_LIBRARIES`
+    target properties, and be specified in :command:`target_link_libraries`
+    and :command:`link_libraries` commands.
+
+  * If a ``$<LINK_LIBRARY:...>`` generator expression appears in the
+    :prop_tgt:`INTERFACE_LINK_LIBRARIES` property of a target, it will be
+    included in the imported target generated by a :command:`install(EXPORT)`
+    command.  It is the responsibility of the environment consuming this
+    import to define the link feature used by this expression.
+
+  * Each target or library involved in the link step must have at most only
+    one kind of library feature.  The absence of a feature is also incompatible
+    with all other features.  For example:
 
-    add_library(lib3 ...)
-    target_link_libraries(lib3 PRIVATE lib1 lib2)
-    # an error will be raised here because lib1 has two different features
+    .. code-block:: cmake
 
-  To resolve such incompatibilities, the :prop_tgt:`LINK_LIBRARY_OVERRIDE`
-  and  :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties can be
-  used.
+      add_library(lib1 ...)
+      add_library(lib2 ...)
+      add_library(lib3 ...)
 
-  .. note::
+      # lib1 will be associated with feature1
+      target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature1,lib1>")
 
-    This expression does not guarantee that the list of specified libraries
-    will be kept grouped. So, to manage constructs like ``start-group`` and
-    ``end-group``, as supported by ``GNU ld``, the :genex:`LINK_GROUP`
-    generator expression can be used.
+      # lib1 is being linked with no feature here. This conflicts with the
+      # use of feature1 in the line above and would result in an error.
+      target_link_libraries(lib3 PRIVATE lib1 lib2)
 
-  CMake pre-defines some features of general interest:
+    Where it isn't possible to use the same feature throughout a build for a
+    given target or library, the :prop_tgt:`LINK_LIBRARY_OVERRIDE` and
+    :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties can be
+    used to resolve such incompatibilities.
 
-  .. include:: ../variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt
+  * The ``$<LINK_LIBRARY:...>`` generator expression does not guarantee
+    that the list of specified targets and libraries will be kept grouped
+    together.  To manage constructs like ``--start-group`` and ``--end-group``,
+    as supported by the GNU ``ld`` linker, use the :genex:`LINK_GROUP`
+    generator expression instead.
 
 .. genex:: $<LINK_GROUP:feature,library-list>
 
   .. versionadded:: 3.24
 
-  Manage the grouping of libraries during the link step.
-  This expression may be used to specify how to keep groups of libraries during
-  the link of a target.
-  For example:
+  Specify a group of libraries to link to a target, along with a ``feature``
+  which defines how that group should be linked.  For example:
 
   .. code-block:: cmake
 
     add_library(lib1 STATIC ...)
     add_library(lib2 ...)
-    target_link_libraries(lib2 PRIVATE "$<LINK_GROUP:cross_refs,lib1,external>")
-
-  This specify to use the ``lib1`` target and ``external`` library  with the
-  group feature ``cross_refs`` for linking target ``lib2``. The feature must
-  have be defined by :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>`
-  variable or, if :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
-  is false, by :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>` variable.
+    target_link_libraries(lib2 PRIVATE "$<LINK_GROUP:RESCAN,lib1,external>")
 
-  .. note::
+  This specifies that ``lib2`` should link to ``lib1`` and ``external``, and
+  that both of those two libraries should be included on the linker command
+  line according to the definition of the ``RESCAN`` feature.
 
-    The evaluation of this generator expression will use, for the following
-    variables, the values defined at the level of the creation of the target:
+  Feature names are case-sensitive and may only contain letters, numbers and
+  underscores.  Feature names defined in all uppercase are reserved for CMake's
+  own built-in features.  Currently, there is only one pre-defined built-in
+  group feature:
 
-    * :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
-    * :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>`
-    * :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
-    * :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>`
+  .. include:: ../variable/LINK_GROUP_PREDEFINED_FEATURES.txt
 
-  This expression can only be used to specify link libraries (i.e. part of
-  :command:`link_libraries` or :command:`target_link_libraries` commands and
-  :prop_tgt:`LINK_LIBRARIES` or :prop_tgt:`INTERFACE_LINK_LIBRARIES` target
-  properties).
+  Built-in and custom group features are defined in terms of the following
+  variables:
 
-  .. note::
+  * :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
+  * :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>`
+  * :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
+  * :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>`
 
-    If this expression appears in the :prop_tgt:`INTERFACE_LINK_LIBRARIES`
-    property of a target, it will be included in the imported target generated
-    by :command:`install(EXPORT)` command. It is the responsibility of the
-    environment consuming this import to define the link feature used by this
-    expression.
+  The value used for each of these variables is the value as set at the end of
+  the directory scope in which the target was created.  The usage is as follows:
 
-  The ``library-list`` argument can hold CMake targets or external libraries.
-  Any CMake target of type :ref:`OBJECT <Object Libraries>` or
-  :ref:`INTERFACE <Interface Libraries>` will be ignored by this expression and
-  will be handled in the standard way.
+  1. If the language-specific
+     :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED` variable
+     is true, the ``feature`` must be defined by the corresponding
+     :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>` variable.
+  2. If no language-specific ``feature`` is supported, then the
+     :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED` variable must be
+     true and the ``feature`` must be defined by the corresponding
+     :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>` variable.
 
-  .. note::
+  The ``LINK_GROUP`` generator expression is compatible with the
+  :genex:`LINK_LIBRARY` generator expression. The libraries involved in a
+  group can be specified using the :genex:`LINK_LIBRARY` generator expression.
 
-    This expression is compatible with the :genex:`LINK_LIBRARY` generator
-    expression. The libraries involved in a group can be specified using the
-    :genex:`LINK_LIBRARY` generator expression.
-
-  Each target or external library involved in the link step can be part of
-  different groups as far as these groups use the same feature, so mixing
-  different group features for the same target or library is forbidden. The
-  different groups will be part of the link step.
+  Each target or external library involved in the link step is allowed to be
+  part of multiple groups, but only if all the groups involved specify the
+  same ``feature``.  Such groups will not be merged on the linker command line,
+  the individual groups will still be preserved.  Mixing different group
+  features for the same target or library is forbidden.
 
   .. code-block:: cmake
 
     add_library(lib1 ...)
     add_library(lib2 ...)
-
     add_library(lib3 ...)
-    target_link_libraries(lib3 PUBLIC "$<LINK_GROUP:feature1,lib1,lib2>")
-
     add_library(lib4 ...)
+    add_library(lib5 ...)
+
+    target_link_libraries(lib3 PUBLIC  "$<LINK_GROUP:feature1,lib1,lib2>")
     target_link_libraries(lib4 PRIVATE "$<LINK_GROUP:feature1,lib1,lib3>")
-    # lib4 will be linked with the groups {lib1,lib2} and {lib1,lib3}
+    # lib4 will be linked with the groups {lib1,lib2} and {lib1,lib3}.
+    # Both groups specify the same feature, so this is fine.
 
-    add_library(lib5 ...)
     target_link_libraries(lib5 PRIVATE "$<LINK_GROUP:feature2,lib1,lib3>")
-    # an error will be raised here because lib1 is part of two groups with
-    # different features
+    # An error will be raised here because both lib1 and lib3 are part of two
+    # groups with different features.
 
   When a target or an external library is involved in the link step as part of
-  a group and also as standalone, any occurrence of the standalone link item
-  will be replaced by the group or groups it belong to.
+  a group and also as not part of any group, any occurrence of the non-group
+  link item will be replaced by the groups it belongs to.
 
   .. code-block:: cmake
 
     add_library(lib1 ...)
     add_library(lib2 ...)
-
     add_library(lib3 ...)
+    add_library(lib4 ...)
+
     target_link_libraries(lib3 PUBLIC lib1)
 
-    add_library(lib4 ...)
     target_link_libraries(lib4 PRIVATE lib3 "$<LINK_GROUP:feature1,lib1,lib2>")
     # lib4 will only be linked with lib3 and the group {lib1,lib2}
 
-  This example will be "re-written" by CMake in the following form:
+  Because ``lib1`` is part of the group defined for ``lib4``, that group then
+  gets applied back to the use of ``lib1`` for ``lib3``.  The end result will
+  be as though the linking relationship for ``lib3`` had been specified as:
 
   .. code-block:: cmake
 
-    add_library(lib1 ...)
-    add_library(lib2 ...)
-
-    add_library(lib3 ...)
     target_link_libraries(lib3 PUBLIC "$<LINK_GROUP:feature1,lib1,lib2>")
 
-    add_library(lib4 ...)
-    target_link_libraries(lib4 PRIVATE lib3 "$<LINK_GROUP:feature1,lib1,lib2>")
-    # lib4 will only be linked with lib3 and the group {lib1,lib2}
-
-  Be aware that the precedence of the group over the standalone link item can
-  result in some circular dependency between groups, which will raise an
-  error because circular dependencies are not allowed for groups.
+  Be aware that the precedence of the group over the non-group link item can
+  result in circular dependencies between groups.  If this occurs, a fatal
+  error is raised because circular dependencies are not allowed for groups.
 
   .. code-block:: cmake
 
     add_library(lib1A ...)
     add_library(lib1B ...)
-
     add_library(lib2A ...)
     add_library(lib2B ...)
+    add_library(lib3 ...)
 
+    # Non-group linking relationships, these are non-circular so far
     target_link_libraries(lib1A PUBLIC lib2A)
     target_link_libraries(lib2B PUBLIC lib1B)
 
-    add_library(lib ...)
-    target_link_libraries(lib3 PRIVATE "$<LINK_GROUP:feat,lib1A,lib1B>"
-                                       "$<LINK_GROUP:feat,lib2A,lib2B>")
+    # The addition of these groups creates circular dependencies
+    target_link_libraries(lib3 PRIVATE
+      "$<LINK_GROUP:feat,lib1A,lib1B>"
+      "$<LINK_GROUP:feat,lib2A,lib2B>"
+    )
 
-  This example will be "re-written" by CMake in the following form:
+  Because of the groups defined for ``lib3``, the linking relationships for
+  ``lib1A`` and ``lib2B`` effectively get expanded to the equivalent of:
 
   .. code-block:: cmake
 
-    add_library(lib1A ...)
-    add_library(lib1B ...)
-
-    add_library(lib2A ...)
-    add_library(lib2B ...)
-
     target_link_libraries(lib1A PUBLIC "$<LINK_GROUP:feat,lib2A,lib2B>")
     target_link_libraries(lib2B PUBLIC "$<LINK_GROUP:feat,lib1A,lib1B>")
 
-    add_library(lib ...)
-    target_link_libraries(lib3 PRIVATE "$<LINK_GROUP:feat,lib1A,lib1B>"
-                                       "$<LINK_GROUP:feat,lib2A,lib2B>")
+  This creates a circular dependency between groups:
+  ``lib1A --> lib2B --> lib1A``.
 
-  So, we have a circular dependency between groups ``{lib1A,lib1B}`` and
-  ``{lib2A,lib2B}``.
+  The following limitations should also be noted:
 
-  CMake pre-defines some features of general interest:
+  * The ``library-list`` can specify CMake targets or libraries.
+    Any CMake target of type :ref:`OBJECT <Object Libraries>`
+    or :ref:`INTERFACE <Interface Libraries>` will ignore the feature aspect
+    of the expression and instead be linked in the standard way.
 
-  .. include:: ../variable/LINK_GROUP_PREDEFINED_FEATURES.txt
+  * The ``$<LINK_GROUP:...>`` generator expression can only be used to
+    specify link libraries.  In practice, this means it can appear in the
+    :prop_tgt:`LINK_LIBRARIES` and :prop_tgt:`INTERFACE_LINK_LIBRARIES`
+    target properties, and be specified in :command:`target_link_libraries`
+    and :command:`link_libraries` commands.
+
+  * If a ``$<LINK_GROUP:...>`` generator expression appears in the
+    :prop_tgt:`INTERFACE_LINK_LIBRARIES` property of a target, it will be
+    included in the imported target generated by a :command:`install(EXPORT)`
+    command.  It is the responsibility of the environment consuming this
+    import to define the link feature used by this expression.
 
 .. genex:: $<INSTALL_INTERFACE:...>
 

+ 40 - 29
Help/prop_tgt/LINK_LIBRARY_OVERRIDE.rst

@@ -3,52 +3,63 @@ LINK_LIBRARY_OVERRIDE
 
 .. versionadded:: 3.24
 
-To resolve incompatible features introduced by :genex:`LINK_LIBRARY` generator
-expression, this property offers the possibility to override, per ``link-item``
-(``CMake`` target or external library) involved in the link step, any defined
-features with a new one.
+Override the library features associated with libraries from
+:genex:`LINK_LIBRARY` generator expressions.  This can be used to resolve
+incompatible library features that result from specifying different features
+for the same library in different :genex:`LINK_LIBRARY` generator expressions.
 
-This property takes a :ref:`;-list <CMake Language Lists>` of override
-declarations which have the following format:
-
-::
+This property supports overriding multiple libraries and features. It expects
+a :ref:`semicolon-separated list <CMake Language Lists>`, where each list item
+has the following form::
 
   feature[,link-item]*
 
-For the list of ``link-item`` (``CMake`` target or external library) specified,
-the feature ``feature`` will be used in place of any declared feature. For
-example:
+For each comma-separated ``link-item``, any existing library feature associated
+with it will be ignored for the target this property is set on.  The item
+will instead be associated with the specified ``feature``.  Each ``link-item``
+can be anything that would be accepted as part of a ``library-list`` in a
+:genex:`LINK_LIBRARY` generator expression.
 
 .. code-block:: cmake
 
   add_library(lib1 ...)
-  target_link_libraries(lib1 PUBLIC "$<LINK_LIBRARY:feature1,external>")
-
   add_library(lib2 ...)
-  target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature2,lib1>")
-
   add_library(lib3 ...)
+
+  target_link_libraries(lib1 PUBLIC "$<LINK_LIBRARY:feature1,external>")
+  target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature2,lib1>")
   target_link_libraries(lib3 PRIVATE lib1 lib2)
-  # Here, lib1 has two different features which prevents to link lib3
-  # So, define LINK_LIBRARY_OVERRIDE property to ensure correct link
+
+  # lib1 is associated with both feature2 and no feature. Without any override,
+  # this would result in a fatal error at generation time for lib3.
+  # Define an override to resolve the incompatible feature associations.
   set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE "feature2,lib1,external")
-  # The lib1 and external will be used with FEATURE2 to link lib3
 
-It is also possible to override any feature with the pre-defined feature
-``DEFAULT`` to get the standard behavior (i.e. no feature):
+  # lib1 and external will now be associated with feature2 instead when linking lib3
+
+It is also possible to override any feature with the pre-defined ``DEFAULT``
+library feature.  This effectively discards any feature for that link item,
+for that target only (``lib3`` in this example):
 
 .. code-block:: cmake
 
-  set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE "DEFAULT,lib1"
-                                                          "feature2,external")
-  # The lib1 will be used without any feature and external will use feature2 to link lib3
+  # When linking lib3, discard any library feature for lib1, and use feature2 for external
+  set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE
+    "DEFAULT,lib1"
+    "feature2,external"
+  )
+
+The above example also demonstrates how to specify different feature overrides
+for different link items.  See the :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>`
+target property for an alternative way of overriding library features for
+individual libraries, which may be simpler in some cases.  If both properties
+are defined and specify an override for the same link item,
+:prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` takes precedence over
+``LINK_LIBRARY_OVERRIDE``.
 
 Contents of ``LINK_LIBRARY_OVERRIDE`` may use
 :manual:`generator expressions <cmake-generator-expressions(7)>`.
 
-See also :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target property for
-a per linked target oriented approach to override features.
-
-For more information about features, see
-:variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>`
-and :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variables.
+For more information about library features, see the
+:variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` and
+:variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variables.

+ 28 - 22
Help/prop_tgt/LINK_LIBRARY_OVERRIDE_LIBRARY.rst

@@ -3,43 +3,49 @@ LINK_LIBRARY_OVERRIDE_<LIBRARY>
 
 .. versionadded:: 3.24
 
-To resolve incompatible features introduced by :genex:`LINK_LIBRARY` generator
-expression, this property offers the possibility to override, for a
-``link-item`` (``CMake`` target or external library) involved in the link step,
-any defined features with a new one.
+Override the library feature associated with ``<LIBRARY>`` from
+:genex:`LINK_LIBRARY` generator expressions.  This can be used to resolve
+incompatible library features that result from specifying different features
+for ``<LIBRARY>`` in different :genex:`LINK_LIBRARY` generator expressions.
 
-This property takes a ``feature`` name which will be applied to the
-``link-item`` specified by ``<LIBRARY>`` suffix property. For example:
+When set on a target, this property holds a single library feature name, which
+will be applied to ``<LIBRARY>`` when linking that target.
 
 .. code-block:: cmake
 
   add_library(lib1 ...)
-  target_link_libraries(lib1 PUBLIC "$<LINK_LIBRARY:feature1,external>")
-
   add_library(lib2 ...)
-  target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature2,lib1>")
-
   add_library(lib3 ...)
+
+  target_link_libraries(lib1 PUBLIC "$<LINK_LIBRARY:feature1,external>")
+  target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature2,lib1>")
   target_link_libraries(lib3 PRIVATE lib1 lib2)
-  # Here, lib1 has two different features which prevents to link lib3
-  # So, define LINK_LIBRARY_OVERRIDE_lib1 property to ensure correct link
+
+  # lib1 is associated with both feature2 and no feature. Without any override,
+  # this would result in a fatal error at generation time for lib3.
+  # Define an override to resolve the incompatible feature associations.
   set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE_lib1 feature2)
-  # The lib1 will be used with feature2 to link lib3
 
-It is also possible to override any feature with the pre-defined feature
-``DEFAULT`` to get the standard behavior (i.e. no feature):
+  # lib1 will now be associated with feature2 instead when linking lib3
+
+It is also possible to override any feature with the pre-defined ``DEFAULT``
+library feature.  This effectively discards any feature for that link item,
+for that target only (``lib3`` in this example):
 
 .. code-block:: cmake
 
+  # When linking lib3, discard any library feature for lib1
   set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE_lib1 DEFAULT)
-  # The lib1 will be used without any feature to link lib3
+
+See the :prop_tgt:`LINK_LIBRARY_OVERRIDE` target property for an alternative
+way of overriding library features for multiple libraries at once.  If both
+properties are defined and specify an override for the same link item,
+``LINK_LIBRARY_OVERRIDE_<LIBRARY>`` takes precedence over
+:prop_tgt:`LINK_LIBRARY_OVERRIDE`.
 
 Contents of ``LINK_LIBRARY_OVERRIDE_<LIBRARY>`` may use
 :manual:`generator expressions <cmake-generator-expressions(7)>`.
 
-This property takes precedence over :prop_tgt:`LINK_LIBRARY_OVERRIDE`
-target property.
-
-For more information about features, see
-:variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>`
-and :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variables.
+For more information about library features, see the
+:variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` and
+:variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variables.

+ 8 - 19
Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE.rst

@@ -3,25 +3,14 @@ CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>
 
 .. versionadded:: 3.24
 
-This variable defines, for the specified ``<FEATURE>`` and the linker language
-``<LANG>``, the expression expected by the linker when libraries are specified
-using :genex:`LINK_GROUP` generator expression.
+This variable defines how to link a group of libraries for the specified
+``<FEATURE>`` when a :genex:`LINK_GROUP` generator expression is used and
+the link language for the target is ``<LANG>``.
+For this variable to have any effect, the associated
+:variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED` variable
+must be set to true.
 
-.. note::
-
-  * Feature names can contain Latin letters, digits and undercores.
-  * Feature names defined in all uppercase are reserved to CMake.
-
-See also the associated variable
-:variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED` and
-:variable:`CMAKE_LINK_GROUP_USING_<FEATURE>` variable for the definition of
-features independent from the link language.
+The :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>` variable should be defined
+instead for features that are independent of the link language.
 
 .. include:: CMAKE_LINK_GROUP_USING_FEATURE.txt
-
-Predefined Features
-^^^^^^^^^^^^^^^^^^^
-
-CMake pre-defines some features of general interest:
-
-.. include:: LINK_GROUP_PREDEFINED_FEATURES.txt

+ 9 - 8
Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED.rst

@@ -3,11 +3,12 @@ CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED
 
 .. versionadded:: 3.24
 
-Set to ``TRUE`` if the ``<FEATURE>``, as defined by variable
-:variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>`, is supported for the
-linker language ``<LANG>``.
-
-.. note::
-
-  This variable is evaluated before the more generic variable
-  :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED`.
+This variable specifies whether the ``<FEATURE>`` is supported for the link
+language ``<LANG>``.  If this variable is true, then the ``<FEATURE>`` must
+be defined by :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>`, and the
+more generic :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED` and
+:variable:`CMAKE_LINK_GROUP_USING_<FEATURE>` variables are not used.
+
+If ``CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED`` is false or is not
+set, then the :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED` variable
+will determine whether ``<FEATURE>`` is deemed to be supported.

+ 8 - 19
Help/variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE.rst

@@ -3,25 +3,14 @@ CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>
 
 .. versionadded:: 3.24
 
-This variable defines, for the specified ``<FEATURE>`` and the linker language
-``<LANG>``, the expression expected by the linker when libraries are specified
-using :genex:`LINK_LIBRARY` generator expression.
+This variable defines how to link a library or framework for the specified
+``<FEATURE>`` when a :genex:`LINK_LIBRARY` generator expression is used and
+the link language for the target is ``<LANG>``.
+For this variable to have any effect, the associated
+:variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` variable
+must be set to true.
 
-.. note::
-
-  * Feature names can contain Latin letters, digits and undercores.
-  * Feature names defined in all uppercase are reserved to CMake.
-
-See also the associated variable
-:variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` and
-:variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variable for the definition of
-features independent from the link language.
+The :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variable should be defined
+instead for features that are independent of the link language.
 
 .. include:: CMAKE_LINK_LIBRARY_USING_FEATURE.txt
-
-Predefined Features
-^^^^^^^^^^^^^^^^^^^
-
-CMake pre-defines some features of general interest:
-
-.. include:: LINK_LIBRARY_PREDEFINED_FEATURES.txt

+ 12 - 23
Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.rst

@@ -3,31 +3,20 @@ CMAKE_LINK_GROUP_USING_<FEATURE>
 
 .. versionadded:: 3.24
 
-This variable defines, for the specified ``<FEATURE>``, the expression expected
-by the linker when libraries are specified using :genex:`LINK_GROUP` generator
-expression.
+This variable defines how to link a group of libraries for the specified
+``<FEATURE>`` when a :genex:`LINK_GROUP` generator expression is used.
+Both of the following conditions must be met for this variable to have any
+effect:
 
-.. note::
+* The associated :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
+  variable must be set to true.
 
-  * Feature names can contain Latin letters, digits and undercores.
-  * Feature names defined in all uppercase are reserved to CMake.
+* There is no language-specific definition for the same ``<FEATURE>``.
+  This means :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
+  cannot be true for the link language used by the target for which the
+  :genex:`LINK_GROUP` generator expression is evaluated.
 
-See also the associated variable
-:variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED` and
-:variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>` variable for the definition
-of features dependent from the link language.
-
-This variable will be used by :genex:`LINK_GROUP` generator expression if,
-for the linker language, the variable
-:variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED` is not defined
-and the variable :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED` is
-``TRUE``..
+The :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>` variable should be
+defined instead for features that are dependent on the link language.
 
 .. include:: CMAKE_LINK_GROUP_USING_FEATURE.txt
-
-Predefined Features
-^^^^^^^^^^^^^^^^^^^
-
-CMake pre-defines some features of general interest:
-
-.. include:: LINK_GROUP_PREDEFINED_FEATURES.txt

+ 45 - 21
Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.txt

@@ -1,17 +1,24 @@
+Feature names are case-sensitive and may only contain letters, numbers
+and underscores.  Feature names defined in all uppercase are reserved for
+CMake's own built-in features (see `Predefined Features`_ further below).
 
-It must contain two elements.
+
+Feature Definitions
+^^^^^^^^^^^^^^^^^^^
+
+A group feature definition is a list that contains exactly two elements:
 
 ::
 
   <PREFIX> <SUFFIX>
 
-``<PREFIX>`` and ``<SUFFIX>`` will be used to encapsulate the list of
-libraries.
+On the linker command line, ``<PREFIX>`` will precede the list of libraries
+in the group and ``<SUFFIX>`` will follow after.
 
-For the elements of this variable, the ``LINKER:`` prefix can be used:
+For the elements of this variable, the ``LINKER:`` prefix can be used.
 
-  .. include:: ../command/LINK_OPTIONS_LINKER.txt
-    :start-line: 3
+.. include:: ../command/LINK_OPTIONS_LINKER.txt
+  :start-line: 3
 
 Examples
 ^^^^^^^^
@@ -19,36 +26,53 @@ Examples
 Solving cross-references between two static libraries
 """""""""""""""""""""""""""""""""""""""""""""""""""""
 
-A common need is the capability to search repeatedly in a group of static
-libraries until no new undefined references are created. This capability is
-offered by different environments but with a specific syntax:
+A project may define two or more static libraries which have circular
+dependencies between them.  In order for the linker to resolve all symbols
+at link time, it may need to search repeatedly among the libraries until no
+new undefined references are created.  Different linkers use different syntax
+for achieving this.  The following example shows how this may be implemented
+for some linkers.  Note that this is for illustration purposes only.
+Projects should use the built-in ``RESCAN`` group feature instead
+(see `Predefined Features`_), which provides a more complete and more robust
+implementation of this functionality.
 
 .. code-block:: cmake
 
   set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED TRUE)
-  if(CMAKE_C_COMPILER_ID STREQUAL "GNU"
-     AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
-    set(CMAKE_C_LINK_GROUP_USING_cross_refs "LINKER:--start-group"
-                                            "LINKER:--end-group")
-  elseif(CMAKE_C_COMPILER_ID STREQUAL "SunPro"
-         AND CMAKE_SYSTEM_NAME STREQUAL "SunOS")
-    set(CMAKE_C_LINK_GROUP_USING_cross_refs "LINKER:-z,rescan-start"
-                                            "LINKER:-z,rescan-end")
+  if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    set(CMAKE_C_LINK_GROUP_USING_cross_refs
+      "LINKER:--start-group"
+      "LINKER:--end-group"
+    )
+  elseif(CMAKE_C_COMPILER_ID STREQUAL "SunPro" AND CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+    set(CMAKE_C_LINK_GROUP_USING_cross_refs
+      "LINKER:-z,rescan-start"
+      "LINKER:-z,rescan-end"
+    )
   else()
     # feature not yet supported for the other environments
     set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED FALSE)
   endif()
 
   add_library(lib1 STATIC ...)
+  add_library(lib2 SHARED ...)
 
-  add_library(lib3 SHARED ...)
   if(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED)
-    target_link_libraries(lib3 PRIVATE "$<LINK_GROUP:cross_refs,lib1,external>")
+    target_link_libraries(lib2 PRIVATE "$<LINK_GROUP:cross_refs,lib1,external>")
   else()
-    target_link_libraries(lib3 PRIVATE lib1 external)
+    target_link_libraries(lib2 PRIVATE lib1 external)
   endif()
 
-CMake will generate the following link expressions:
+CMake will generate the following linker command line fragments when linking
+``lib2``:
 
 * ``GNU``: ``-Wl,--start-group /path/to/lib1.a -lexternal -Wl,--end-group``
 * ``SunPro``: ``-Wl,-z,rescan-start /path/to/lib1.a -lexternal -Wl,-z,rescan-end``
+
+
+Predefined Features
+^^^^^^^^^^^^^^^^^^^
+
+The following built-in group features are pre-defined by CMake:
+
+.. include:: LINK_GROUP_PREDEFINED_FEATURES.txt

+ 6 - 7
Help/variable/CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED.rst

@@ -3,11 +3,10 @@ CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED
 
 .. versionadded:: 3.24
 
-Set to ``TRUE`` if the ``<FEATURE>``, as defined by variable
-:variable:`CMAKE_LINK_GROUP_USING_<FEATURE>`, is supported regardless the
-linker language.
+This variable specifies whether the ``<FEATURE>`` is supported regardless of
+the link language.  If this variable is true, then the ``<FEATURE>`` must
+be defined by :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>`.
 
-.. note::
-
-  This variable is evaluated if, and only if, the variable
-  :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED` is not defined.
+Note that this variable has no effect if
+:variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED` is true for
+the link language of the target.

+ 10 - 24
Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.rst

@@ -3,31 +3,17 @@ CMAKE_LINK_LIBRARY_USING_<FEATURE>
 
 .. versionadded:: 3.24
 
-This variable defines, for the specified ``FEATURE``, the expression expected
-by the linker, regardless the linker language, when libraries are specified
-using :genex:`LINK_LIBRARY` generator expression.
+This variable defines how to link a library or framework for the specified
+``<FEATURE>`` when a :genex:`LINK_LIBRARY` generator expression is used.
+Both of the following conditions must be met for this variable to have any
+effect:
 
-.. note::
+* The associated :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
+  variable must be set to true.
 
-  * Feature names can contain Latin letters, digits and undercores.
-  * Feature names defined in all uppercase are reserved to CMake.
-
-See also the associated variable
-:variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` and
-:variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` variable for the
-definition of features dependent from the link language.
-
-This variable will be used by :genex:`LINK_LIBRARY` generator expression if,
-for the linker language, the variable
-:variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` is not defined
-and the variable :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` is
-``TRUE``.
+* There is no language-specific definition for the same ``<FEATURE>``.
+  This means :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
+  cannot be true for the link language used by the target for which the
+  :genex:`LINK_LIBRARY` generator expression is evaluated.
 
 .. include:: CMAKE_LINK_LIBRARY_USING_FEATURE.txt
-
-Predefined Features
-^^^^^^^^^^^^^^^^^^^
-
-CMake pre-defines some features of general interest:
-
-.. include:: LINK_LIBRARY_PREDEFINED_FEATURES.txt

+ 89 - 51
Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.txt

@@ -1,39 +1,58 @@
+Feature names are case-sensitive and may only contain letters, numbers
+and underscores.  Feature names defined in all uppercase are reserved for
+CMake's own built-in features (see `Predefined Features`_ further below).
 
-It can contain one or three elements.
 
-::
-
-  [<PREFIX>] <LIBRARY_EXPRESSION> [<SUFFIX>]
+Feature Definitions
+^^^^^^^^^^^^^^^^^^^
 
-When ``<PREFIX>`` and/or ``<SUFFIX>`` are specified, they encapsulate the list
-of libraries.
+A library feature definition is a list that contains one or three elements:
 
-.. note::
+::
 
-  Even if ``<PREFIX>`` and ``<SUFFIX>`` are specified, there is not guarantee
-  that the list of specified libraries, as part of :genex:`LINK_LIBRARY`
-  generator expression, will be kept grouped. So, constructs like
-  ``start-group`` and ``end-group``, as supported by ``GNU ld``, cannot be
-  used.
+  [<PREFIX>] <LIBRARY_EXPRESSION> [<SUFFIX>]
 
-``<LIBRARY_EXPRESSION>`` is used to specify the decoration for each
-library. For that purpose, the patterns ``<LIBRARY>``, ``<LINK_ITEM>``, and
-``<LIB_ITEM>`` are available:
+When ``<PREFIX>`` and ``<SUFFIX>`` are specified, they precede and follow
+respectively the whole list of libraries specified in the
+:genex:`LINK_LIBRARY` expression, not each library item individually.
+There is no guarantee that the list of specified libraries will be kept
+grouped together though, so the ``<PREFIX>`` and ``<SUFFIX>`` may appear
+more than once if the library list is reorganized by CMake to satisfy other
+constraints.  This means constructs like ``--start-group`` and ``--end-group``,
+as supported by the GNU ``ld`` linker, cannot be used in this way.  The
+:genex:`LINK_GROUP` generator expression should be used instead for such
+constructs.
+
+``<LIBRARY_EXPRESSION>`` is used to specify the pattern for constructing the
+corresponding fragment on the linker command line for each library.
+The following placeholders can be used in the expression:
+
+* ``<LIBRARY>`` is expanded to the full path to the library for CMake targets,
+  or to a platform-specific value based on the item otherwise (the same as
+  ``<LINK_ITEM>`` on Windows, or the library base name for other platforms).
+* ``<LINK_ITEM>`` is expanded to how the library would normally be linked on
+  the linker command line.
+* ``<LIB_ITEM>`` is expanded to the full path to the library for CMake targets,
+  or the item itself exactly as specified in the ``<LIBRARY_EXPRESSION>``
+  otherwise.
+
+In addition to the above, it is possible to have one pattern for paths
+(CMake targets and external libraries specified with file paths) and another
+for other items specified by name only.  The ``PATH{}`` and ``NAME{}`` wrappers
+can be used to provide the expansion for those two cases, respectively.
+When wrappers are used, both must be present.  For example:
 
-* ``<LIBRARY>`` is expanded to the library as computed by CMake.
-* ``<LINK_ITEM>`` is expanded to the same expression as if the library was
-  specified in the standard way.
-* ``<LIB_ITEM>`` is equivalent to ``<LIBRARY>`` for CMake targets and is
-  expanded to the item specified by the user for external libraries.
+.. code-block:: cmake
 
-Moreover, it is possible to have different decorations for paths (CMake targets
-and external libraries specified with absolute paths) and other items specified
-by name. For that purpose, ``PATH{}`` and ``NAME{}`` wrappers can be used.
+  set(CMAKE_LINK_LIBRARY_USING_weak_library
+      "PATH{-weak_library <LIBRARY>}NAME{LINKER:-weak-l<LIB_ITEM>}"
+  )
 
-For all three elements of this variable, the ``LINKER:`` prefix can be used:
+For all three elements of this variable (``<PREFIX>``, ``<LIBRARY_EXPRESSION>``,
+and ``<SUFFIX>``), the ``LINKER:`` prefix can be used.
 
-  .. include:: ../command/LINK_OPTIONS_LINKER.txt
-    :start-line: 3
+.. include:: ../command/LINK_OPTIONS_LINKER.txt
+  :start-line: 3
 
 Examples
 ^^^^^^^^
@@ -41,19 +60,24 @@ Examples
 Loading a whole static library
 """"""""""""""""""""""""""""""
 
-A common need is the capability to load a whole static library. This capability
-is offered by various environments but with a specific syntax:
+A common need is to prevent the linker from discarding any symbols from a
+static library.  Different linkers use different syntax for achieving this.
+The following example shows how this may be implemented for some linkers.
+Note that this is for illustration purposes only.  Projects should use the
+built-in ``WHOLE_ARCHIVE`` feature instead (see `Predefined Features`_), which
+provides a more complete and more robust implementation of this functionality.
 
 .. code-block:: cmake
 
   set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED TRUE)
   if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
     set(CMAKE_C_LINK_LIBRARY_USING_load_archive "-force_load <LIB_ITEM>")
-  elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU"
-         AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
-    set(CMAKE_C_LINK_LIBRARY_USING_load_archive "LINKER:--push-state,--whole-archive"
-                                                "<LINK_ITEM>"
-                                                "LINKER:--pop-state")
+  elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    set(CMAKE_C_LINK_LIBRARY_USING_load_archive
+      "LINKER:--push-state,--whole-archive"
+      "<LINK_ITEM>"
+      "LINKER:--pop-state"
+    )
   elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
     set(CMAKE_C_LINK_LIBRARY_USING_load_archive "/WHOLEARCHIVE:<LIBRARY>")
   else()
@@ -62,41 +86,45 @@ is offered by various environments but with a specific syntax:
   endif()
 
   add_library(lib1 STATIC ...)
-
   add_library(lib2 SHARED ...)
+
   if(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED)
+    # The -force_load Apple linker option requires a file name
+    set(external_lib
+      "$<IF:$<LINK_LANG_AND_ID:C,AppleClang>,libexternal.a,external>"
+    )
     target_link_libraries(lib2 PRIVATE
-      "$<LINK_LIBRARY:load_archive,lib1,$<IF:$<LINK_LANG_AND_ID:C,Clang>,libexternal.a,external>>")
+      "$<LINK_LIBRARY:load_archive,lib1,${external_lib}>"
+    )
   else()
     target_link_libraries(lib2 PRIVATE lib1 external)
   endif()
 
 CMake will generate the following link expressions:
 
-* ``Clang``: ``-force_load /path/to/lib1.a -force_load libexternal.a``
-* ``GNU``: ``-Wl,--whole-archive /path/to/lib1.a -lexternal -Wl,--no-whole-archive``
+* ``AppleClang``: ``-force_load /path/to/lib1.a -force_load libexternal.a``
+* ``GNU``: ``-Wl,--push-state,--whole-archive /path/to/lib1.a -lexternal -Wl,--pop-state``
 * ``MSVC``: ``/WHOLEARCHIVE:/path/to/lib1.lib /WHOLEARCHIVE:external.lib``
 
-CMake will ensure, when possible, that ``<PREFIX>`` and ``<SUFFIX>`` are
-not repeated for each library.
-
-In case of ``Clang``, the pattern ``<LIB_ITEM>`` is used because we need to
-specify the library as defined by the user, not the name computed by CMake
-(in that case ``external``).
-
 Linking a library as weak
 """""""""""""""""""""""""
 
-On MacOS, it is possible to link a library in weak mode (the library and all
-references are marked as weak imports), but different flags must be used for a
-library specified by path and by name. This constraint by be solved by using
-``PATH{}`` and ``NAME{}`` wrappers:
+On macOS, it is possible to link a library in weak mode (the library and all
+references are marked as weak imports).  Different flags must be used for a
+library specified by file path compared to one specified by name.
+This constraint can be solved using ``PATH{}`` and ``NAME{}`` wrappers.
+Again, the following example shows how this may be implemented for some
+linkers, but it is for illustration purposes only.  Projects should use the
+built-in ``WEAK_FRAMEWORK`` or ``WEAK_LIBRARY`` features instead (see
+`Predefined Features`_), which provide more complete and more robust
+implementations of this functionality.
 
 .. code-block:: cmake
 
   if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
     set(CMAKE_LINK_LIBRARY_USING_weak_library
-        "PATH{-weak_library <LIBRARY>}NAME{LINKER:-weak-l<LIB_ITEM>}")
+        "PATH{-weak_library <LIBRARY>}NAME{LINKER:-weak-l<LIB_ITEM>}"
+    )
     set(CMAKE_LINK_LIBRARY_USING_weak_library_SUPPORTED TRUE)
   endif()
 
@@ -108,5 +136,15 @@ library specified by path and by name. This constraint by be solved by using
     target_link_libraries(main PRIVATE lib external)
   endif()
 
-CMake will generate the following link expression:
-``-weak_library /path/to/lib -Xlinker -weak-lexternal``
+CMake will generate the following linker command line fragment when linking
+``main`` using the ``AppleClang`` toolchain:
+
+``-weak_library /path/to/lib -Xlinker -weak-lexternal``.
+
+
+Predefined Features
+^^^^^^^^^^^^^^^^^^^
+
+The following built-in library features are pre-defined by CMake:
+
+.. include:: LINK_LIBRARY_PREDEFINED_FEATURES.txt

+ 16 - 16
Help/variable/LINK_GROUP_PREDEFINED_FEATURES.txt

@@ -1,22 +1,22 @@
-**Circular references with static libraries**
-
-Some linkers are one-pass only so to handle circular references between
-static libraries, the following feature can be used:
-
 ``RESCAN``
-  The specified static libraries are searched repeatedly until no
-  new undefined references are created. Normally, an static library is searched
-  only once in the order that it is specified on the command line. If a symbol
-  in that library is needed to resolve an undefined symbol referred to by an
-  object in an library that appears later on the command line, the linker would
-  not be able to resolve that reference. By grouping the static libraries, they
-  all be searched repeatedly until all possible references are resolved (use
-  linker options ``--start-group`` and ``--end-group`` or, on ``SunOS``,
-  ``-z rescan-start`` and ``-z rescan-end``).
+  Some linkers are single-pass only.  For such linkers, circular references
+  between libraries typically result in unresolved symbols.  This feature
+  instructs the linker to search the specified static libraries repeatedly
+  until no new undefined references are created.
+
+  Normally, a static library is searched only once in the order that it is
+  specified on the command line.  If a symbol in that library is needed to
+  resolve an undefined symbol referred to by an object in a library that
+  appears later on the command line, the linker would not be able to resolve
+  that reference.  By grouping the static libraries with the ``RESCAN``
+  feature, they will all be searched repeatedly until all possible references
+  are resolved.  This will use linker options like ``--start-group`` and
+  ``--end-group``, or on SunOS, ``-z rescan-start`` and ``-z rescan-end``.
 
   Using this feature has a significant performance cost. It is best to use it
   only when there are unavoidable circular references between two or more
   static libraries.
 
-  This feature is available on ``Linux``, ``BSD``, and ``SunOS`` target
-  platforms as well as ``Windows`` when ``GNU`` toolchain is used.
+  This feature is available when using toolchains that target Linux, BSD, and
+  SunOS.  It can also be used when targeting Windows platforms if the GNU
+  toolchain is used.

+ 83 - 75
Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt

@@ -1,88 +1,96 @@
-**Features available in all environments**
-
 ``DEFAULT``
-  This feature enables default link expression. This is mainly
-  useful with :prop_tgt:`LINK_LIBRARY_OVERRIDE` and
+  This feature corresponds to standard linking, essentially equivalent to
+  using no feature at all.  It is typically only used with the
+  :prop_tgt:`LINK_LIBRARY_OVERRIDE` and
   :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties.
 
-**Features available for a subset of environments**
-
 ``WHOLE_ARCHIVE``
-  Force load of all members in a static library.
-
-  Target platforms supported: all ``Apple`` variants, ``Linux``, all ``BSD``
-  variants, ``SunOS``, ``Windows``, ``CYGWIN``, and ``MSYS``.
-
-  Platform-specific notes:
-
-  * On Apple platforms, the library must be specified as a CMake target name, a
-    library file name (such as ``libfoo.a``), or a library file path (such as
-    ``/path/to/libfoo.a``).  It cannot be specified as a plain library name
-    (such as ``foo``, where ``foo`` is not CMake target), due to a limitation
-    in the Apple linker.
-  * On Windows platforms, for ``MSVC`` or MSVC-like toolchains, the version
-    must be greater than ``1900``.
-
-**Features available in Apple environments**
-
-It is assumed that the linker used is the one provided by `XCode` or is
-compatible with it.
-
-Framework support
+  Force inclusion of all members of a static library.  This feature is only
+  supported for the following platforms, with limitations as noted:
+
+  * Linux.
+  * All BSD variants.
+  * SunOS.
+  * All Apple variants.  The library must be specified as a CMake target name,
+    a library file name (such as ``libfoo.a``), or a library file path (such as
+    ``/path/to/libfoo.a``).  Due to a limitation of the Apple linker, it
+    cannot be specified as a plain library name like ``foo``, where ``foo``
+    is not a CMake target.
+  * Windows.  When using a MSVC or MSVC-like toolchain, the MSVC version must
+    be greater than 1900.
+  * Cygwin.
+  * MSYS.
 
 ``FRAMEWORK``
-  This option tells the linker to search for the specified
-  framework (use linker option ``-framework``).
-``NEEDED_FRAMEWORK``
-  This is the same as the ``FRAMEWORK`` feature but means
-  to really link with the framework even if no symbols are used from it (use
-  linker option ``-needed_framework``).
-``REEXPORT_FRAMEWORK``
-  This is the same as the ``FRAMEWORK`` feature but
-  also specifies that all symbols in that framework should be available to
-  clients linking to the library being created (use linker option
-  ``-reexport_framework``).
-``WEAK_FRAMEWORK``
-  This is the same as the ``FRAMEWORK`` feature but forces
-  the framework and all references to it to be marked as weak imports (use
-  linker option ``-weak_framework``).
+  This option tells the linker to search for the specified framework using
+  the ``-framework`` linker option.  It can only be used on Apple platforms,
+  and only with a linker that understands the option used (i.e. the linker
+  provided with Xcode, or one compatible with it).
+
+  The framework can be specified as a CMake framework target, a bare framework
+  name, or a file path.  If a target is given, that target must have the
+  :prop_tgt:`FRAMEWORK` target property set to true.  For a file path, if it
+  contains a directory part, that directory will be added as a framework
+  search path.
+
+  .. code-block:: cmake
+
+    add_library(lib SHARED ...)
+    target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:FRAMEWORK,/path/to/my_framework>")
+
+    # The constructed linker command line will contain:
+    #   -F/path/to -framework my_framework
+
+  File paths must conform to one of the following patterns (``*`` is a
+  wildcard, and optional parts are shown as ``[...]``):
+
+     * ``[/path/to/]FwName[.framework]``
+     * ``[/path/to/]FwName.framework/FwName``
+     * ``[/path/to/]FwName.framework/Versions/*/FwName``
+
+  Note that CMake recognizes and automatically handles framework targets,
+  even without using the ``$<LINK_LIBRARY:FRAMEWORK,...>`` expression.
+  The generator expression can still be used with a CMake target if the
+  project wants to be explicit about it, but it is not required to do so.
+  The linker command line may have some differences between using the
+  generator expression or not, but the final result should be the same.
+  On the other hand, if a file path is given, CMake will recognize some paths
+  automatically, but not all cases.  The project may want to use
+  ``$<LINK_LIBRARY:FRAMEWORK,...>`` for file paths so that the expected
+  behavior is clear.
 
-Features for framework linking have a special handling in CMake: the
-framework can be specified as a CMake framework target or file path. In the
-first case, the target must have the :prop_tgt:`FRAMEWORK` target property set
-as ``TRUE`` to enable framework handling. In the later case, if the path
-includes a directory part, this one will be specified as framework search path
-at link step.
-
-.. code-block:: cmake
-
-  add_library(lib SHARED ...)
-  target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:NEEDED_FRAMEWORK,/path/to/my_framework>")
-
-  # at link step we will have:
-  # -F/path/to -needed_framework my_framework
-
-.. note::
-
-   The expected formats for the file path, with optional parts specified as
-   ``()?``, are:
+``NEEDED_FRAMEWORK``
+  This is similar to the ``FRAMEWORK`` feature, except it forces the linker
+  to link with the framework even if no symbols are used from it.  It uses
+  the ``-needed_framework`` option and has the same linker constraints as
+  ``FRAMEWORK``.
 
-   * (/path/to/)?FwName(.framework)?
-   * (/path/to/)?FwName.framework/FwName
-   * (/path/to/)?FwName.framework/Versions/\*/FwName
+``REEXPORT_FRAMEWORK``
+  This is similar to the ``FRAMEWORK`` feature, except it tells the linker
+  that the framework should be available to clients linking to the library
+  being created.  It uses the ``-reexport_framework`` option and has the
+  same linker constraints as ``FRAMEWORK``.
 
-Library support
+``WEAK_FRAMEWORK``
+  This is similar to the ``FRAMEWORK`` feature, except it forces the linker
+  to mark the framework and all references to it as weak imports.  It uses
+  the ``-weak_framework`` option and has the same linker constraints as
+  ``FRAMEWORK``.
 
 ``NEEDED_LIBRARY``
-  This is the same as specifying a link item (target or
-  library) but means to really link with the item even if no symbols are used
-  from it (use linker option ``-needed_library`` or ``-needed-l``).
+  This is similar to the ``NEEDED_FRAMEWORK`` feature, except it is for use
+  with non-framework targets or libraries (Apple platforms only).
+  It uses the ``-needed_library`` or ``-needed-l`` option as appropriate,
+  and has the same linker constraints as ``NEEDED_FRAMEWORK``.
+
 ``REEXPORT_LIBRARY``
-  This is the same as specifying a link item (target or
-  library) but also specifies that all symbols in that item should be available
-  to clients linking to the library being created (use linker option
-  ``-reexport_library`` or ``-reexport-l``).
+  This is similar to the ``REEXPORT_FRAMEWORK`` feature,  except it is for use
+  with non-framework targets or libraries (Apple platforms only).
+  It uses the ``-reexport_library`` or ``-reexport-l`` option as appropriate,
+  and has the same linker constraints as ``REEXPORT_FRAMEWORK``.
+
 ``WEAK_LIBRARY``
-  This is the same as specifying a link item (target or
-  library) but forces the item and all references to it to be marked as weak
-  imports (use linker option ``-weak_library`` or ``-weak-l``).
+  This is similar to the ``WEAK_FRAMEWORK`` feature, except it is for use
+  with non-framework targets or libraries (Apple platforms only).
+  It uses the ``-weak_library`` or ``-weak-l`` option as appropriate,
+  and has the same linker constraints as ``WEAK_FRAMEWORK``.