summaryrefslogtreecommitdiffstats
path: root/Source/cmComputeLinkInformation.cxx
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2022-01-31 15:43:41 (GMT)
committerMarc Chevrier <marc.chevrier@gmail.com>2022-02-28 09:26:26 (GMT)
commit0a81ea1f12cbaf60ec60b8e4a27c5ea476a655de (patch)
tree8491b1ae05b5c252b1165244c6976d81c87397ee /Source/cmComputeLinkInformation.cxx
parenta9928eb4a54431780d589f70460e5715258f1d27 (diff)
downloadCMake-0a81ea1f12cbaf60ec60b8e4a27c5ea476a655de.zip
CMake-0a81ea1f12cbaf60ec60b8e4a27c5ea476a655de.tar.gz
CMake-0a81ea1f12cbaf60ec60b8e4a27c5ea476a655de.tar.bz2
Genex-LINK_GROUP: Add possibility to group libraries at link step
Fixes: #23121
Diffstat (limited to 'Source/cmComputeLinkInformation.cxx')
-rw-r--r--Source/cmComputeLinkInformation.cxx284
1 files changed, 201 insertions, 83 deletions
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index fe4491d..67214f1 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -350,21 +350,23 @@ cmComputeLinkInformation::cmComputeLinkInformation(
if (!this->GetLibLinkFileFlag().empty()) {
this->LibraryFeatureDescriptors.emplace(
"__CMAKE_LINK_LIBRARY",
- FeatureDescriptor{ "__CMAKE_LINK_LIBRARY",
- cmStrCat(this->GetLibLinkFileFlag(), "<LIBRARY>") });
+ LibraryFeatureDescriptor{
+ "__CMAKE_LINK_LIBRARY",
+ cmStrCat(this->GetLibLinkFileFlag(), "<LIBRARY>") });
}
if (!this->GetObjLinkFileFlag().empty()) {
this->LibraryFeatureDescriptors.emplace(
"__CMAKE_LINK_OBJECT",
- FeatureDescriptor{ "__CMAKE_LINK_OBJECT",
- cmStrCat(this->GetObjLinkFileFlag(), "<LIBRARY>") });
+ LibraryFeatureDescriptor{
+ "__CMAKE_LINK_OBJECT",
+ cmStrCat(this->GetObjLinkFileFlag(), "<LIBRARY>") });
}
if (!this->LoaderFlag->empty()) {
// Define a Feature descriptor for the link of an executable with exports
this->LibraryFeatureDescriptors.emplace(
"__CMAKE_LINK_EXECUTABLE",
- FeatureDescriptor{ "__CMAKE_LINK_EXECUTABLE",
- cmStrCat(this->LoaderFlag, "<LIBRARY>") });
+ LibraryFeatureDescriptor{ "__CMAKE_LINK_EXECUTABLE",
+ cmStrCat(this->LoaderFlag, "<LIBRARY>") });
}
// Check the platform policy for missing soname case.
@@ -544,6 +546,19 @@ bool cmComputeLinkInformation::Compute()
// Add the link line items.
for (cmComputeLinkDepends::LinkEntry const& linkEntry : linkEntries) {
+ if (linkEntry.Kind == cmComputeLinkDepends::LinkEntry::Group) {
+ const auto& groupFeature = this->GetGroupFeature(linkEntry.Feature);
+ if (groupFeature.Supported) {
+ this->Items.emplace_back(
+ BT<std::string>{ linkEntry.Item.Value == "<LINK_GROUP>"
+ ? groupFeature.Prefix
+ : groupFeature.Suffix,
+ linkEntry.Item.Backtrace },
+ ItemIsPath::No);
+ }
+ continue;
+ }
+
if (currentFeature != nullptr &&
linkEntry.Feature != currentFeature->Name) {
// emit feature suffix, if any
@@ -664,6 +679,117 @@ bool IsValidFeatureFormat(const std::string& format)
format.find("<LIB_ITEM>") != std::string::npos ||
format.find("<LINK_ITEM>") != std::string::npos;
}
+
+class FeaturePlaceHolderExpander : public cmPlaceholderExpander
+{
+public:
+ FeaturePlaceHolderExpander(const std::string* library,
+ const std::string* libItem = nullptr,
+ const std::string* linkItem = nullptr)
+ : Library(library)
+ , LibItem(libItem)
+ , LinkItem(linkItem)
+ {
+ }
+
+private:
+ std::string ExpandVariable(std::string const& variable) override
+ {
+ if (this->Library != nullptr && variable == "LIBRARY") {
+ return *this->Library;
+ }
+ if (this->LibItem != nullptr && variable == "LIB_ITEM") {
+ return *this->LibItem;
+ }
+ if (this->LinkItem != nullptr && variable == "LINK_ITEM") {
+ return *this->LinkItem;
+ }
+
+ return variable;
+ }
+
+ const std::string* Library = nullptr;
+ const std::string* LibItem = nullptr;
+ const std::string* LinkItem = nullptr;
+};
+}
+
+cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor(
+ std::string name, std::string itemFormat)
+ : Name(std::move(name))
+ , Supported(true)
+ , ItemPathFormat(std::move(itemFormat))
+ , ItemNameFormat(this->ItemPathFormat)
+{
+}
+cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor(
+ std::string name, std::string itemPathFormat, std::string itemNameFormat)
+ : Name(std::move(name))
+ , Supported(true)
+ , ItemPathFormat(std::move(itemPathFormat))
+ , ItemNameFormat(std::move(itemNameFormat))
+{
+}
+cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor(
+ std::string name, std::string prefix, std::string itemPathFormat,
+ std::string itemNameFormat, std::string suffix)
+ : Name(std::move(name))
+ , Supported(true)
+ , Prefix(std::move(prefix))
+ , Suffix(std::move(suffix))
+ , ItemPathFormat(std::move(itemPathFormat))
+ , ItemNameFormat(std::move(itemNameFormat))
+{
+}
+cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor(
+ std::string name, std::string prefix, std::string suffix, bool)
+ : Name(std::move(name))
+ , Supported(true)
+ , Prefix(std::move(prefix))
+ , Suffix(std::move(suffix))
+{
+}
+
+std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem(
+ std::string const& library, ItemIsPath isPath) const
+{
+ auto format =
+ isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat;
+
+ // replace <LIBRARY>, <LIB_ITEM> and <LINK_ITEM> patterns with library path
+ FeaturePlaceHolderExpander expander(&library, &library, &library);
+ return expander.ExpandVariables(format);
+}
+std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem(
+ std::string const& library, std::string const& libItem,
+ std::string const& linkItem, ItemIsPath isPath) const
+{
+ auto format =
+ isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat;
+
+ // replace <LIBRARY>, <LIB_ITEM> and <LINK_ITEM> patterns
+ FeaturePlaceHolderExpander expander(&library, &libItem, &linkItem);
+ return expander.ExpandVariables(format);
+}
+
+cmComputeLinkInformation::LibraryFeatureDescriptor::LibraryFeatureDescriptor(
+ std::string name, std::string itemFormat)
+ : FeatureDescriptor(std::move(name), std::move(itemFormat))
+{
+}
+cmComputeLinkInformation::LibraryFeatureDescriptor::LibraryFeatureDescriptor(
+ std::string name, std::string itemPathFormat, std::string itemNameFormat)
+ : FeatureDescriptor(std::move(name), std::move(itemPathFormat),
+ std::move(itemNameFormat))
+{
+}
+cmComputeLinkInformation::LibraryFeatureDescriptor::LibraryFeatureDescriptor(
+ std::string name, std::string prefix, std::string itemPathFormat,
+ std::string itemNameFormat, std::string suffix)
+ : FeatureDescriptor(std::move(name), std::move(prefix),
+ std::move(itemPathFormat), std::move(itemNameFormat),
+ std::move(suffix))
+{
}
bool cmComputeLinkInformation::AddLibraryFeature(std::string const& feature)
@@ -792,12 +918,13 @@ bool cmComputeLinkInformation::AddLibraryFeature(std::string const& feature)
if (items.size() == 2) {
this->LibraryFeatureDescriptors.emplace(
- feature, FeatureDescriptor{ feature, items[0].Value, items[1].Value });
+ feature,
+ LibraryFeatureDescriptor{ feature, items[0].Value, items[1].Value });
} else {
this->LibraryFeatureDescriptors.emplace(
feature,
- FeatureDescriptor{ feature, items[0].Value, items[1].Value,
- items[2].Value, items[3].Value });
+ LibraryFeatureDescriptor{ feature, items[0].Value, items[1].Value,
+ items[2].Value, items[3].Value });
}
return true;
@@ -819,89 +946,80 @@ cmComputeLinkInformation::FindLibraryFeature(std::string const& feature) const
return &it->second;
}
-namespace {
-class FeaturePlaceHolderExpander : public cmPlaceholderExpander
+cmComputeLinkInformation::GroupFeatureDescriptor::GroupFeatureDescriptor(
+ std::string name, std::string prefix, std::string suffix)
+ : FeatureDescriptor(std::move(name), std::move(prefix), std::move(suffix),
+ true)
{
-public:
- FeaturePlaceHolderExpander(const std::string* library,
- const std::string* libItem = nullptr,
- const std::string* linkItem = nullptr)
- : Library(library)
- , LibItem(libItem)
- , LinkItem(linkItem)
- {
- }
+}
-private:
- std::string ExpandVariable(std::string const& variable) override
- {
- if (this->Library != nullptr && variable == "LIBRARY") {
- return *this->Library;
- }
- if (this->LibItem != nullptr && variable == "LIB_ITEM") {
- return *this->LibItem;
- }
- if (this->LinkItem != nullptr && variable == "LINK_ITEM") {
- return *this->LinkItem;
- }
+cmComputeLinkInformation::FeatureDescriptor const&
+cmComputeLinkInformation::GetGroupFeature(std::string const& feature)
+{
+ auto it = this->GroupFeatureDescriptors.find(feature);
+ if (it != this->GroupFeatureDescriptors.end()) {
+ return it->second;
+ }
- return variable;
+ auto featureName =
+ cmStrCat("CMAKE_", this->LinkLanguage, "_LINK_GROUP_USING_", feature);
+ cmValue featureSupported =
+ this->Makefile->GetDefinition(cmStrCat(featureName, "_SUPPORTED"));
+ if (!featureSupported.IsOn()) {
+ featureName = cmStrCat("CMAKE_LINK_GROUP_USING_", feature);
+ featureSupported =
+ this->Makefile->GetDefinition(cmStrCat(featureName, "_SUPPORTED"));
+ }
+ if (!featureSupported.IsOn()) {
+ this->CMakeInstance->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Feature '", feature,
+ "', specified through generator-expression '$<LINK_GROUP>' to "
+ "link target '",
+ this->Target->GetName(), "', is not supported for the '",
+ this->LinkLanguage, "' link language."),
+ this->Target->GetBacktrace());
+ return this->GroupFeatureDescriptors.emplace(feature, FeatureDescriptor{})
+ .first->second;
}
- const std::string* Library = nullptr;
- const std::string* LibItem = nullptr;
- const std::string* LinkItem = nullptr;
-};
-}
+ cmValue langFeature = this->Makefile->GetDefinition(featureName);
+ if (!langFeature) {
+ this->CMakeInstance->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Feature '", feature,
+ "', specified through generator-expression '$<LINK_GROUP>' to "
+ "link target '",
+ this->Target->GetName(), "', is not defined for the '",
+ this->LinkLanguage, "' link language."),
+ this->Target->GetBacktrace());
+ return this->GroupFeatureDescriptors.emplace(feature, FeatureDescriptor{})
+ .first->second;
+ }
-cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor(
- std::string name, std::string itemFormat)
- : Name(std::move(name))
- , Supported(true)
- , ItemPathFormat(std::move(itemFormat))
- , ItemNameFormat(this->ItemPathFormat)
-{
-}
-cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor(
- std::string name, std::string itemPathFormat, std::string itemNameFormat)
- : Name(std::move(name))
- , Supported(true)
- , ItemPathFormat(std::move(itemPathFormat))
- , ItemNameFormat(std::move(itemNameFormat))
-{
-}
-cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor(
- std::string name, std::string prefix, std::string itemPathFormat,
- std::string itemNameFormat, std::string suffix)
- : Name(std::move(name))
- , Supported(true)
- , Prefix(std::move(prefix))
- , Suffix(std::move(suffix))
- , ItemPathFormat(std::move(itemPathFormat))
- , ItemNameFormat(std::move(itemNameFormat))
-{
-}
+ auto items =
+ cmExpandListWithBacktrace(langFeature, this->Target->GetBacktrace(), true);
-std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem(
- std::string const& library, ItemIsPath isPath) const
-{
- auto format =
- isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat;
+ // replace LINKER: pattern
+ this->Target->ResolveLinkerWrapper(items, this->LinkLanguage, true);
- // replace <LIBRARY>, <LIB_ITEM> and <LINK_ITEM> patterns with library path
- FeaturePlaceHolderExpander expander(&library, &library, &library);
- return expander.ExpandVariables(format);
-}
-std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem(
- std::string const& library, std::string const& libItem,
- std::string const& linkItem, ItemIsPath isPath) const
-{
- auto format =
- isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat;
+ if (items.size() == 2) {
+ return this->GroupFeatureDescriptors
+ .emplace(
+ feature,
+ GroupFeatureDescriptor{ feature, items[0].Value, items[1].Value })
+ .first->second;
+ }
- // replace <LIBRARY>, <LIB_ITEM> and <LINK_ITEM> patterns
- FeaturePlaceHolderExpander expander(&library, &libItem, &linkItem);
- return expander.ExpandVariables(format);
+ this->CMakeInstance->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Feature '", feature, "', specified by variable '", featureName,
+ "', is malformed (wrong number of elements) and cannot be used "
+ "to link target '",
+ this->Target->GetName(), "'."),
+ this->Target->GetBacktrace());
+ return this->GroupFeatureDescriptors.emplace(feature, FeatureDescriptor{})
+ .first->second;
}
void cmComputeLinkInformation::AddImplicitLinkInfo()