diff options
author | Marc Chevrier <marc.chevrier@gmail.com> | 2022-01-31 15:43:41 (GMT) |
---|---|---|
committer | Marc Chevrier <marc.chevrier@gmail.com> | 2022-02-28 09:26:26 (GMT) |
commit | 0a81ea1f12cbaf60ec60b8e4a27c5ea476a655de (patch) | |
tree | 8491b1ae05b5c252b1165244c6976d81c87397ee /Source/cmGeneratorExpressionNode.cxx | |
parent | a9928eb4a54431780d589f70460e5715258f1d27 (diff) | |
download | CMake-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/cmGeneratorExpressionNode.cxx')
-rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index b63b90b..db043ec 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1231,7 +1231,15 @@ static const struct LinkLibraryNode : public cmGeneratorExpressionNode return std::string(); } + static cmsys::RegularExpression featureNameValidator("^[A-Za-z0-9_]+$"); auto const& feature = list.front(); + if (!featureNameValidator.find(feature)) { + reportError(context, content->GetOriginalExpression(), + cmStrCat("The feature name '", feature, + "' contains invalid characters.")); + return std::string(); + } + const auto LL_BEGIN = cmStrCat("<LINK_LIBRARY:", feature, '>'); const auto LL_END = cmStrCat("</LINK_LIBRARY:", feature, '>'); @@ -1252,6 +1260,17 @@ static const struct LinkLibraryNode : public cmGeneratorExpressionNode "$<LINK_LIBRARY:...> with different features cannot be nested."); return std::string(); } + // $<LINK_GROUP:...> must not appear as part of $<LINK_LIBRARY:...> + it = std::find_if(list.cbegin() + 1, list.cend(), + [](const std::string& item) -> bool { + return cmHasPrefix(item, "<LINK_GROUP:"_s); + }); + if (it != list.cend()) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_GROUP:...> cannot be nested inside a " + "$<LINK_LIBRARY:...> expression."); + return std::string(); + } list.front() = LL_BEGIN; list.push_back(LL_END); @@ -1260,6 +1279,71 @@ static const struct LinkLibraryNode : public cmGeneratorExpressionNode } } linkLibraryNode; +static const struct LinkGroupNode : public cmGeneratorExpressionNode +{ + LinkGroupNode() {} // NOLINT(modernize-use-equals-default) + + int NumExpectedParameters() const override { return OneOrMoreParameters; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget || !dagChecker || + !dagChecker->EvaluatingLinkLibraries()) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_GROUP:...> may only be used with binary targets " + "to specify group of link libraries."); + return std::string(); + } + + std::vector<std::string> list; + cmExpandLists(parameters.begin(), parameters.end(), list); + if (list.empty()) { + reportError( + context, content->GetOriginalExpression(), + "$<LINK_GROUP:...> expects a feature name as first argument."); + return std::string(); + } + // $<LINK_GROUP:..> cannot be nested + if (std::find_if(list.cbegin(), list.cend(), + [](const std::string& item) -> bool { + return cmHasPrefix(item, "<LINK_GROUP"_s); + }) != list.cend()) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_GROUP:...> cannot be nested."); + return std::string(); + } + if (list.size() == 1) { + // no libraries specified, ignore this genex + return std::string(); + } + + static cmsys::RegularExpression featureNameValidator("^[A-Za-z0-9_]+$"); + auto const& feature = list.front(); + if (!featureNameValidator.find(feature)) { + reportError(context, content->GetOriginalExpression(), + cmStrCat("The feature name '", feature, + "' contains invalid characters.")); + return std::string(); + } + + const auto LG_BEGIN = cmStrCat( + "<LINK_GROUP:", feature, ':', + cmJoin(cmRange<decltype(list.cbegin())>(list.cbegin() + 1, list.cend()), + "|"_s), + '>'); + const auto LG_END = cmStrCat("</LINK_GROUP:", feature, '>'); + + list.front() = LG_BEGIN; + list.push_back(LG_END); + + return cmJoin(list, ";"_s); + } +} linkGroupNode; + static const struct HostLinkNode : public cmGeneratorExpressionNode { HostLinkNode() {} // NOLINT(modernize-use-equals-default) @@ -2731,6 +2815,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "LINK_LANG_AND_ID", &linkLanguageAndIdNode }, { "LINK_LANGUAGE", &linkLanguageNode }, { "LINK_LIBRARY", &linkLibraryNode }, + { "LINK_GROUP", &linkGroupNode }, { "HOST_LINK", &hostLinkNode }, { "DEVICE_LINK", &deviceLinkNode }, { "SHELL_PATH", &shellPathNode } |