Bläddra i källkod

Merge topic 'doc-LINK_LIBRARY_genex' into release-3.24

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

Acked-by: Kitware Robot <[email protected]>
Merge-request: !7413
Craig Scott 3 år sedan
förälder
incheckning
2a336d8554

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

@@ -1370,229 +1370,237 @@ Output-Related Expressions
 
 
   .. versionadded:: 3.24
   .. 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
   .. code-block:: cmake
 
 
     add_library(lib1 STATIC ...)
     add_library(lib1 STATIC ...)
     add_library(lib2 ...)
     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>
 .. genex:: $<LINK_GROUP:feature,library-list>
 
 
   .. versionadded:: 3.24
   .. 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
   .. code-block:: cmake
 
 
     add_library(lib1 STATIC ...)
     add_library(lib1 STATIC ...)
     add_library(lib2 ...)
     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
   .. code-block:: cmake
 
 
     add_library(lib1 ...)
     add_library(lib1 ...)
     add_library(lib2 ...)
     add_library(lib2 ...)
-
     add_library(lib3 ...)
     add_library(lib3 ...)
-    target_link_libraries(lib3 PUBLIC "$<LINK_GROUP:feature1,lib1,lib2>")
-
     add_library(lib4 ...)
     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>")
     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>")
     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
   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
   .. code-block:: cmake
 
 
     add_library(lib1 ...)
     add_library(lib1 ...)
     add_library(lib2 ...)
     add_library(lib2 ...)
-
     add_library(lib3 ...)
     add_library(lib3 ...)
+    add_library(lib4 ...)
+
     target_link_libraries(lib3 PUBLIC lib1)
     target_link_libraries(lib3 PUBLIC lib1)
 
 
-    add_library(lib4 ...)
     target_link_libraries(lib4 PRIVATE lib3 "$<LINK_GROUP:feature1,lib1,lib2>")
     target_link_libraries(lib4 PRIVATE lib3 "$<LINK_GROUP:feature1,lib1,lib2>")
     # lib4 will only be linked with lib3 and the group {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
   .. code-block:: cmake
 
 
-    add_library(lib1 ...)
-    add_library(lib2 ...)
-
-    add_library(lib3 ...)
     target_link_libraries(lib3 PUBLIC "$<LINK_GROUP:feature1,lib1,lib2>")
     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
   .. code-block:: cmake
 
 
     add_library(lib1A ...)
     add_library(lib1A ...)
     add_library(lib1B ...)
     add_library(lib1B ...)
-
     add_library(lib2A ...)
     add_library(lib2A ...)
     add_library(lib2B ...)
     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(lib1A PUBLIC lib2A)
     target_link_libraries(lib2B PUBLIC lib1B)
     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
   .. 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(lib1A PUBLIC "$<LINK_GROUP:feat,lib2A,lib2B>")
     target_link_libraries(lib2B PUBLIC "$<LINK_GROUP:feat,lib1A,lib1B>")
     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:...>
 .. genex:: $<INSTALL_INTERFACE:...>
 
 

+ 40 - 29
Help/prop_tgt/LINK_LIBRARY_OVERRIDE.rst

@@ -3,52 +3,63 @@ LINK_LIBRARY_OVERRIDE
 
 
 .. versionadded:: 3.24
 .. 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]*
   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
 .. code-block:: cmake
 
 
   add_library(lib1 ...)
   add_library(lib1 ...)
-  target_link_libraries(lib1 PUBLIC "$<LINK_LIBRARY:feature1,external>")
-
   add_library(lib2 ...)
   add_library(lib2 ...)
-  target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature2,lib1>")
-
   add_library(lib3 ...)
   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)
   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")
   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
 .. 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
 Contents of ``LINK_LIBRARY_OVERRIDE`` may use
 :manual:`generator expressions <cmake-generator-expressions(7)>`.
 :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
 .. 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
 .. code-block:: cmake
 
 
   add_library(lib1 ...)
   add_library(lib1 ...)
-  target_link_libraries(lib1 PUBLIC "$<LINK_LIBRARY:feature1,external>")
-
   add_library(lib2 ...)
   add_library(lib2 ...)
-  target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature2,lib1>")
-
   add_library(lib3 ...)
   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)
   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)
   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
 .. code-block:: cmake
 
 
+  # When linking lib3, discard any library feature for lib1
   set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE_lib1 DEFAULT)
   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
 Contents of ``LINK_LIBRARY_OVERRIDE_<LIBRARY>`` may use
 :manual:`generator expressions <cmake-generator-expressions(7)>`.
 :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
 .. 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
 .. 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
 .. 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
 .. 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
 .. 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
 .. 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
 .. 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> <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
 Examples
 ^^^^^^^^
 ^^^^^^^^
@@ -19,36 +26,53 @@ Examples
 Solving cross-references between two static libraries
 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
 .. code-block:: cmake
 
 
   set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED TRUE)
   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()
   else()
     # feature not yet supported for the other environments
     # feature not yet supported for the other environments
     set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED FALSE)
     set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED FALSE)
   endif()
   endif()
 
 
   add_library(lib1 STATIC ...)
   add_library(lib1 STATIC ...)
+  add_library(lib2 SHARED ...)
 
 
-  add_library(lib3 SHARED ...)
   if(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED)
   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()
   else()
-    target_link_libraries(lib3 PRIVATE lib1 external)
+    target_link_libraries(lib2 PRIVATE lib1 external)
   endif()
   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``
 * ``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``
 * ``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
 .. 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
 .. 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
 .. 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
 Examples
 ^^^^^^^^
 ^^^^^^^^
@@ -41,19 +60,24 @@ Examples
 Loading a whole static library
 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
 .. code-block:: cmake
 
 
   set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED TRUE)
   set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED TRUE)
   if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
   if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
     set(CMAKE_C_LINK_LIBRARY_USING_load_archive "-force_load <LIB_ITEM>")
     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")
   elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
     set(CMAKE_C_LINK_LIBRARY_USING_load_archive "/WHOLEARCHIVE:<LIBRARY>")
     set(CMAKE_C_LINK_LIBRARY_USING_load_archive "/WHOLEARCHIVE:<LIBRARY>")
   else()
   else()
@@ -62,41 +86,45 @@ is offered by various environments but with a specific syntax:
   endif()
   endif()
 
 
   add_library(lib1 STATIC ...)
   add_library(lib1 STATIC ...)
-
   add_library(lib2 SHARED ...)
   add_library(lib2 SHARED ...)
+
   if(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED)
   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
     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()
   else()
     target_link_libraries(lib2 PRIVATE lib1 external)
     target_link_libraries(lib2 PRIVATE lib1 external)
   endif()
   endif()
 
 
 CMake will generate the following link expressions:
 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``
 * ``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
 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
 .. code-block:: cmake
 
 
   if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
   if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
     set(CMAKE_LINK_LIBRARY_USING_weak_library
     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)
     set(CMAKE_LINK_LIBRARY_USING_weak_library_SUPPORTED TRUE)
   endif()
   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)
     target_link_libraries(main PRIVATE lib external)
   endif()
   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``
 ``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
   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
   only when there are unavoidable circular references between two or more
   static libraries.
   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``
 ``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.
   :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties.
 
 
-**Features available for a subset of environments**
-
 ``WHOLE_ARCHIVE``
 ``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``
 ``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``
 ``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``
 ``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``
 ``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``.