diff options
Diffstat (limited to 'Source/cmGeneratorExpressionNode.cxx')
| -rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 677 |
1 files changed, 669 insertions, 8 deletions
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 396e9c9..45d5a83 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -7,10 +7,12 @@ #include <cerrno> #include <cstdlib> #include <cstring> +#include <functional> #include <map> #include <memory> #include <set> #include <sstream> +#include <unordered_map> #include <utility> #include <cm/iterator> @@ -24,6 +26,7 @@ #include "cmsys/String.h" #include "cmAlgorithms.h" +#include "cmCMakePath.h" #include "cmComputeLinkInformation.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionContext.h" @@ -413,7 +416,7 @@ static const struct TargetExistsNode : public cmGeneratorExpressionNode return std::string(); } - std::string targetName = parameters.front(); + std::string const& targetName = parameters.front(); if (targetName.empty() || !cmGeneratorExpression::IsValidTargetName(targetName)) { reportError(context, content->GetOriginalExpression(), @@ -445,7 +448,7 @@ static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode return std::string(); } - std::string targetName = parameters.front(); + std::string const& targetName = parameters.front(); if (targetName.empty() || !cmGeneratorExpression::IsValidTargetName(targetName)) { reportError(context, content->GetOriginalExpression(), @@ -599,6 +602,455 @@ static const struct UpperCaseNode : public cmGeneratorExpressionNode } } upperCaseNode; +namespace { +template <typename Container> +class Range : public cmRange<typename Container::const_iterator> +{ +private: + using Base = cmRange<typename Container::const_iterator>; + +public: + using const_iterator = typename Container::const_iterator; + using value_type = typename Container::value_type; + using size_type = typename Container::size_type; + using difference_type = typename Container::difference_type; + using const_reference = typename Container::const_reference; + + Range(const Container& container) + : Base(container.begin(), container.end()) + { + } + + const_reference operator[](size_type pos) const + { + return *(this->begin() + pos); + } + + const_reference front() const { return *this->begin(); } + const_reference back() const { return *std::prev(this->end()); } + + Range& advance(difference_type amount) & + { + Base::advance(amount); + return *this; + } + Range advance(difference_type amount) && + { + Base::advance(amount); + return std::move(*this); + } +}; + +using Arguments = Range<std::vector<std::string>>; + +bool CheckPathParametersEx(cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + cm::string_view option, std::size_t count, + int required = 1, bool exactly = true) +{ + if (static_cast<int>(count) < required || + (exactly && static_cast<int>(count) > required)) { + reportError(ctx, cnt->GetOriginalExpression(), + cmStrCat("$<PATH:", option, "> expression requires ", + (exactly ? "exactly" : "at least"), ' ', + (required == 1 ? "one parameter" : "two parameters"), + '.')); + return false; + } + return true; +}; +bool CheckPathParameters(cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + cm::string_view option, const Arguments& args, + int required = 1) +{ + return CheckPathParametersEx(ctx, cnt, option, args.size(), required); +}; +std::string ToString(bool isTrue) +{ + return isTrue ? "1" : "0"; +}; +} + +static const struct PathNode : public cmGeneratorExpressionNode +{ + PathNode() {} // NOLINT(modernize-use-equals-default) + + int NumExpectedParameters() const override { return TwoOrMoreParameters; } + + bool AcceptsArbitraryContentParameter() const override { return true; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + { + static std::unordered_map< + cm::string_view, + std::function<std::string(cmGeneratorExpressionContext*, + const GeneratorExpressionContent*, + Arguments&)>> + pathCommands{ + { "GET_ROOT_NAME"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "GET_ROOT_NAME"_s, args) && + !args.front().empty() + ? cmCMakePath{ args.front() }.GetRootName().String() + : std::string{}; + } }, + { "GET_ROOT_DIRECTORY"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "GET_ROOT_DIRECTORY"_s, + args) && + !args.front().empty() + ? cmCMakePath{ args.front() }.GetRootDirectory().String() + : std::string{}; + } }, + { "GET_ROOT_PATH"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "GET_ROOT_PATH"_s, args) && + !args.front().empty() + ? cmCMakePath{ args.front() }.GetRootPath().String() + : std::string{}; + } }, + { "GET_FILENAME"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "GET_FILENAME"_s, args) && + !args.front().empty() + ? cmCMakePath{ args.front() }.GetFileName().String() + : std::string{}; + } }, + { "GET_EXTENSION"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + bool lastOnly = args.front() == "LAST_ONLY"_s; + if (lastOnly) { + args.advance(1); + } + if (CheckPathParametersEx(ctx, cnt, + lastOnly ? "GET_EXTENSION,LAST_ONLY"_s + : "GET_EXTENSION"_s, + args.size())) { + if (args.front().empty()) { + return std::string{}; + } + return lastOnly + ? cmCMakePath{ args.front() }.GetExtension().String() + : cmCMakePath{ args.front() }.GetWideExtension().String(); + } + return std::string{}; + } }, + { "GET_STEM"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + bool lastOnly = args.front() == "LAST_ONLY"_s; + if (lastOnly) { + args.advance(1); + } + if (CheckPathParametersEx( + ctx, cnt, lastOnly ? "GET_STEM,LAST_ONLY"_s : "GET_STEM"_s, + args.size())) { + if (args.front().empty()) { + return std::string{}; + } + return lastOnly + ? cmCMakePath{ args.front() }.GetStem().String() + : cmCMakePath{ args.front() }.GetNarrowStem().String(); + } + return std::string{}; + } }, + { "GET_RELATIVE_PART"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "GET_RELATIVE_PART"_s, + args) && + !args.front().empty() + ? cmCMakePath{ args.front() }.GetRelativePath().String() + : std::string{}; + } }, + { "GET_PARENT_PATH"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "GET_PARENT_PATH"_s, args) + ? cmCMakePath{ args.front() }.GetParentPath().String() + : std::string{}; + } }, + { "HAS_ROOT_NAME"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "HAS_ROOT_NAME"_s, args) + ? ToString(cmCMakePath{ args.front() }.HasRootName()) + : std::string{ "0" }; + } }, + { "HAS_ROOT_DIRECTORY"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "HAS_ROOT_DIRECTORY"_s, args) + ? ToString(cmCMakePath{ args.front() }.HasRootDirectory()) + : std::string{ "0" }; + } }, + { "HAS_ROOT_PATH"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "HAS_ROOT_PATH"_s, args) + ? ToString(cmCMakePath{ args.front() }.HasRootPath()) + : std::string{ "0" }; + } }, + { "HAS_FILENAME"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "HAS_FILENAME"_s, args) + ? ToString(cmCMakePath{ args.front() }.HasFileName()) + : std::string{ "0" }; + } }, + { "HAS_EXTENSION"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "HAS_EXTENSION"_s, args) && + !args.front().empty() + ? ToString(cmCMakePath{ args.front() }.HasExtension()) + : std::string{ "0" }; + } }, + { "HAS_STEM"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "HAS_STEM"_s, args) + ? ToString(cmCMakePath{ args.front() }.HasStem()) + : std::string{ "0" }; + } }, + { "HAS_RELATIVE_PART"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "HAS_RELATIVE_PART"_s, args) + ? ToString(cmCMakePath{ args.front() }.HasRelativePath()) + : std::string{ "0" }; + } }, + { "HAS_PARENT_PATH"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "HAS_PARENT_PATH"_s, args) + ? ToString(cmCMakePath{ args.front() }.HasParentPath()) + : std::string{ "0" }; + } }, + { "IS_ABSOLUTE"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "IS_ABSOLUTE"_s, args) + ? ToString(cmCMakePath{ args.front() }.IsAbsolute()) + : std::string{ "0" }; + } }, + { "IS_RELATIVE"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "IS_RELATIVE"_s, args) + ? ToString(cmCMakePath{ args.front() }.IsRelative()) + : std::string{ "0" }; + } }, + { "IS_PREFIX"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + bool normalize = args.front() == "NORMALIZE"_s; + if (normalize) { + args.advance(1); + } + if (CheckPathParametersEx(ctx, cnt, + normalize ? "IS_PREFIX,NORMALIZE"_s + : "IS_PREFIX"_s, + args.size(), 2)) { + if (normalize) { + return ToString(cmCMakePath{ args[0] }.Normal().IsPrefix( + cmCMakePath{ args[1] }.Normal())); + } + return ToString( + cmCMakePath{ args[0] }.IsPrefix(cmCMakePath{ args[1] })); + } + return std::string{}; + } }, + { "CMAKE_PATH"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + bool normalize = args.front() == "NORMALIZE"_s; + if (normalize) { + args.advance(1); + } + if (CheckPathParametersEx(ctx, cnt, + normalize ? "CMAKE_PATH,NORMALIZE"_s + : "CMAKE_PATH"_s, + args.size(), 1)) { + auto path = + cmCMakePath{ args.front(), cmCMakePath::auto_format }; + return normalize ? path.Normal().GenericString() + : path.GenericString(); + } + return std::string{}; + } }, + { "APPEND"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + if (CheckPathParametersEx(ctx, cnt, "APPEND"_s, args.size(), 1, + false)) { + cmCMakePath path; + for (const auto& p : args) { + path /= p; + } + return path.String(); + } + return std::string{}; + } }, + { "REMOVE_FILENAME"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "REMOVE_FILENAME"_s, args) && + !args.front().empty() + ? cmCMakePath{ args.front() }.RemoveFileName().String() + : std::string{}; + } }, + { "REPLACE_FILENAME"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "REPLACE_FILENAME"_s, args, 2) + ? cmCMakePath{ args[0] } + .ReplaceFileName(cmCMakePath{ args[1] }) + .String() + : std::string{}; + } }, + { "REMOVE_EXTENSION"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + bool lastOnly = args.front() == "LAST_ONLY"_s; + if (lastOnly) { + args.advance(1); + } + if (CheckPathParametersEx(ctx, cnt, + lastOnly ? "REMOVE_EXTENSION,LAST_ONLY"_s + : "REMOVE_EXTENSION"_s, + args.size())) { + if (args.front().empty()) { + return std::string{}; + } + return lastOnly + ? cmCMakePath{ args.front() }.RemoveExtension().String() + : cmCMakePath{ args.front() }.RemoveWideExtension().String(); + } + return std::string{}; + } }, + { "REPLACE_EXTENSION"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + bool lastOnly = args.front() == "LAST_ONLY"_s; + if (lastOnly) { + args.advance(1); + } + if (CheckPathParametersEx(ctx, cnt, + lastOnly + ? "REPLACE_EXTENSION,LAST_ONLY"_s + : "REPLACE_EXTENSION"_s, + args.size(), 2)) { + if (lastOnly) { + return cmCMakePath{ args[0] } + .ReplaceExtension(cmCMakePath{ args[1] }) + .String(); + } + return cmCMakePath{ args[0] } + .ReplaceWideExtension(cmCMakePath{ args[1] }) + .String(); + } + return std::string{}; + } }, + { "NORMAL_PATH"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "NORMAL_PATH"_s, args) && + !args.front().empty() + ? cmCMakePath{ args.front() }.Normal().String() + : std::string{}; + } }, + { "RELATIVE_PATH"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + return CheckPathParameters(ctx, cnt, "RELATIVE_PATH"_s, args, 2) + ? cmCMakePath{ args[0] }.Relative(args[1]).String() + : std::string{}; + } }, + { "ABSOLUTE_PATH"_s, + [](cmGeneratorExpressionContext* ctx, + const GeneratorExpressionContent* cnt, + Arguments& args) -> std::string { + bool normalize = args.front() == "NORMALIZE"_s; + if (normalize) { + args.advance(1); + } + if (CheckPathParametersEx(ctx, cnt, + normalize ? "ABSOLUTE_PATH,NORMALIZE"_s + : "ABSOLUTE_PATH"_s, + args.size(), 2)) { + auto path = cmCMakePath{ args[0] }.Absolute(args[1]); + return normalize ? path.Normal().String() : path.String(); + } + return std::string{}; + } } + }; + + if (cm::contains(pathCommands, parameters.front())) { + auto args = Arguments{ parameters }.advance(1); + return pathCommands[parameters.front()](context, content, args); + } + + reportError(context, content->GetOriginalExpression(), + cmStrCat(parameters.front(), ": invalid option.")); + return std::string{}; + } +} pathNode; + +static const struct PathEqualNode : public cmGeneratorExpressionNode +{ + PathEqualNode() {} // NOLINT(modernize-use-equals-default) + + int NumExpectedParameters() const override { return 2; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* /*context*/, + const GeneratorExpressionContent* /*content*/, + cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + { + return cmCMakePath{ parameters[0] } == cmCMakePath{ parameters[1] } ? "1" + : "0"; + } +} pathEqualNode; + static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode { MakeCIdentifierNode() {} // NOLINT(modernize-use-equals-default) @@ -1198,6 +1650,162 @@ static const struct LinkLanguageAndIdNode : public cmGeneratorExpressionNode } } linkLanguageAndIdNode; +static const struct LinkLibraryNode : public cmGeneratorExpressionNode +{ + LinkLibraryNode() {} // 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 + { + using ForGenex = cmGeneratorExpressionDAGChecker::ForGenex; + + if (!context->HeadTarget || !dagChecker || + !dagChecker->EvaluatingLinkLibraries(nullptr, + ForGenex::LINK_LIBRARY)) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_LIBRARY:...> may only be used with binary targets " + "to specify link libraries through 'LINK_LIBRARIES', " + "'INTERFACE_LINK_LIBRARIES', and " + "'INTERFACE_LINK_LIBRARIES_DIRECT' properties."); + return std::string(); + } + + std::vector<std::string> list; + cmExpandLists(parameters.begin(), parameters.end(), list); + if (list.empty()) { + reportError( + context, content->GetOriginalExpression(), + "$<LINK_LIBRARY:...> expects a feature name as first argument."); + 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 LL_BEGIN = cmStrCat("<LINK_LIBRARY:", feature, '>'); + const auto LL_END = cmStrCat("</LINK_LIBRARY:", feature, '>'); + + // filter out $<LINK_LIBRARY:..> tags with same feature + // and raise an error for any different feature + cm::erase_if(list, [&](const std::string& item) -> bool { + return item == LL_BEGIN || item == LL_END; + }); + auto it = + std::find_if(list.cbegin() + 1, list.cend(), + [&feature](const std::string& item) -> bool { + return cmHasPrefix(item, "<LINK_LIBRARY:"_s) && + item.substr(14, item.find('>', 14) - 14) != feature; + }); + if (it != list.cend()) { + reportError( + context, content->GetOriginalExpression(), + "$<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); + + return cmJoin(list, ";"_s); + } +} 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 + { + using ForGenex = cmGeneratorExpressionDAGChecker::ForGenex; + + if (!context->HeadTarget || !dagChecker || + !dagChecker->EvaluatingLinkLibraries(nullptr, ForGenex::LINK_GROUP)) { + reportError( + context, content->GetOriginalExpression(), + "$<LINK_GROUP:...> may only be used with binary targets " + "to specify group of link libraries through 'LINK_LIBRARIES', " + "'INTERFACE_LINK_LIBRARIES', and " + "'INTERFACE_LINK_LIBRARIES_DIRECT' properties."); + 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) @@ -1269,7 +1877,8 @@ static std::string getLinkedTargetsContent( { std::string result; if (cmLinkImplementationLibraries const* impl = - target->GetLinkImplementationLibraries(context->Config)) { + target->GetLinkImplementationLibraries( + context->Config, cmGeneratorTarget::LinkInterfaceFor::Usage)) { for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target) { // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our @@ -1612,7 +2221,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - std::string tgtName = parameters.front(); + std::string const& tgtName = parameters.front(); cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName); if (!gt) { std::ostringstream e; @@ -1638,7 +2247,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode { std::string reason; if (!context->EvaluateForBuildsystem && - !gg->HasKnownObjectFileLocation(&reason)) { + !gt->Target->HasKnownObjectFileLocation(&reason)) { std::ostringstream e; e << "The evaluation of the TARGET_OBJECTS generator expression " "is only suitable for consumption by CMake (limited" @@ -1700,7 +2309,7 @@ static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - std::string tgtName = parameters.front(); + std::string const& tgtName = parameters.front(); cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName); if (!gt) { std::ostringstream e; @@ -1951,6 +2560,7 @@ class ArtifactPathTag; class ArtifactPdbTag; class ArtifactSonameTag; class ArtifactBundleDirTag; +class ArtifactBundleDirNameTag; class ArtifactBundleContentDirTag; template <typename ArtifactT, typename ComponentT> @@ -2011,6 +2621,12 @@ struct TargetFilesystemArtifactDependency<ArtifactBundleDirTag, { }; template <> +struct TargetFilesystemArtifactDependency<ArtifactBundleDirNameTag, + ArtifactPathTag> + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; +template <> struct TargetFilesystemArtifactDependency<ArtifactBundleContentDirTag, ArtifactPathTag> : TargetFilesystemArtifactDependencyCMP0112 @@ -2138,6 +2754,41 @@ struct TargetFilesystemArtifactResultCreator<ArtifactBundleDirTag> }; template <> +struct TargetFilesystemArtifactResultCreator<ArtifactBundleDirNameTag> +{ + static std::string Create(cmGeneratorTarget* target, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content) + { + if (target->IsImported()) { + ::reportError( + context, content->GetOriginalExpression(), + "TARGET_BUNDLE_DIR_NAME not allowed for IMPORTED targets."); + return std::string(); + } + if (!target->IsBundleOnApple()) { + ::reportError( + context, content->GetOriginalExpression(), + "TARGET_BUNDLE_DIR_NAME is allowed only for Bundle targets."); + return std::string(); + } + + auto level = cmGeneratorTarget::BundleDirLevel; + auto config = context->Config; + if (target->IsAppBundleOnApple()) { + return target->GetAppBundleDirectory(config, level); + } + if (target->IsFrameworkOnApple()) { + return target->GetFrameworkDirectory(config, level); + } + if (target->IsCFBundleOnApple()) { + return target->GetCFBundleDirectory(config, level); + } + return std::string(); + } +}; + +template <> struct TargetFilesystemArtifactResultCreator<ArtifactBundleContentDirTag> { static std::string Create(cmGeneratorTarget* target, @@ -2217,7 +2868,7 @@ protected: cmGeneratorExpressionDAGChecker* dagChecker) const { // Lookup the referenced target. - std::string name = parameters.front(); + std::string const& name = parameters.front(); if (!cmGeneratorExpression::IsValidTargetName(name)) { ::reportError(context, content->GetOriginalExpression(), @@ -2270,7 +2921,8 @@ struct TargetFilesystemArtifact : public TargetArtifactBase return std::string(); } // Not a dependent target if we are querying for ArtifactDirTag, - // ArtifactNameTag, ArtifactBundleDirTag, and ArtifactBundleContentDirTag + // ArtifactNameTag, ArtifactBundleDirTag, ArtifactBundleDirNameTag, + // and ArtifactBundleContentDirTag TargetFilesystemArtifactDependency<ArtifactT, ComponentT>::AddDependency( target, context); @@ -2311,6 +2963,10 @@ static const TargetFilesystemArtifactNodeGroup<ArtifactPdbTag> static const TargetFilesystemArtifact<ArtifactBundleDirTag, ArtifactPathTag> targetBundleDirNode; +static const TargetFilesystemArtifact<ArtifactBundleDirNameTag, + ArtifactNameTag> + targetBundleDirNameNode; + static const TargetFilesystemArtifact<ArtifactBundleContentDirTag, ArtifactPathTag> targetBundleContentDirNode; @@ -2636,6 +3292,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "TARGET_SONAME_FILE_DIR", &targetSoNameNodeGroup.FileDir }, { "TARGET_PDB_FILE_DIR", &targetPdbNodeGroup.FileDir }, { "TARGET_BUNDLE_DIR", &targetBundleDirNode }, + { "TARGET_BUNDLE_DIR_NAME", &targetBundleDirNameNode }, { "TARGET_BUNDLE_CONTENT_DIR", &targetBundleContentDirNode }, { "STREQUAL", &strEqualNode }, { "EQUAL", &equalNode }, @@ -2644,6 +3301,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "REMOVE_DUPLICATES", &removeDuplicatesNode }, { "LOWER_CASE", &lowerCaseNode }, { "UPPER_CASE", &upperCaseNode }, + { "PATH", &pathNode }, + { "PATH_EQUAL", &pathEqualNode }, { "MAKE_C_IDENTIFIER", &makeCIdentifierNode }, { "BOOL", &boolNode }, { "IF", &ifNode }, @@ -2668,6 +3327,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "COMPILE_LANGUAGE", &languageNode }, { "LINK_LANG_AND_ID", &linkLanguageAndIdNode }, { "LINK_LANGUAGE", &linkLanguageNode }, + { "LINK_LIBRARY", &linkLibraryNode }, + { "LINK_GROUP", &linkGroupNode }, { "HOST_LINK", &hostLinkNode }, { "DEVICE_LINK", &deviceLinkNode }, { "SHELL_PATH", &shellPathNode } |
