mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-07 22:30:13 -06:00
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
This commit is contained in:
@@ -467,6 +467,7 @@ Variables that Control the Build
|
||||
/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 @@ Variables that Control the Build
|
||||
/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
|
||||
|
||||
@@ -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.
|
||||
12
Help/variable/CMAKE_LANG_LINK_LIBRARY_FEATURE_PROPERTIES.rst
Normal file
12
Help/variable/CMAKE_LANG_LINK_LIBRARY_FEATURE_PROPERTIES.rst
Normal file
@@ -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
|
||||
14
Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.rst
Normal file
14
Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.rst
Normal file
@@ -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
|
||||
87
Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.txt
Normal file
87
Help/variable/CMAKE_LINK_LIBRARY_FEATURE_PROPERTIES.txt
Normal file
@@ -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.
|
||||
@@ -2,6 +2,9 @@ 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).
|
||||
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -19,6 +19,7 @@ macro(__apple_compiler_clang lang)
|
||||
|
||||
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")
|
||||
|
||||
@@ -17,6 +17,7 @@ macro(__apple_compiler_gnu lang)
|
||||
|
||||
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")
|
||||
|
||||
@@ -40,6 +40,7 @@ else()
|
||||
"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)
|
||||
|
||||
@@ -114,29 +114,37 @@ set(CMAKE_CREATE_TEXT_STUBS "<CMAKE_TAPI> stubify -isysroot <CMAKE_OSX_SYSROOT>
|
||||
# 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)
|
||||
|
||||
@@ -51,6 +51,7 @@ else()
|
||||
"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
|
||||
|
||||
@@ -44,6 +44,7 @@ else()
|
||||
"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
|
||||
|
||||
@@ -37,6 +37,7 @@ else()
|
||||
"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
|
||||
|
||||
@@ -20,6 +20,7 @@ else()
|
||||
"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
|
||||
|
||||
@@ -140,6 +140,7 @@ macro(__windows_compiler_clang_gnu lang)
|
||||
## 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)
|
||||
|
||||
@@ -88,6 +88,7 @@ else()
|
||||
"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
|
||||
|
||||
@@ -37,6 +37,7 @@ macro(__windows_compiler_intel lang)
|
||||
## 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
|
||||
|
||||
@@ -358,6 +358,7 @@ if(MSVC_VERSION GREATER "1900")
|
||||
## 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()
|
||||
|
||||
|
||||
|
||||
@@ -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 @@ bool IsFeatureSupported(cmMakefile* makefile, std::string const& linkLanguage,
|
||||
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 @@ public:
|
||||
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 @@ private:
|
||||
|
||||
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 @@ private:
|
||||
|
||||
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 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
|
||||
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 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
|
||||
}
|
||||
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 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
|
||||
}
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,3 +35,10 @@ run_cmake(override-features2)
|
||||
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)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error:
|
||||
Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
|
||||
|
||||
BAD_PROPERTY=XXX
|
||||
@@ -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>")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error:
|
||||
Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
|
||||
|
||||
BAD_PROPERTY=XXX
|
||||
@@ -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>")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error:
|
||||
Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
|
||||
|
||||
LIBRARY_TYPE=STATIC,BAD_TYPE
|
||||
@@ -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>")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error:
|
||||
Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
|
||||
|
||||
LIBRARY_TYPE=STATIC,BAD_TYPE
|
||||
@@ -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>")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error:
|
||||
Erroneous option\(s\) for 'CMAKE_LINK_LIBRARY_feature_PROPERTIES':
|
||||
|
||||
UNICITY=YES,NO
|
||||
@@ -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>")
|
||||
@@ -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 @@ 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 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.
|
||||
|
||||
@@ -2,13 +2,14 @@ enable_language(C)
|
||||
|
||||
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)
|
||||
|
||||
@@ -135,4 +135,5 @@ if ((CMAKE_SYSTEM_NAME STREQUAL "Windows" AND
|
||||
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()
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
void circular2(void);
|
||||
|
||||
void circular1(void)
|
||||
{
|
||||
circular2();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
void circular1(void);
|
||||
|
||||
void circular2(void)
|
||||
{
|
||||
circular1();
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
(ld: warning: ignoring duplicate libraries:)?
|
||||
@@ -9,3 +9,13 @@ target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,base>")
|
||||
|
||||
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>)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
void circular1(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
circular1();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user