mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-06 05:40:54 -06:00
Merge topic 'link-feature-attributes-stabilization' into release-3.30
576567f028Link feature attributes: stabilization5617c34c31Libraries processing: update configuration wording Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !9607
This commit is contained in:
@@ -202,8 +202,8 @@ bool IsFeatureSupported(cmMakefile* makefile, std::string const& linkLanguage,
|
||||
return makefile->GetDefinition(featureSupported).IsOn();
|
||||
}
|
||||
|
||||
// LINK_LIBRARY feature properties management
|
||||
struct LinkLibraryFeaturePropertySet
|
||||
// LINK_LIBRARY feature attributes management
|
||||
struct LinkLibraryFeatureAttributeSet
|
||||
{
|
||||
std::set<cmStateEnums::TargetType> LibraryTypes = {
|
||||
cmStateEnums::EXECUTABLE, cmStateEnums::STATIC_LIBRARY,
|
||||
@@ -212,84 +212,88 @@ struct LinkLibraryFeaturePropertySet
|
||||
};
|
||||
std::set<std::string> Override;
|
||||
|
||||
enum UnicityKind
|
||||
enum DeduplicationKind
|
||||
{
|
||||
Default,
|
||||
Yes,
|
||||
No
|
||||
};
|
||||
UnicityKind Unicity = Default;
|
||||
DeduplicationKind Deduplication = Default;
|
||||
};
|
||||
std::map<std::string, LinkLibraryFeaturePropertySet>
|
||||
LinkLibraryFeatureProperties;
|
||||
const LinkLibraryFeaturePropertySet& GetLinkLibraryFeatureProperties(
|
||||
std::map<std::string, LinkLibraryFeatureAttributeSet>
|
||||
LinkLibraryFeatureAttributes;
|
||||
const LinkLibraryFeatureAttributeSet& GetLinkLibraryFeatureAttributes(
|
||||
cmMakefile* makefile, std::string const& linkLanguage,
|
||||
const std::string& feature)
|
||||
{
|
||||
auto it = LinkLibraryFeatureProperties.find(feature);
|
||||
if (it != LinkLibraryFeatureProperties.end()) {
|
||||
auto it = LinkLibraryFeatureAttributes.find(feature);
|
||||
if (it != LinkLibraryFeatureAttributes.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
auto featurePropertiesVariable =
|
||||
cmStrCat("CMAKE_", linkLanguage, "_LINK_LIBRARY_", feature, "_PROPERTIES");
|
||||
auto featurePropertiesValues =
|
||||
makefile->GetDefinition(featurePropertiesVariable);
|
||||
if (featurePropertiesValues.IsEmpty()) {
|
||||
auto featureAttributesVariable =
|
||||
cmStrCat("CMAKE_", linkLanguage, "_LINK_LIBRARY_", feature, "_ATTRIBUTES");
|
||||
auto featureAttributesValues =
|
||||
makefile->GetDefinition(featureAttributesVariable);
|
||||
if (featureAttributesValues.IsEmpty()) {
|
||||
// try language agnostic definition
|
||||
featurePropertiesVariable =
|
||||
cmStrCat("CMAKE_LINK_LIBRARY_", feature, "_PROPERTIES");
|
||||
featurePropertiesValues =
|
||||
makefile->GetDefinition(featurePropertiesVariable);
|
||||
featureAttributesVariable =
|
||||
cmStrCat("CMAKE_LINK_LIBRARY_", feature, "_ATTRIBUTES");
|
||||
featureAttributesValues =
|
||||
makefile->GetDefinition(featureAttributesVariable);
|
||||
}
|
||||
if (!featurePropertiesValues.IsEmpty()) {
|
||||
LinkLibraryFeaturePropertySet featureProperties;
|
||||
if (!featureAttributesValues.IsEmpty()) {
|
||||
LinkLibraryFeatureAttributeSet featureAttributes;
|
||||
cmsys::RegularExpression processingOption{
|
||||
"^(LIBRARY_TYPE|UNICITY|OVERRIDE)=((STATIC|SHARED|MODULE|EXECUTABLE)(,("
|
||||
"^(LIBRARY_TYPE|DEDUPLICATION|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 }) {
|
||||
for (auto const& option : cmList{ featureAttributesValues }) {
|
||||
if (processingOption.find(option)) {
|
||||
if (processingOption.match(1) == "LIBRARY_TYPE") {
|
||||
featureProperties.LibraryTypes.clear();
|
||||
featureAttributes.LibraryTypes.clear();
|
||||
for (auto const& value :
|
||||
cmTokenize(processingOption.match(2), ","_s)) {
|
||||
if (value == "STATIC") {
|
||||
featureProperties.LibraryTypes.emplace(
|
||||
featureAttributes.LibraryTypes.emplace(
|
||||
cmStateEnums::STATIC_LIBRARY);
|
||||
} else if (value == "SHARED") {
|
||||
featureProperties.LibraryTypes.emplace(
|
||||
featureAttributes.LibraryTypes.emplace(
|
||||
cmStateEnums::SHARED_LIBRARY);
|
||||
} else if (value == "MODULE") {
|
||||
featureProperties.LibraryTypes.emplace(
|
||||
featureAttributes.LibraryTypes.emplace(
|
||||
cmStateEnums::MODULE_LIBRARY);
|
||||
} else if (value == "EXECUTABLE") {
|
||||
featureProperties.LibraryTypes.emplace(cmStateEnums::EXECUTABLE);
|
||||
featureAttributes.LibraryTypes.emplace(cmStateEnums::EXECUTABLE);
|
||||
} else {
|
||||
errorMessage += cmStrCat(" ", option, '\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Always add UNKNOWN type
|
||||
featureProperties.LibraryTypes.emplace(
|
||||
featureAttributes.LibraryTypes.emplace(
|
||||
cmStateEnums::UNKNOWN_LIBRARY);
|
||||
} else if (processingOption.match(1) == "UNICITY") {
|
||||
} else if (processingOption.match(1) == "DEDUPLICATION") {
|
||||
if (processingOption.match(2) == "YES") {
|
||||
featureProperties.Unicity = LinkLibraryFeaturePropertySet::Yes;
|
||||
featureAttributes.Deduplication =
|
||||
LinkLibraryFeatureAttributeSet::Yes;
|
||||
} else if (processingOption.match(2) == "NO") {
|
||||
featureProperties.Unicity = LinkLibraryFeaturePropertySet::No;
|
||||
featureAttributes.Deduplication =
|
||||
LinkLibraryFeatureAttributeSet::No;
|
||||
} else if (processingOption.match(2) == "DEFAULT") {
|
||||
featureProperties.Unicity = LinkLibraryFeaturePropertySet::Default;
|
||||
featureAttributes.Deduplication =
|
||||
LinkLibraryFeatureAttributeSet::Default;
|
||||
} else {
|
||||
errorMessage += cmStrCat(" ", option, '\n');
|
||||
}
|
||||
} else if (processingOption.match(1) == "OVERRIDE") {
|
||||
featureProperties.Override.clear();
|
||||
featureAttributes.Override.clear();
|
||||
auto values = cmTokenize(processingOption.match(2), ","_s);
|
||||
featureProperties.Override.insert(values.begin(), values.end());
|
||||
featureAttributes.Override.insert(values.begin(), values.end());
|
||||
}
|
||||
} else {
|
||||
errorMessage += cmStrCat(" ", option, '\n');
|
||||
@@ -298,14 +302,14 @@ const LinkLibraryFeaturePropertySet& GetLinkLibraryFeatureProperties(
|
||||
if (!errorMessage.empty()) {
|
||||
makefile->GetCMakeInstance()->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("Erroneous option(s) for '", featurePropertiesVariable,
|
||||
cmStrCat("Erroneous option(s) for '", featureAttributesVariable,
|
||||
"':\n", errorMessage));
|
||||
}
|
||||
return LinkLibraryFeatureProperties.emplace(feature, featureProperties)
|
||||
return LinkLibraryFeatureAttributes.emplace(feature, featureAttributes)
|
||||
.first->second;
|
||||
}
|
||||
return LinkLibraryFeatureProperties
|
||||
.emplace(feature, LinkLibraryFeaturePropertySet{})
|
||||
return LinkLibraryFeatureAttributes
|
||||
.emplace(feature, LinkLibraryFeatureAttributeSet{})
|
||||
.first->second;
|
||||
}
|
||||
|
||||
@@ -376,8 +380,10 @@ public:
|
||||
case cmPolicies::NEW: {
|
||||
if (auto libProcessing = makefile->GetDefinition(cmStrCat(
|
||||
"CMAKE_", linkLanguage, "_LINK_LIBRARIES_PROCESSING"))) {
|
||||
// UNICITY keyword is just for compatibility with previous
|
||||
// implementation
|
||||
cmsys::RegularExpression processingOption{
|
||||
"^(ORDER|UNICITY)=(FORWARD|REVERSE|ALL|NONE|SHARED)$"
|
||||
"^(ORDER|UNICITY|DEDUPLICATION)=(FORWARD|REVERSE|ALL|NONE|SHARED)$"
|
||||
};
|
||||
std::string errorMessage;
|
||||
for (auto const& option : cmList{ libProcessing }) {
|
||||
@@ -390,13 +396,14 @@ public:
|
||||
} else {
|
||||
errorMessage += cmStrCat(" ", option, '\n');
|
||||
}
|
||||
} else if (processingOption.match(1) == "UNICITY") {
|
||||
} else if (processingOption.match(1) == "UNICITY" ||
|
||||
processingOption.match(1) == "DEDUPLICATION") {
|
||||
if (processingOption.match(2) == "ALL") {
|
||||
this->Unicity = All;
|
||||
this->Deduplication = All;
|
||||
} else if (processingOption.match(2) == "NONE") {
|
||||
this->Unicity = None;
|
||||
this->Deduplication = None;
|
||||
} else if (processingOption.match(2) == "SHARED") {
|
||||
this->Unicity = Shared;
|
||||
this->Deduplication = Shared;
|
||||
} else {
|
||||
errorMessage += cmStrCat(" ", option, '\n');
|
||||
}
|
||||
@@ -499,7 +506,7 @@ private:
|
||||
Reverse
|
||||
};
|
||||
|
||||
enum UnicityKind
|
||||
enum DeduplicationKind
|
||||
{
|
||||
None,
|
||||
Shared,
|
||||
@@ -509,22 +516,23 @@ private:
|
||||
bool IncludeEntry(LinkEntry const& entry) const
|
||||
{
|
||||
if (entry.Feature != cmComputeLinkDepends::LinkEntry::DEFAULT) {
|
||||
auto const& featureProperties = GetLinkLibraryFeatureProperties(
|
||||
auto const& featureAttributes = GetLinkLibraryFeatureAttributes(
|
||||
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;
|
||||
featureAttributes.LibraryTypes.find(entry.Target->GetType()) !=
|
||||
featureAttributes.LibraryTypes.end()) &&
|
||||
featureAttributes.Deduplication !=
|
||||
LinkLibraryFeatureAttributeSet::Default) {
|
||||
return featureAttributes.Deduplication ==
|
||||
LinkLibraryFeatureAttributeSet::No;
|
||||
}
|
||||
}
|
||||
|
||||
return this->Unicity == None ||
|
||||
(this->Unicity == Shared &&
|
||||
return this->Deduplication == None ||
|
||||
(this->Deduplication == Shared &&
|
||||
(entry.Target == nullptr ||
|
||||
entry.Target->GetType() != cmStateEnums::SHARED_LIBRARY)) ||
|
||||
(this->Unicity == All && entry.Kind != LinkEntry::Library);
|
||||
(this->Deduplication == All && entry.Kind != LinkEntry::Library);
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
@@ -539,7 +547,7 @@ private:
|
||||
}
|
||||
|
||||
OrderKind Order = Reverse;
|
||||
UnicityKind Unicity = Shared;
|
||||
DeduplicationKind Deduplication = Shared;
|
||||
const cmGeneratorTarget* Target;
|
||||
const std::string& LinkLanguage;
|
||||
EntryVector& Entries;
|
||||
@@ -1121,27 +1129,29 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
|
||||
" library '", entry.Item.Value, "'."),
|
||||
this->Target->GetBacktrace());
|
||||
}
|
||||
// check if feature is applicable to this item
|
||||
if (itemFeature != LinkEntry::DEFAULT && entry.Target != nullptr) {
|
||||
auto const& featureAttributes = GetLinkLibraryFeatureAttributes(
|
||||
this->Makefile, this->LinkLanguage, itemFeature);
|
||||
if (featureAttributes.LibraryTypes.find(entry.Target->GetType()) ==
|
||||
featureAttributes.LibraryTypes.end()) {
|
||||
supportedItem = false;
|
||||
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 (ale.second) {
|
||||
// current item not yet defined
|
||||
entry.Feature = itemFeature;
|
||||
|
||||
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) {
|
||||
entry.Feature = LinkEntry::DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1170,38 +1180,50 @@ void cmComputeLinkDepends::AddLinkEntries(size_t depender_index,
|
||||
if (entry.Feature != itemFeature) {
|
||||
bool incompatibleFeatures = true;
|
||||
// check if an override is possible
|
||||
auto const& entryFeatureProperties = GetLinkLibraryFeatureProperties(
|
||||
auto const& entryFeatureAttributes = GetLinkLibraryFeatureAttributes(
|
||||
this->Makefile, this->LinkLanguage, entry.Feature);
|
||||
auto const& itemFeatureProperties = GetLinkLibraryFeatureProperties(
|
||||
auto const& itemFeatureAttributes = GetLinkLibraryFeatureAttributes(
|
||||
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
|
||||
if (itemFeatureAttributes.Override.find(entry.Feature) !=
|
||||
itemFeatureAttributes.Override.end() &&
|
||||
entryFeatureAttributes.Override.find(itemFeature) !=
|
||||
entryFeatureAttributes.Override.end()) {
|
||||
// features override each other
|
||||
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."),
|
||||
"' is specified with the features '", itemFeature,
|
||||
"' and '", entry.Feature, "'",
|
||||
", and both have an 'OVERRIDE' attribute that overrides "
|
||||
"the other. Such cycles are not allowed."),
|
||||
this->Target->GetBacktrace());
|
||||
} else {
|
||||
if (itemFeatureAttributes.Override.find(entry.Feature) !=
|
||||
itemFeatureAttributes.Override.end()) {
|
||||
entry.Feature = itemFeature;
|
||||
incompatibleFeatures = false;
|
||||
} else if (entryFeatureAttributes.Override.find(itemFeature) !=
|
||||
entryFeatureAttributes.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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user