diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmExportBuildFileGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 19 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.h | 4 | ||||
-rw-r--r-- | Source/cmExportInstallFileGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionDAGChecker.cxx | 5 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 12 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 2 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 38 | ||||
-rw-r--r-- | Source/cmGeneratorTarget_Link.cxx | 17 | ||||
-rw-r--r-- | Source/cmGeneratorTarget_TransitiveProperty.cxx | 90 |
10 files changed, 181 insertions, 10 deletions
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 2345d64..d877d76 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -152,6 +152,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) gte, cmGeneratorExpression::BuildInterface, properties); } this->PopulateCompatibleInterfaceProperties(gte, properties); + this->PopulateCustomTransitiveInterfaceProperties( + gte, cmGeneratorExpression::BuildInterface, properties); this->GenerateInterfaceProperties(gte, os, properties); diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 9bd7f49..a7d0d7e 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -604,6 +604,25 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( } } +void cmExportFileGenerator::PopulateCustomTransitiveInterfaceProperties( + cmGeneratorTarget const* target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap& properties) +{ + this->PopulateInterfaceProperty("TRANSITIVE_COMPILE_PROPERTIES", target, + properties); + std::set<std::string> ifaceProperties; + for (std::string const& config : this->Configurations) { + for (auto const& i : target->GetCustomTransitiveProperties( + config, cmGeneratorTarget::PropertyFor::Interface)) { + ifaceProperties.emplace(i.second.InterfaceName); + } + } + for (std::string const& ip : ifaceProperties) { + this->PopulateInterfaceProperty(ip, target, preprocessRule, properties); + } +} + void cmExportFileGenerator::GenerateInterfaceProperties( const cmGeneratorTarget* target, std::ostream& os, const ImportPropertyMap& properties) diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index f619576..f275a12 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -145,6 +145,10 @@ protected: ImportPropertyMap& properties); void PopulateCompatibleInterfaceProperties(cmGeneratorTarget const* target, ImportPropertyMap& properties); + void PopulateCustomTransitiveInterfaceProperties( + cmGeneratorTarget const* target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap& properties); virtual void GenerateInterfaceProperties( cmGeneratorTarget const* target, std::ostream& os, const ImportPropertyMap& properties); diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 5c95ecd..f5f22ef 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -160,6 +160,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) properties); this->PopulateCompatibleInterfaceProperties(gt, properties); + this->PopulateCustomTransitiveInterfaceProperties( + gt, cmGeneratorExpression::InstallInterface, properties); this->GenerateInterfaceProperties(gt, os, properties); diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 1ae422e..aad25f0 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -40,12 +40,13 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( , Content(content) , Backtrace(std::move(backtrace)) { - static_cast<void>(contextConfig); if (parent) { this->TopIsTransitiveProperty = parent->TopIsTransitiveProperty; } else { this->TopIsTransitiveProperty = - this->Target->IsTransitiveProperty(this->Property, contextLG) + this->Target + ->IsTransitiveProperty(this->Property, contextLG, contextConfig, + this->EvaluatingLinkLibraries()) .has_value(); } diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index e07f26d..01cd18d 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -2873,19 +2873,22 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return target->GetLinkerLanguage(context->Config); } + bool const evaluatingLinkLibraries = + dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries(); + std::string interfacePropertyName; bool isInterfaceProperty = false; cmGeneratorTarget::UseTo usage = cmGeneratorTarget::UseTo::Compile; if (cm::optional<cmGeneratorTarget::TransitiveProperty> transitiveProp = - target->IsTransitiveProperty(propertyName, context->LG)) { + target->IsTransitiveProperty(propertyName, context->LG, + context->Config, + evaluatingLinkLibraries)) { interfacePropertyName = std::string(transitiveProp->InterfaceName); isInterfaceProperty = transitiveProp->InterfaceName == propertyName; usage = transitiveProp->Usage; } - bool evaluatingLinkLibraries = false; - if (dagCheckerParent) { // This $<TARGET_PROPERTY:...> node has been reached while evaluating // another target property value. Check that the outermost evaluation @@ -2894,8 +2897,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode dagCheckerParent->EvaluatingPICExpression() || dagCheckerParent->EvaluatingLinkerLauncher()) { // No check required. - } else if (dagCheckerParent->EvaluatingLinkLibraries()) { - evaluatingLinkLibraries = true; + } else if (evaluatingLinkLibraries) { if (!interfacePropertyName.empty()) { reportError( context, content->GetOriginalExpression(), diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 55f34f8..aa3e36f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -518,6 +518,8 @@ void cmGeneratorTarget::ClearSourcesCache() this->IncludeDirectoriesCache.clear(); this->CompileOptionsCache.clear(); this->CompileDefinitionsCache.clear(); + this->CustomTransitiveBuildPropertiesMap.clear(); + this->CustomTransitiveInterfacePropertiesMap.clear(); this->PrecompileHeadersCache.clear(); this->LinkOptionsCache.clear(); this->LinkDirectoriesCache.clear(); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 3090a5b..8f27a91 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -907,7 +907,8 @@ public: BuiltinTransitiveProperties; cm::optional<TransitiveProperty> IsTransitiveProperty( - cm::string_view prop, cmLocalGenerator const* lg) const; + cm::string_view prop, cmLocalGenerator const* lg, + std::string const& config, bool evaluatingLinkLibraries) const; bool HaveInstallTreeRPATH(const std::string& config) const; @@ -989,6 +990,30 @@ public: bool DiscoverSyntheticTargets(cmSyntheticTargetCache& cache, std::string const& config); + class CustomTransitiveProperty : public TransitiveProperty + { + std::unique_ptr<std::string> InterfaceNameBuf; + CustomTransitiveProperty(std::unique_ptr<std::string> interfaceNameBuf, + UseTo usage); + + public: + CustomTransitiveProperty(std::string interfaceName, UseTo usage); + }; + struct CustomTransitiveProperties + : public std::map<std::string, CustomTransitiveProperty> + { + void Add(cmValue props, UseTo usage); + }; + + enum class PropertyFor + { + Build, + Interface, + }; + + CustomTransitiveProperties const& GetCustomTransitiveProperties( + std::string const& config, PropertyFor propertyFor) const; + private: void AddSourceCommon(const std::string& src, bool before = false); @@ -1056,6 +1081,11 @@ private: std::string const& base, std::string const& suffix, std::string const& name, cmValue version) const; + mutable std::map<std::string, CustomTransitiveProperties> + CustomTransitiveBuildPropertiesMap; + mutable std::map<std::string, CustomTransitiveProperties> + CustomTransitiveInterfacePropertiesMap; + struct CompatibleInterfacesBase { std::set<std::string> PropsBool; @@ -1306,6 +1336,12 @@ private: void ComputeLinkInterfaceRuntimeLibraries( const std::string& config, cmOptionalLinkInterface& iface) const; + // If this method is made public, or call sites are added outside of + // methods computing cached members, add dedicated caching members. + std::vector<cmGeneratorTarget const*> GetLinkInterfaceClosure( + std::string const& config, cmGeneratorTarget const* headTarget, + UseTo usage) const; + public: const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure( const std::string& config, UseTo usage) const; diff --git a/Source/cmGeneratorTarget_Link.cxx b/Source/cmGeneratorTarget_Link.cxx index 7c6f7b5..0799429 100644 --- a/Source/cmGeneratorTarget_Link.cxx +++ b/Source/cmGeneratorTarget_Link.cxx @@ -282,6 +282,23 @@ static void processILibs(const std::string& config, } } +std::vector<cmGeneratorTarget const*> +cmGeneratorTarget::GetLinkInterfaceClosure(std::string const& config, + cmGeneratorTarget const* headTarget, + UseTo usage) const +{ + cmGlobalGenerator* gg = this->GetLocalGenerator()->GetGlobalGenerator(); + std::vector<cmGeneratorTarget const*> tgts; + std::set<cmGeneratorTarget const*> emitted; + if (cmLinkInterfaceLibraries const* iface = + this->GetLinkInterfaceLibraries(config, headTarget, usage)) { + for (cmLinkItem const& lib : iface->Libraries) { + processILibs(config, headTarget, lib, gg, tgts, emitted, usage); + } + } + return tgts; +} + const std::vector<const cmGeneratorTarget*>& cmGeneratorTarget::GetLinkImplementationClosure(const std::string& config, UseTo usage) const diff --git a/Source/cmGeneratorTarget_TransitiveProperty.cxx b/Source/cmGeneratorTarget_TransitiveProperty.cxx index 2cd3665..d63d11c 100644 --- a/Source/cmGeneratorTarget_TransitiveProperty.cxx +++ b/Source/cmGeneratorTarget_TransitiveProperty.cxx @@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include <cm/memory> #include <cm/optional> #include <cm/string_view> #include <cmext/string_view> @@ -19,6 +20,7 @@ #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorExpressionNode.h" #include "cmLinkItem.h" +#include "cmList.h" #include "cmLocalGenerator.h" #include "cmPolicies.h" #include "cmStringAlgorithms.h" @@ -176,11 +178,16 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( cm::optional<cmGeneratorTarget::TransitiveProperty> cmGeneratorTarget::IsTransitiveProperty(cm::string_view prop, - cmLocalGenerator const* lg) const + cmLocalGenerator const* lg, + std::string const& config, + bool evaluatingLinkLibraries) const { cm::optional<TransitiveProperty> result; static const cm::string_view kINTERFACE_ = "INTERFACE_"_s; - if (cmHasPrefix(prop, kINTERFACE_)) { + PropertyFor const propertyFor = cmHasPrefix(prop, kINTERFACE_) + ? PropertyFor::Interface + : PropertyFor::Build; + if (propertyFor == PropertyFor::Interface) { prop = prop.substr(kINTERFACE_.length()); } auto i = BuiltinTransitiveProperties.find(prop); @@ -202,6 +209,85 @@ cmGeneratorTarget::IsTransitiveProperty(cm::string_view prop, result = TransitiveProperty{ "INTERFACE_COMPILE_DEFINITIONS"_s, UseTo::Compile }; } + } else if (!evaluatingLinkLibraries) { + // Honor TRANSITIVE_COMPILE_PROPERTIES + // from the link closure when we are not evaluating the closure itself. + CustomTransitiveProperties const& ctp = + this->GetCustomTransitiveProperties(config, propertyFor); + auto ci = ctp.find(std::string(prop)); + if (ci != ctp.end()) { + result = ci->second; + } } return result; } + +cmGeneratorTarget::CustomTransitiveProperty::CustomTransitiveProperty( + std::string interfaceName, UseTo usage) + : CustomTransitiveProperty( + cm::make_unique<std::string>(std::move(interfaceName)), usage) +{ +} +cmGeneratorTarget::CustomTransitiveProperty::CustomTransitiveProperty( + std::unique_ptr<std::string> interfaceNameBuf, UseTo usage) + : TransitiveProperty{ *interfaceNameBuf, usage } + , InterfaceNameBuf(std::move(interfaceNameBuf)) +{ +} + +void cmGeneratorTarget::CustomTransitiveProperties::Add(cmValue props, + UseTo usage) +{ + if (props) { + cmList propsList(*props); + for (std::string p : propsList) { + std::string ip; + static const cm::string_view kINTERFACE_ = "INTERFACE_"_s; + if (cmHasPrefix(p, kINTERFACE_)) { + ip = std::move(p); + p = ip.substr(kINTERFACE_.length()); + } else { + ip = cmStrCat(kINTERFACE_, p); + } + this->emplace(std::move(p), + CustomTransitiveProperty(std::move(ip), usage)); + } + } +} + +cmGeneratorTarget::CustomTransitiveProperties const& +cmGeneratorTarget::GetCustomTransitiveProperties(std::string const& config, + PropertyFor propertyFor) const +{ + std::map<std::string, CustomTransitiveProperties>& ctpm = + propertyFor == PropertyFor::Build + ? this->CustomTransitiveBuildPropertiesMap + : this->CustomTransitiveInterfacePropertiesMap; + auto i = ctpm.find(config); + if (i == ctpm.end()) { + CustomTransitiveProperties ctp; + auto addTransitiveProperties = [this, &config, propertyFor, + &ctp](std::string const& tp, UseTo usage) { + // Add transitive properties named by the target itself. + ctp.Add(this->GetProperty(tp), usage); + // Add transitive properties named by the target's link dependencies. + if (propertyFor == PropertyFor::Build) { + for (cmGeneratorTarget const* gt : + this->GetLinkImplementationClosure(config, usage)) { + ctp.Add(gt->GetProperty(tp), usage); + } + } else { + // The set of custom transitive INTERFACE_ properties does not + // depend on the consumer. Use the target as its own head. + cmGeneratorTarget const* headTarget = this; + for (cmGeneratorTarget const* gt : + this->GetLinkInterfaceClosure(config, headTarget, usage)) { + ctp.Add(gt->GetProperty(tp), usage); + } + } + }; + addTransitiveProperties("TRANSITIVE_COMPILE_PROPERTIES", UseTo::Compile); + i = ctpm.emplace(config, std::move(ctp)).first; + } + return i->second; +} |