Merge topic 'LINK_LIBRARY-Feature-properties'
6e5e7968c3 GenEx $<LINK_LIBRARY>: Add the support of properties attached to features
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !9510
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 8f98f8b..b71e3d9 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -467,6 +467,7 @@
/variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE
/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE
/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED
+ /variable/CMAKE_LANG_LINK_LIBRARY_FEATURE_PROPERTIES
/variable/CMAKE_LANG_LINK_LIBRARY_FILE_FLAG
/variable/CMAKE_LANG_LINK_LIBRARY_FLAG
/variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE
@@ -485,6 +486,7 @@
/variable/CMAKE_LINK_GROUP_USING_FEATURE
/variable/CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED
/variable/CMAKE_LINK_INTERFACE_LIBRARIES
+ /variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES
/variable/CMAKE_LINK_LIBRARY_FILE_FLAG
/variable/CMAKE_LINK_LIBRARY_FLAG
/variable/CMAKE_LINK_LIBRARY_USING_FEATURE
diff --git a/Help/release/dev/GenEx-LINK_LIBRARY-feature-properties.rst b/Help/release/dev/GenEx-LINK_LIBRARY-feature-properties.rst
new file mode 100644
index 0000000..a96eab9
--- /dev/null
+++ b/Help/release/dev/GenEx-LINK_LIBRARY-feature-properties.rst
@@ -0,0 +1,7 @@
+GenEx-LINK_LIBRARY-feature-properties
+-------------------------------------
+
+* Link features, as used with the :genex:`LINK_LIBRARY` generator expression,
+ gained the ability to have properties that describe their behavior by
+ specifying the :variable:`CMAKE_LINK_LIBRARY_<FEATURE>_PROPERTIES` or
+ :variable:`CMAKE_<LANG>_LINK_LIBRARY_<FEATURE>_PROPERTIES` variables.
diff --git a/Help/variable/CMAKE_LANG_LINK_LIBRARY_FEATURE_PROPERTIES.rst b/Help/variable/CMAKE_LANG_LINK_LIBRARY_FEATURE_PROPERTIES.rst
new file mode 100644
index 0000000..d8efd0f
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_LINK_LIBRARY_FEATURE_PROPERTIES.rst
@@ -0,0 +1,12 @@
+CMAKE_<LANG>_LINK_LIBRARY_<FEATURE>_PROPERTIES
+----------------------------------------------
+
+.. versionadded:: 3.30
+
+This variable defines the semantics of the specified ``<FEATURE>`` for the
+language ``<LANG>`` (as described by the
+:variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` or
+:variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variables) used for the link
+command generation.
+
+.. include:: CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.txt
diff --git a/Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.rst b/Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.rst
new file mode 100644
index 0000000..86b4e77
--- /dev/null
+++ b/Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.rst
@@ -0,0 +1,14 @@
+CMAKE_LINK_LIBRARY_<FEATURE>_PROPERTIES
+---------------------------------------
+
+.. versionadded:: 3.30
+
+This variable defines the semantics of the specified ``<FEATURE>`` (as
+described by the :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` or
+:variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variables) used for the link
+command generation.
+
+This variable will be considered only if the
+ :variable:`CMAKE_<LANG>_LINK_LIBRARY_<FEATURE>_PROPERTIES` is not defined.
+
+.. include:: CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.txt
diff --git a/Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.txt b/Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.txt
new file mode 100644
index 0000000..202a7ec
--- /dev/null
+++ b/Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.txt
@@ -0,0 +1,87 @@
+Feature Properties Definition
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A feature properties definition is a
+:ref:`semicolon-separated list <CMake Language Lists>` of ``property=value(s)``
+items. In the case of multiple values can be specified, they are separated by
+a comma.
+
+The following properties are supported:
+
+``LIBRARY_TYPE=<library_type-list>``
+ Specify which library types are supported by this feature. The possible
+ values are: ``STATIC``, ``SHARED``, ``MODULE`` or ``EXECUTABLE``.
+
+ If this property is not specified, the default is
+ ``LIBRARY_TYPE=STATIC,SHARED,MODULE,EXECUTABLE``.
+
+ If the feature is used with an unsupported library type, CMake will emit a
+ developer warning and the feature will be ignored.
+
+``OVERRIDE=<feature-list>``
+ Specify which features will be replaced by this one in the event of a
+ conflict. This override mechanism is superseded by any
+ :prop_tgt:`LINK_LIBRARY_OVERRIDE` or
+ :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties definitions.
+
+ If this property is not specified, the default is an empty list.
+
+``UNICITY=YES|NO|DEFAULT``
+ Manage the strategy of de-duplication for the libraries using this feature.
+
+ ``YES``
+ Libraries are de-duplicated regardless the default strategy applied by
+ CMake.
+
+ ``NO``
+ Libraries are not de-duplicated regardless the default strategy applied
+ by CMake.
+
+ ``DEFAULT``
+ Apply the default CMake strategy.
+
+ If this property is not specified, ``DEFAULT`` will be used.
+
+Example
+^^^^^^^
+
+A common need is the loading of a full archive as part of the creation of a
+shared library or an executable. For that purpose, the ``WHOLE_ARCHIVE``
+feature can be used.
+
+Currently, the associated properties with this feature are defined as follows:
+
+.. code-block:: cmake
+
+ set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC
+ OVERRIDE=DEFAULT
+ UNICITY=YES)
+
+``LIBRARY_TYPE=STATIC``
+ Obviously, this feature is only meaningful for static libraries.
+``OVERRIDE=DEFAULT``
+ The ``DEFAULT`` feature will be overridden by the ``WHOLE_ARCHIVE`` feature
+ because they are compatible and enhance the user's experience: standard
+ library specification and ``$<LINK_LIBRARY:WHOLE_ARCHIVE>`` can be used
+ freely.
+``UNICITY=YES``
+ When this feature is used, all symbols from the static library are loaded
+ by the linker, so there is no need to duplicate the library on the link
+ command.
+
+A typical usage of the ``WHOLE_ARCHIVE`` can be:
+
+.. code-block:: cmake
+
+ add_library(A STATIC ...)
+ add_library(B STATIC ...)
+
+ target_link_libraries(B PUBLIC A)
+ target_link_libraries(A PUBLIC B)
+
+ add_library(global SHARED ...)
+ target_link_libraries(global PRIVATE $<LINK_LIBRARY:WHOLE_ARCHIVE,A>)
+
+The resulting link command will only have one iteration of the ``A`` library
+specified with the needed linker flags to ensure the load of all the symbols
+of the library.
diff --git a/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.txt b/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.txt
index 4b13b7c..0359f58 100644
--- a/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.txt
+++ b/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.txt
@@ -2,6 +2,9 @@
and underscores. Feature names defined in all uppercase are reserved for
CMake's own built-in features (see `Predefined Features`_ further below).
+The feature behavior can be described using the
+:variable:`CMAKE_<LANG>_LINK_LIBRARY_<FEATURE>_PROPERTIES` or
+:variable:`CMAKE_LINK_LIBRARY_<FEATURE>_PROPERTIES` variables.
Feature Definitions
^^^^^^^^^^^^^^^^^^^
diff --git a/Modules/Platform/Apple-Clang.cmake b/Modules/Platform/Apple-Clang.cmake
index bd5ba9a..31f4293 100644
--- a/Modules/Platform/Apple-Clang.cmake
+++ b/Modules/Platform/Apple-Clang.cmake
@@ -19,6 +19,7 @@
set(CMAKE_${lang}_LINK_LIBRARY_USING_FRAMEWORK "-framework <LIBRARY>")
set(CMAKE_${lang}_LINK_LIBRARY_USING_FRAMEWORK_SUPPORTED TRUE)
+ set(CMAKE_${lang}_LINK_LIBRARY_FRAMEWORK_PROPERTIES LIBRARY_TYPE=STATIC,SHARED UNICITY=DEFAULT OVERRIDE=DEFAULT)
# linker selection
set(CMAKE_${lang}_USING_LINKER_SYSTEM "-fuse-ld=ld")
diff --git a/Modules/Platform/Apple-GNU.cmake b/Modules/Platform/Apple-GNU.cmake
index 15f6a71..20b18ad 100644
--- a/Modules/Platform/Apple-GNU.cmake
+++ b/Modules/Platform/Apple-GNU.cmake
@@ -17,6 +17,7 @@
set(CMAKE_${lang}_LINK_LIBRARY_USING_FRAMEWORK "-framework <LIBRARY>")
set(CMAKE_${lang}_LINK_LIBRARY_USING_FRAMEWORK_SUPPORTED TRUE)
+ set(CMAKE_LINK_LIBRARY_FRAMEWORK_PROPERTIES LIBRARY_TYPE=STATIC,SHARED UNICITY=DEFAULT OVERRIDE=DEFAULT)
set(CMAKE_${lang}_USING_LINKER_SYSTEM "")
set(CMAKE_${lang}_USING_LINKER_APPLE_CLASSIC "LINKER:-ld_classic")
diff --git a/Modules/Platform/CYGWIN-GNU.cmake b/Modules/Platform/CYGWIN-GNU.cmake
index 070b24d..5e2ba41 100644
--- a/Modules/Platform/CYGWIN-GNU.cmake
+++ b/Modules/Platform/CYGWIN-GNU.cmake
@@ -40,6 +40,7 @@
"LINKER:--no-whole-archive")
endif()
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
macro(__cygwin_compiler_gnu lang)
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index 533b9ce..1272baf 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -114,29 +114,37 @@
# Defines LINK_LIBRARY features for frameworks
set(CMAKE_LINK_LIBRARY_USING_FRAMEWORK "LINKER:-framework,<LIBRARY>")
set(CMAKE_LINK_LIBRARY_USING_FRAMEWORK_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_FRAMEWORK_PROPERTIES LIBRARY_TYPE=STATIC,SHARED UNICITY=DEFAULT OVERRIDE=DEFAULT)
set(CMAKE_LINK_LIBRARY_USING_NEEDED_FRAMEWORK "LINKER:-needed_framework,<LIBRARY>")
set(CMAKE_LINK_LIBRARY_USING_NEEDED_FRAMEWORK_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_NEEDED_FRAMEWORK_PROPERTIES LIBRARY_TYPE=STATIC,SHARED UNICITY=DEFAULT OVERRIDE=DEFAULT)
set(CMAKE_LINK_LIBRARY_USING_REEXPORT_FRAMEWORK "LINKER:-reexport_framework,<LIBRARY>")
set(CMAKE_LINK_LIBRARY_USING_REEXPORT_FRAMEWORK_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_REEXPORT_FRAMEWORK_PROPERTIES LIBRARY_TYPE=STATIC,SHARED UNICITY=DEFAULT OVERRIDE=DEFAULT)
set(CMAKE_LINK_LIBRARY_USING_WEAK_FRAMEWORK "LINKER:-weak_framework,<LIBRARY>")
set(CMAKE_LINK_LIBRARY_USING_WEAK_FRAMEWORK_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_WEAK_FRAMEWORK_PROPERTIES LIBRARY_TYPE=STATIC,SHARED UNICITY=DEFAULT OVERRIDE=DEFAULT)
# Defines LINK_LIBRARY features for libraries
set(CMAKE_LINK_LIBRARY_USING_NEEDED_LIBRARY "PATH{LINKER:-needed_library,<LIBRARY>}NAME{LINKER:-needed-l<LIBRARY>}")
set(CMAKE_LINK_LIBRARY_USING_NEEDED_LIBRARY_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_NEEDED_LIBRARY_PROPERTIES LIBRARY_TYPE=SHARED UNICITY=DEFAULT OVERRIDE=DEFAULT)
set(CMAKE_LINK_LIBRARY_USING_REEXPORT_LIBRARY "PATH{LINKER:-reexport_library,<LIBRARY>}NAME{LINKER:-reexport-l<LIBRARY>}")
set(CMAKE_LINK_LIBRARY_USING_REEXPORT_LIBRARY_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_REEXPORT_LIBRARY_PROPERTIES LIBRARY_TYPE=STATIC,SHARED UNICITY=DEFAULT OVERRIDE=DEFAULT)
set(CMAKE_LINK_LIBRARY_USING_WEAK_LIBRARY "PATH{LINKER:-weak_library,<LIBRARY>}NAME{LINKER:-weak-l<LIBRARY>}")
set(CMAKE_LINK_LIBRARY_USING_WEAK_LIBRARY_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_WEAK_LIBRARY_PROPERTIES LIBRARY_TYPE=STATIC,SHARED UNICITY=DEFAULT OVERRIDE=DEFAULT)
# Defines LINK_LIBRARY feature to Force loading of all members of an archive
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:-force_load,<LIB_ITEM>")
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
# default to searching for frameworks first
if(NOT DEFINED CMAKE_FIND_FRAMEWORK)
diff --git a/Modules/Platform/FreeBSD.cmake b/Modules/Platform/FreeBSD.cmake
index bd5a786..7d5f951 100644
--- a/Modules/Platform/FreeBSD.cmake
+++ b/Modules/Platform/FreeBSD.cmake
@@ -51,6 +51,7 @@
"LINKER:--no-whole-archive")
endif()
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
# Features for LINK_GROUP generator expression
diff --git a/Modules/Platform/Linux.cmake b/Modules/Platform/Linux.cmake
index 97a116f..fba6ab8 100644
--- a/Modules/Platform/Linux.cmake
+++ b/Modules/Platform/Linux.cmake
@@ -44,6 +44,7 @@
"LINKER:--no-whole-archive")
endif()
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
# Features for LINK_GROUP generator expression
## RESCAN: request the linker to rescan static libraries until there is
diff --git a/Modules/Platform/NetBSD.cmake b/Modules/Platform/NetBSD.cmake
index ab85923..af368cd 100644
--- a/Modules/Platform/NetBSD.cmake
+++ b/Modules/Platform/NetBSD.cmake
@@ -37,6 +37,7 @@
"LINKER:--no-whole-archive")
endif()
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
# Features for LINK_GROUP generator expression
diff --git a/Modules/Platform/SunOS.cmake b/Modules/Platform/SunOS.cmake
index b8a302c..73205c1 100644
--- a/Modules/Platform/SunOS.cmake
+++ b/Modules/Platform/SunOS.cmake
@@ -20,6 +20,7 @@
"LINKER:-z,defaultextract")
endif()
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
# Features for LINK_GROUP generator expression
diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake
index b9e6394..35055bc 100644
--- a/Modules/Platform/Windows-Clang.cmake
+++ b/Modules/Platform/Windows-Clang.cmake
@@ -140,6 +140,7 @@
## WHOLE_ARCHIVE: Force loading all members of an archive
set(CMAKE_${lang}_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:/WHOLEARCHIVE:<LIBRARY>")
set(CMAKE_${lang}_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+ set(CMAKE_${lang}_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
endif()
enable_language(RC)
diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake
index 9f81882..d2b25c6 100644
--- a/Modules/Platform/Windows-GNU.cmake
+++ b/Modules/Platform/Windows-GNU.cmake
@@ -88,6 +88,7 @@
"LINKER:--no-whole-archive")
endif()
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
# Features for LINK_GROUP generator expression
## RESCAN: request the linker to rescan static libraries until there is
diff --git a/Modules/Platform/Windows-IntelLLVM.cmake b/Modules/Platform/Windows-IntelLLVM.cmake
index b1a336b..691c7ce 100644
--- a/Modules/Platform/Windows-IntelLLVM.cmake
+++ b/Modules/Platform/Windows-IntelLLVM.cmake
@@ -37,6 +37,7 @@
## WHOLE_ARCHIVE: Force loading all members of an archive
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:/WHOLEARCHIVE:<LIBRARY>")
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+ set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
endif()
set(CMAKE_${lang}_LINK_EXECUTABLE
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index ef57031..c737b88 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -358,6 +358,7 @@
## WHOLE_ARCHIVE: Force loading all members of an archive
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "/WHOLEARCHIVE:<LIBRARY>")
set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+ set(CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_PROPERTIES LIBRARY_TYPE=STATIC UNICITY=YES OVERRIDE=DEFAULT)
endif()
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 8651436..db0d71a 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -30,6 +30,7 @@
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
+#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
@@ -201,6 +202,113 @@
return makefile->GetDefinition(featureSupported).IsOn();
}
+// LINK_LIBRARY feature properties management
+struct LinkLibraryFeaturePropertySet
+{
+ std::set<cmStateEnums::TargetType> LibraryTypes = {
+ cmStateEnums::EXECUTABLE, cmStateEnums::STATIC_LIBRARY,
+ cmStateEnums::SHARED_LIBRARY, cmStateEnums::MODULE_LIBRARY,
+ cmStateEnums::UNKNOWN_LIBRARY
+ };
+ std::set<std::string> Override;
+
+ enum UnicityKind
+ {
+ Default,
+ Yes,
+ No
+ };
+ UnicityKind Unicity = Default;
+};
+std::map<std::string, LinkLibraryFeaturePropertySet>
+ LinkLibraryFeatureProperties;
+const LinkLibraryFeaturePropertySet& GetLinkLibraryFeatureProperties(
+ cmMakefile* makefile, std::string const& linkLanguage,
+ const std::string& feature)
+{
+ auto it = LinkLibraryFeatureProperties.find(feature);
+ if (it != LinkLibraryFeatureProperties.end()) {
+ return it->second;
+ }
+
+ auto featurePropertiesVariable =
+ cmStrCat("CMAKE_", linkLanguage, "_LINK_LIBRARY_", feature, "_PROPERTIES");
+ auto featurePropertiesValues =
+ makefile->GetDefinition(featurePropertiesVariable);
+ if (featurePropertiesValues.IsEmpty()) {
+ // try language agnostic definition
+ featurePropertiesVariable =
+ cmStrCat("CMAKE_LINK_LIBRARY_", feature, "_PROPERTIES");
+ featurePropertiesValues =
+ makefile->GetDefinition(featurePropertiesVariable);
+ }
+ if (!featurePropertiesValues.IsEmpty()) {
+ LinkLibraryFeaturePropertySet featureProperties;
+ cmsys::RegularExpression processingOption{
+ "^(LIBRARY_TYPE|UNICITY|OVERRIDE)=((STATIC|SHARED|MODULE|EXECUTABLE)(,("
+ "STATIC|"
+ "SHARED|MODULE|EXECUTABLE)"
+ ")*|YES|NO|DEFAULT|[A-Za-z0-9_]+(,[A-Za-z0-9_]+)*)$"
+ };
+ std::string errorMessage;
+ for (auto const& option : cmList{ featurePropertiesValues }) {
+ if (processingOption.find(option)) {
+ if (processingOption.match(1) == "LIBRARY_TYPE") {
+ featureProperties.LibraryTypes.clear();
+ for (auto const& value :
+ cmTokenize(processingOption.match(2), ","_s)) {
+ if (value == "STATIC") {
+ featureProperties.LibraryTypes.emplace(
+ cmStateEnums::STATIC_LIBRARY);
+ } else if (value == "SHARED") {
+ featureProperties.LibraryTypes.emplace(
+ cmStateEnums::SHARED_LIBRARY);
+ } else if (value == "MODULE") {
+ featureProperties.LibraryTypes.emplace(
+ cmStateEnums::MODULE_LIBRARY);
+ } else if (value == "EXECUTABLE") {
+ featureProperties.LibraryTypes.emplace(cmStateEnums::EXECUTABLE);
+ } else {
+ errorMessage += cmStrCat(" ", option, '\n');
+ break;
+ }
+ }
+ // Always add UNKNOWN type
+ featureProperties.LibraryTypes.emplace(
+ cmStateEnums::UNKNOWN_LIBRARY);
+ } else if (processingOption.match(1) == "UNICITY") {
+ if (processingOption.match(2) == "YES") {
+ featureProperties.Unicity = LinkLibraryFeaturePropertySet::Yes;
+ } else if (processingOption.match(2) == "NO") {
+ featureProperties.Unicity = LinkLibraryFeaturePropertySet::No;
+ } else if (processingOption.match(2) == "DEFAULT") {
+ featureProperties.Unicity = LinkLibraryFeaturePropertySet::Default;
+ } else {
+ errorMessage += cmStrCat(" ", option, '\n');
+ }
+ } else if (processingOption.match(1) == "OVERRIDE") {
+ featureProperties.Override.clear();
+ auto values = cmTokenize(processingOption.match(2), ","_s);
+ featureProperties.Override.insert(values.begin(), values.end());
+ }
+ } else {
+ errorMessage += cmStrCat(" ", option, '\n');
+ }
+ }
+ if (!errorMessage.empty()) {
+ makefile->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Erroneous option(s) for '", featurePropertiesVariable,
+ "':\n", errorMessage));
+ }
+ return LinkLibraryFeatureProperties.emplace(feature, featureProperties)
+ .first->second;
+ }
+ return LinkLibraryFeatureProperties
+ .emplace(feature, LinkLibraryFeaturePropertySet{})
+ .first->second;
+}
+
// LINK_GROUP helpers
const auto LG_BEGIN = "<LINK_GROUP:"_s;
const auto LG_END = "</LINK_GROUP:"_s;
@@ -235,7 +343,9 @@
EntriesProcessing(const cmGeneratorTarget* target,
const std::string& linkLanguage, EntryVector& entries,
EntryVector& finalEntries)
- : Entries(entries)
+ : Target(target)
+ , LinkLanguage(linkLanguage)
+ , Entries(entries)
, FinalEntries(finalEntries)
{
const auto* makefile = target->Makefile;
@@ -398,6 +508,18 @@
bool IncludeEntry(LinkEntry const& entry) const
{
+ if (entry.Feature != cmComputeLinkDepends::LinkEntry::DEFAULT) {
+ auto const& featureProperties = GetLinkLibraryFeatureProperties(
+ this->Target->Makefile, this->LinkLanguage, entry.Feature);
+ if ((entry.Target == nullptr ||
+ featureProperties.LibraryTypes.find(entry.Target->GetType()) !=
+ featureProperties.LibraryTypes.end()) &&
+ featureProperties.Unicity !=
+ LinkLibraryFeaturePropertySet::Default) {
+ return featureProperties.Unicity == LinkLibraryFeaturePropertySet::No;
+ }
+ }
+
return this->Unicity == None ||
(this->Unicity == Shared &&
(entry.Target == nullptr ||
@@ -418,6 +540,8 @@
OrderKind Order = Reverse;
UnicityKind Unicity = Shared;
+ const cmGeneratorTarget* Target;
+ const std::string& LinkLanguage;
EntryVector& Entries;
EntryVector& FinalEntries;
std::set<size_t> Emitted;
@@ -973,12 +1097,14 @@
auto ale = this->AddLinkEntry(item, groupIndex.first);
dependee_index = ale.first;
LinkEntry& entry = this->EntryList[dependee_index];
+ bool supportedItem = true;
auto const& itemFeature =
this->GetCurrentFeature(entry.Item.Value, item.Feature);
if (inGroup && ale.second && entry.Target != nullptr &&
(entry.Target->GetType() == cmStateEnums::TargetType::OBJECT_LIBRARY ||
entry.Target->GetType() ==
cmStateEnums::TargetType::INTERFACE_LIBRARY)) {
+ supportedItem = false;
const auto& groupFeature = this->EntryList[groupIndex.first].Feature;
this->CMakeInstance->IssueMessage(
MessageType::AUTHOR_WARNING,
@@ -995,30 +1121,27 @@
}
if (ale.second) {
// current item not yet defined
- if (itemFeature != LinkEntry::DEFAULT && entry.Target != nullptr &&
- (entry.Target->GetType() ==
- cmStateEnums::TargetType::OBJECT_LIBRARY ||
- entry.Target->GetType() ==
- cmStateEnums::TargetType::INTERFACE_LIBRARY)) {
- this->CMakeInstance->IssueMessage(
- MessageType::AUTHOR_WARNING,
- cmStrCat("The feature '", itemFeature,
- "', specified as part of a generator-expression "
- "'$<LINK_LIBRARY:",
- itemFeature, ">', will not be applied to the ",
- (entry.Target->GetType() ==
- cmStateEnums::TargetType::OBJECT_LIBRARY
- ? "OBJECT"
- : "INTERFACE"),
- " library '", entry.Item.Value, "'."),
- this->Target->GetBacktrace());
- }
entry.Feature = itemFeature;
- }
- bool supportedItem = entry.Target == nullptr ||
- (entry.Target->GetType() != cmStateEnums::TargetType::OBJECT_LIBRARY &&
- entry.Target->GetType() != cmStateEnums::TargetType::INTERFACE_LIBRARY);
+ if (itemFeature != LinkEntry::DEFAULT && entry.Target != nullptr) {
+ auto const& featureProperties = GetLinkLibraryFeatureProperties(
+ this->Makefile, this->LinkLanguage, itemFeature);
+ if (featureProperties.LibraryTypes.find(entry.Target->GetType()) ==
+ featureProperties.LibraryTypes.end()) {
+ supportedItem = false;
+ entry.Feature = LinkEntry::DEFAULT;
+ this->CMakeInstance->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat("The feature '", itemFeature,
+ "', specified as part of a generator-expression "
+ "'$<LINK_LIBRARY:",
+ itemFeature, ">', will not be applied to the ",
+ cmState::GetTargetTypeName(entry.Target->GetType()), " '",
+ entry.Item.Value, "'."),
+ this->Target->GetBacktrace());
+ }
+ }
+ }
if (supportedItem) {
if (inGroup) {
@@ -1043,21 +1166,41 @@
}
}
if (entry.Feature != itemFeature) {
- // incompatibles features occurred
- this->CMakeInstance->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Impossible to link target '", this->Target->GetName(),
- "' because the link item '", entry.Item.Value,
- "', specified ",
- (itemFeature == LinkEntry::DEFAULT
- ? "without any feature or 'DEFAULT' feature"
- : cmStrCat("with the feature '", itemFeature, '\'')),
- ", has already occurred ",
- (entry.Feature == LinkEntry::DEFAULT
- ? "without any feature or 'DEFAULT' feature"
- : cmStrCat("with the feature '", entry.Feature, '\'')),
- ", which is not allowed."),
- this->Target->GetBacktrace());
+ bool incompatibleFeatures = true;
+ // check if an override is possible
+ auto const& entryFeatureProperties = GetLinkLibraryFeatureProperties(
+ this->Makefile, this->LinkLanguage, entry.Feature);
+ auto const& itemFeatureProperties = GetLinkLibraryFeatureProperties(
+ this->Makefile, this->LinkLanguage, itemFeature);
+ if (entryFeatureProperties.Override.empty() &&
+ !itemFeatureProperties.Override.empty() &&
+ itemFeatureProperties.Override.find(entry.Feature) !=
+ itemFeatureProperties.Override.end()) {
+ entry.Feature = itemFeature;
+ incompatibleFeatures = false;
+ } else if (!entryFeatureProperties.Override.empty() &&
+ itemFeatureProperties.Override.empty() &&
+ entryFeatureProperties.Override.find(itemFeature) !=
+ entryFeatureProperties.Override.end()) {
+ incompatibleFeatures = false;
+ }
+ if (incompatibleFeatures) {
+ // incompatibles features occurred
+ this->CMakeInstance->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Impossible to link target '", this->Target->GetName(),
+ "' because the link item '", entry.Item.Value,
+ "', specified ",
+ (itemFeature == LinkEntry::DEFAULT
+ ? "without any feature or 'DEFAULT' feature"
+ : cmStrCat("with the feature '", itemFeature, '\'')),
+ ", has already occurred ",
+ (entry.Feature == LinkEntry::DEFAULT
+ ? "without any feature or 'DEFAULT' feature"
+ : cmStrCat("with the feature '", entry.Feature, '\'')),
+ ", which is not allowed."),
+ this->Target->GetBacktrace());
+ }
}
}
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake
index 2ad45ba..a061127 100644
--- a/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake
@@ -35,3 +35,10 @@
run_cmake(override-features3)
run_cmake(override-features4)
run_cmake(override-features5)
+
+# testing feature properties specification
+run_cmake(bad-feature-properties1)
+run_cmake(bad-feature-properties2)
+run_cmake(bad-feature-properties3)
+run_cmake(bad-feature-properties4)
+run_cmake(bad-feature-properties5)
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties1-result.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties1-stderr.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties1-stderr.txt
new file mode 100644
index 0000000..ac07251
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties1-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error:
+ Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
+
+ BAD_PROPERTY=XXX
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties1.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties1.cmake
new file mode 100644
index 0000000..e5790a8
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties1.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+set(CMAKE_LINK_LIBRARY_USING_feature "<LIBRARY>")
+set(CMAKE_LINK_LIBRARY_USING_feature_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_feature_PROPERTIES BAD_PROPERTY=XXX)
+
+add_library(dep SHARED empty.c)
+
+add_library(lib SHARED empty.c)
+target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:feature,dep>")
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties2-result.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties2-stderr.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties2-stderr.txt
new file mode 100644
index 0000000..ac07251
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties2-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error:
+ Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
+
+ BAD_PROPERTY=XXX
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties2.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties2.cmake
new file mode 100644
index 0000000..dea98d2
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties2.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+set(CMAKE_LINK_LIBRARY_USING_feature "<LIBRARY>")
+set(CMAKE_LINK_LIBRARY_USING_feature_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_feature_PROPERTIES LIBRARY_TYPE=STATIC BAD_PROPERTY=XXX UNICITY=YES)
+
+add_library(dep SHARED empty.c)
+
+add_library(lib SHARED empty.c)
+target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:feature,dep>")
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties3-result.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties3-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties3-stderr.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties3-stderr.txt
new file mode 100644
index 0000000..29f5f66
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties3-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error:
+ Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
+
+ LIBRARY_TYPE=STATIC,BAD_TYPE
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties3.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties3.cmake
new file mode 100644
index 0000000..0a535db
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties3.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+set(CMAKE_LINK_LIBRARY_USING_feature "<LIBRARY>")
+set(CMAKE_LINK_LIBRARY_USING_feature_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_feature_PROPERTIES LIBRARY_TYPE=STATIC,BAD_TYPE)
+
+add_library(dep SHARED empty.c)
+
+add_library(lib SHARED empty.c)
+target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:feature,dep>")
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties4-result.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties4-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties4-stderr.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties4-stderr.txt
new file mode 100644
index 0000000..29f5f66
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties4-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error:
+ Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
+
+ LIBRARY_TYPE=STATIC,BAD_TYPE
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties4.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties4.cmake
new file mode 100644
index 0000000..c106653
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties4.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+set(CMAKE_LINK_LIBRARY_USING_feature "<LIBRARY>")
+set(CMAKE_LINK_LIBRARY_USING_feature_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_feature_PROPERTIES UNICITY=YES LIBRARY_TYPE=STATIC,BAD_TYPE)
+
+add_library(dep SHARED empty.c)
+
+add_library(lib SHARED empty.c)
+target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:feature,dep>")
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties5-result.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties5-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties5-stderr.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties5-stderr.txt
new file mode 100644
index 0000000..3e57782
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties5-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error:
+ Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
+
+ UNICITY=YES,NO
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties5.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties5.cmake
new file mode 100644
index 0000000..06efe7e
--- /dev/null
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/bad-feature-properties5.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+set(CMAKE_LINK_LIBRARY_USING_feature "<LIBRARY>")
+set(CMAKE_LINK_LIBRARY_USING_feature_SUPPORTED TRUE)
+set(CMAKE_LINK_LIBRARY_feature_PROPERTIES UNICITY=YES,NO)
+
+add_library(dep SHARED empty.c)
+
+add_library(lib SHARED empty.c)
+target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:feature,dep>")
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/library-ignored-stderr.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/library-ignored-stderr.txt
index f9a99af..8f43a7f 100644
--- a/Tests/RunCMake/GenEx-LINK_LIBRARY/library-ignored-stderr.txt
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/library-ignored-stderr.txt
@@ -1,6 +1,6 @@
CMake Warning \(dev\) at library-ignored.cmake:[0-9]+ \(add_library\):
The feature 'feat', specified as part of a generator-expression
- '\$<LINK_LIBRARY:feat>', will not be applied to the INTERFACE library
+ '\$<LINK_LIBRARY:feat>', will not be applied to the INTERFACE_LIBRARY
'front'.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
@@ -8,7 +8,14 @@
CMake Warning \(dev\) at library-ignored.cmake:[0-9]+ \(add_library\):
The feature 'feat', specified as part of a generator-expression
- '\$<LINK_LIBRARY:feat>', will not be applied to the OBJECT library 'dep'.
+ '\$<LINK_LIBRARY:feat>', will not be applied to the OBJECT_LIBRARY 'dep'.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\) at library-ignored.cmake:[0-9]+ \(add_library\):
+ The feature 'feat', specified as part of a generator-expression
+ '\$<LINK_LIBRARY:feat>', will not be applied to the SHARED_LIBRARY 'lib'.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/library-ignored.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/library-ignored.cmake
index a888bb8..675b87d 100644
--- a/Tests/RunCMake/GenEx-LINK_LIBRARY/library-ignored.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/library-ignored.cmake
@@ -2,13 +2,14 @@
set(CMAKE_C_LINK_LIBRARY_USING_feat_SUPPORTED TRUE)
set(CMAKE_C_LINK_LIBRARY_USING_feat "<LIBRARY>")
+set(CMAKE_C_LINK_LIBRARY_feat_PROPERTIES "LIBRARY_TYPE=STATIC")
add_library(dep OBJECT empty.c)
add_library(lib SHARED empty.c)
add_library(front INTERFACE)
-target_link_libraries(front INTERFACE lib)
+target_link_libraries(front INTERFACE "$<LINK_LIBRARY:feat,lib>")
add_library(lib2 SHARED empty.c)
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake
index 88a7e63..97a96b4 100644
--- a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake
@@ -135,4 +135,5 @@
OR CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|tvOS|visionOS|watchOS|Linux|BSD|MSYS|CYGWIN")
run_cmake(feature-WHOLE_ARCHIVE)
run_cmake_target(feature-WHOLE_ARCHIVE link-exe main)
+ run_cmake_target(feature-WHOLE_ARCHIVE circular-exe main_circular)
endif()
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/circular1.c b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/circular1.c
new file mode 100644
index 0000000..80ee413
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/circular1.c
@@ -0,0 +1,6 @@
+void circular2(void);
+
+void circular1(void)
+{
+ circular2();
+}
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/circular2.c b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/circular2.c
new file mode 100644
index 0000000..751bab5
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/circular2.c
@@ -0,0 +1,7 @@
+
+void circular1(void);
+
+void circular2(void)
+{
+ circular1();
+}
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE-circular-exe-stderr-darwin.txt b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE-circular-exe-stderr-darwin.txt
new file mode 100644
index 0000000..fb4871c
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE-circular-exe-stderr-darwin.txt
@@ -0,0 +1 @@
+(ld: warning: ignoring duplicate libraries:)?
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE.cmake
index e525325..5c599c9 100644
--- a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE.cmake
@@ -9,3 +9,13 @@
add_executable(main main.c)
target_link_libraries(main PRIVATE lib)
+
+
+add_library(circular1 STATIC circular1.c)
+add_library(circular2 STATIC circular2.c)
+
+target_link_libraries(circular1 PRIVATE circular2)
+target_link_libraries(circular2 PRIVATE circular1)
+
+add_executable(main_circular main_circular.c)
+target_link_libraries(main_circular PRIVATE $<LINK_LIBRARY:WHOLE_ARCHIVE,circular1>)
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/main_circular.c b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/main_circular.c
new file mode 100644
index 0000000..16ebee6
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/main_circular.c
@@ -0,0 +1,9 @@
+
+void circular1(void);
+
+int main(void)
+{
+ circular1();
+
+ return 0;
+}