diff options
Diffstat (limited to 'Source')
21 files changed, 284 insertions, 77 deletions
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index fbf39e2..9f25904 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -500,9 +500,9 @@ std::string cmCommonTargetGenerator::GetLinkerLauncher( std::string propName = lang + "_LINKER_LAUNCHER"; cmValue launcherProp = this->GeneratorTarget->GetProperty(propName); if (cmNonempty(launcherProp)) { - cmGeneratorExpressionDAGChecker dagChecker(this->GeneratorTarget, propName, - nullptr, nullptr, - this->LocalCommonGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + this->GeneratorTarget, propName, nullptr, nullptr, + this->LocalCommonGenerator, config); std::string evaluatedLinklauncher = cmGeneratorExpression::Evaluate( *launcherProp, this->LocalCommonGenerator, config, this->GeneratorTarget, &dagChecker, this->GeneratorTarget, lang); diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index db0d71a..cc323f4 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -581,7 +581,8 @@ cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target, "LINK_LIBRARY_OVERRIDE", nullptr, nullptr, - this->Target->GetLocalGenerator() + this->Target->GetLocalGenerator(), + config }; auto overrideFeature = cmGeneratorExpression::Evaluate( *feature, this->Target->GetLocalGenerator(), config, @@ -599,7 +600,8 @@ cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target, "LINK_LIBRARY_OVERRIDE", nullptr, nullptr, - target->GetLocalGenerator() }; + target->GetLocalGenerator(), + config }; auto overrideValue = cmGeneratorExpression::Evaluate( *linkLibraryOverride, target->GetLocalGenerator(), config, target, &dag, target, linkLanguage); 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..a5348f2 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -604,6 +604,27 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( } } +void cmExportFileGenerator::PopulateCustomTransitiveInterfaceProperties( + cmGeneratorTarget const* target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap& properties) +{ + this->PopulateInterfaceProperty("TRANSITIVE_COMPILE_PROPERTIES", target, + properties); + this->PopulateInterfaceProperty("TRANSITIVE_LINK_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/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 4c41ff5..7ce5cd9 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -76,10 +76,12 @@ std::string cmExportTryCompileFileGenerator::FindTargets( // To please constraint checks of DAGChecker, this property must have // LINK_OPTIONS property as parent parentDagChecker = cm::make_unique<cmGeneratorExpressionDAGChecker>( - tgt, "LINK_OPTIONS", nullptr, nullptr, tgt->GetLocalGenerator()); + tgt, "LINK_OPTIONS", nullptr, nullptr, tgt->GetLocalGenerator(), + this->Config); } cmGeneratorExpressionDAGChecker dagChecker( - tgt, propName, nullptr, parentDagChecker.get(), tgt->GetLocalGenerator()); + tgt, propName, nullptr, parentDagChecker.get(), tgt->GetLocalGenerator(), + this->Config); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*prop); diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 0583fd5..8e590fa 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -425,7 +425,7 @@ const std::string& cmGeneratorExpressionInterpreter::Evaluate( cmGeneratorExpressionDAGChecker dagChecker( this->HeadTarget, property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, nullptr, - nullptr, this->LocalGenerator); + nullptr, this->LocalGenerator, this->Config); return this->CompiledGeneratorExpression->Evaluate( this->LocalGenerator, this->Config, this->HeadTarget, &dagChecker, nullptr, diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index bb1f4b4..aad25f0 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -20,17 +20,19 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( cmGeneratorTarget const* target, std::string property, const GeneratorExpressionContent* content, - cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG) + cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG, + std::string const& contextConfig) : cmGeneratorExpressionDAGChecker(cmListFileBacktrace(), target, std::move(property), content, parent, - contextLG) + contextLG, contextConfig) { } cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( cmListFileBacktrace backtrace, cmGeneratorTarget const* target, std::string property, const GeneratorExpressionContent* content, - cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG) + cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG, + std::string const& contextConfig) : Parent(parent) , Top(parent ? parent->Top : this) , Target(target) @@ -42,7 +44,9 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( 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/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index b230188..8b0eea7 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -22,12 +22,14 @@ struct cmGeneratorExpressionDAGChecker std::string property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent, - cmLocalGenerator const* contextLG); + cmLocalGenerator const* contextLG, + std::string const& contextConfig); cmGeneratorExpressionDAGChecker(cmGeneratorTarget const* target, std::string property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent, - cmLocalGenerator const* contextLG); + cmLocalGenerator const* contextLG, + std::string const& contextConfig); enum Result { diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 5945e41..01cd18d 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -488,7 +488,7 @@ protected: cmGeneratorExpressionDAGChecker dagChecker( context->Backtrace, context->HeadTarget, genexOperator + ":" + expression, content, dagCheckerParent, - context->LG); + context->LG, context->Config); switch (dagChecker.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: { @@ -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(), @@ -2915,9 +2917,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode dagCheckerParent, usage)); } - cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, target, - propertyName, content, - dagCheckerParent, context->LG); + cmGeneratorExpressionDAGChecker dagChecker( + context->Backtrace, target, propertyName, content, dagCheckerParent, + context->LG, context->Config); switch (dagChecker.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ce53316..aa3e36f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -511,11 +511,15 @@ void cmGeneratorTarget::ClearSourcesCache() this->SourcesAreContextDependent = Tribool::Indeterminate; this->Objects.clear(); this->VisitedConfigsForObjects.clear(); + this->LinkImplClosureForLinkMap.clear(); + this->LinkImplClosureForUsageMap.clear(); this->LinkImplMap.clear(); this->LinkImplUsageRequirementsOnlyMap.clear(); this->IncludeDirectoriesCache.clear(); this->CompileOptionsCache.clear(); this->CompileDefinitionsCache.clear(); + this->CustomTransitiveBuildPropertiesMap.clear(); + this->CustomTransitiveInterfacePropertiesMap.clear(); this->PrecompileHeadersCache.clear(); this->LinkOptionsCache.clear(); this->LinkDirectoriesCache.clear(); @@ -707,8 +711,8 @@ std::string cmGeneratorTarget::GetLinkerTypeProperty( std::string propName{ "LINKER_TYPE" }; auto linkerType = this->GetProperty(propName); if (!linkerType.IsEmpty()) { - cmGeneratorExpressionDAGChecker dagChecker(this, propName, nullptr, - nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + this, propName, nullptr, nullptr, this->LocalGenerator, config); auto ltype = cmGeneratorExpression::Evaluate(*linkerType, this->GetLocalGenerator(), config, this, &dagChecker, this, lang); @@ -1174,7 +1178,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( if (iter == this->SystemIncludesCache.end()) { cmGeneratorExpressionDAGChecker dagChecker( this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr, - this->LocalGenerator); + this->LocalGenerator, config); bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED"); @@ -1186,7 +1190,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( } std::vector<cmGeneratorTarget const*> const& deps = - this->GetLinkImplementationClosure(config); + this->GetLinkImplementationClosure(config, UseTo::Compile); for (cmGeneratorTarget const* dep : deps) { handleSystemIncludesDep(this->LocalGenerator, dep, config, this, &dagChecker, result, excludeImported, language); @@ -1934,8 +1938,8 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result, return; } - cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr, - nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + this, "AUTOUIC_OPTIONS", nullptr, nullptr, this->LocalGenerator, config); cmExpandList(cmGeneratorExpression::Evaluate(prop, this->LocalGenerator, config, this, &dagChecker), result); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 51f112e..8f27a91 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -892,6 +892,13 @@ public: struct TransitiveProperty { +#if defined(__SUNPRO_CC) || (defined(__ibmxl__) && defined(__clang__)) + TransitiveProperty(cm::string_view interfaceName, UseTo usage) + : InterfaceName(interfaceName) + , Usage(usage) + { + } +#endif cm::string_view InterfaceName; UseTo Usage; }; @@ -900,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; @@ -982,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); @@ -1049,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; @@ -1080,7 +1117,8 @@ private: { bool Done = false; }; - mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap; + mutable std::map<std::string, LinkImplClosure> LinkImplClosureForLinkMap; + mutable std::map<std::string, LinkImplClosure> LinkImplClosureForUsageMap; using LinkInterfaceMapType = std::map<std::string, cmHeadToLinkInterfaceMap>; mutable LinkInterfaceMapType LinkInterfaceMap; @@ -1298,9 +1336,15 @@ 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) const; + const std::string& config, UseTo usage) const; mutable std::map<std::string, std::string> MaxLanguageStandards; std::map<std::string, std::string> const& GetMaxLanguageStandards() const diff --git a/Source/cmGeneratorTarget_CompatibleInterface.cxx b/Source/cmGeneratorTarget_CompatibleInterface.cxx index b6eb373..3af205e 100644 --- a/Source/cmGeneratorTarget_CompatibleInterface.cxx +++ b/Source/cmGeneratorTarget_CompatibleInterface.cxx @@ -31,6 +31,10 @@ #include "cmSystemTools.h" #include "cmValue.h" +namespace { +using UseTo = cmGeneratorTarget::UseTo; +} + const cmGeneratorTarget::CompatibleInterfacesBase& cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const { @@ -41,7 +45,7 @@ cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const compat.PropsBool.insert("POSITION_INDEPENDENT_CODE"); compat.PropsString.insert("AUTOUIC_OPTIONS"); std::vector<cmGeneratorTarget const*> const& deps = - this->GetLinkImplementationClosure(config); + this->GetLinkImplementationClosure(config, UseTo::Compile); for (cmGeneratorTarget const* li : deps) { #define CM_READ_COMPATIBLE_INTERFACE(X, x) \ if (cmValue prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \ @@ -573,7 +577,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet)); std::vector<cmGeneratorTarget const*> const& deps = - tgt->GetLinkImplementationClosure(config); + tgt->GetLinkImplementationClosure(config, UseTo::Compile); if (deps.empty()) { return propContent; diff --git a/Source/cmGeneratorTarget_IncludeDirectories.cxx b/Source/cmGeneratorTarget_IncludeDirectories.cxx index eaa3959..2b45e1c 100644 --- a/Source/cmGeneratorTarget_IncludeDirectories.cxx +++ b/Source/cmGeneratorTarget_IncludeDirectories.cxx @@ -48,8 +48,8 @@ std::string AddLangSpecificInterfaceIncludeDirectories( cmGeneratorExpressionDAGChecker* context) { cmGeneratorExpressionDAGChecker dag{ - target->GetBacktrace(), target, propertyName, nullptr, context, - target->GetLocalGenerator() + target->GetBacktrace(), target, propertyName, nullptr, context, + target->GetLocalGenerator(), config }; switch (dag.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: @@ -101,8 +101,8 @@ void AddLangSpecificImplicitIncludeDirectories( if (const auto* libraries = target->GetLinkImplementationLibraries(config, UseTo::Compile)) { cmGeneratorExpressionDAGChecker dag{ - target->GetBacktrace(), target, propertyName, nullptr, nullptr, - target->GetLocalGenerator() + target->GetBacktrace(), target, propertyName, nullptr, nullptr, + target->GetLocalGenerator(), config }; for (const cmLinkImplItem& library : libraries->Libraries) { @@ -254,8 +254,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( std::vector<BT<std::string>> includes; std::unordered_set<std::string> uniqueIncludes; - cmGeneratorExpressionDAGChecker dagChecker( - this, "INCLUDE_DIRECTORIES", nullptr, nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES", + nullptr, nullptr, + this->LocalGenerator, config); cmList debugProperties{ this->Makefile->GetDefinition( "CMAKE_DEBUG_TARGET_PROPERTIES") }; diff --git a/Source/cmGeneratorTarget_Link.cxx b/Source/cmGeneratorTarget_Link.cxx index 3ab36b6..0799429 100644 --- a/Source/cmGeneratorTarget_Link.cxx +++ b/Source/cmGeneratorTarget_Link.cxx @@ -268,23 +268,40 @@ static void processILibs(const std::string& config, cmGeneratorTarget const* headTarget, cmLinkItem const& item, cmGlobalGenerator* gg, std::vector<cmGeneratorTarget const*>& tgts, - std::set<cmGeneratorTarget const*>& emitted) + std::set<cmGeneratorTarget const*>& emitted, + UseTo usage) { if (item.Target && emitted.insert(item.Target).second) { tgts.push_back(item.Target); if (cmLinkInterfaceLibraries const* iface = - item.Target->GetLinkInterfaceLibraries(config, headTarget, - UseTo::Compile)) { + item.Target->GetLinkInterfaceLibraries(config, headTarget, usage)) { for (cmLinkItem const& lib : iface->Libraries) { - processILibs(config, headTarget, lib, gg, tgts, emitted); + processILibs(config, headTarget, lib, gg, tgts, emitted, usage); } } } } +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) const +cmGeneratorTarget::GetLinkImplementationClosure(const std::string& config, + UseTo usage) const { // There is no link implementation for targets that cannot compile sources. if (!this->CanCompileSources()) { @@ -292,18 +309,21 @@ cmGeneratorTarget::GetLinkImplementationClosure( return empty; } - LinkImplClosure& tgts = this->LinkImplClosureMap[config]; + LinkImplClosure& tgts = + (usage == UseTo::Compile ? this->LinkImplClosureForUsageMap[config] + : this->LinkImplClosureForLinkMap[config]); if (!tgts.Done) { tgts.Done = true; std::set<cmGeneratorTarget const*> emitted; cmLinkImplementationLibraries const* impl = - this->GetLinkImplementationLibraries(config, UseTo::Compile); + this->GetLinkImplementationLibraries(config, usage); assert(impl); for (cmLinkImplItem const& lib : impl->Libraries) { processILibs(config, this, lib, - this->LocalGenerator->GetGlobalGenerator(), tgts, emitted); + this->LocalGenerator->GetGlobalGenerator(), tgts, emitted, + usage); } } return tgts; @@ -518,7 +538,7 @@ void cmGeneratorTarget::ExpandLinkItems(std::string const& prop, } // Keep this logic in sync with ComputeLinkImplementationLibraries. cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr, - this->LocalGenerator); + this->LocalGenerator, config); // The $<LINK_ONLY> expression may be in a link interface to specify // private link dependencies that are otherwise excluded from usage // requirements. @@ -1268,8 +1288,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( // Collect libraries directly linked in this configuration. for (auto const& entry : entryRange) { // Keep this logic in sync with ExpandLinkItems. - cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, - nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + this, "LINK_LIBRARIES", nullptr, nullptr, this->LocalGenerator, config); // The $<LINK_ONLY> expression may be used to specify link dependencies // that are otherwise excluded from usage requirements. if (usage == UseTo::Compile) { diff --git a/Source/cmGeneratorTarget_LinkDirectories.cxx b/Source/cmGeneratorTarget_LinkDirectories.cxx index 0955dfb..bd89497 100644 --- a/Source/cmGeneratorTarget_LinkDirectories.cxx +++ b/Source/cmGeneratorTarget_LinkDirectories.cxx @@ -125,8 +125,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories( std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueDirectories; - cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr, - nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + this, "LINK_DIRECTORIES", nullptr, nullptr, this->LocalGenerator, config); cmList debugProperties{ this->Makefile->GetDefinition( "CMAKE_DEBUG_TARGET_PROPERTIES") }; diff --git a/Source/cmGeneratorTarget_Options.cxx b/Source/cmGeneratorTarget_Options.cxx index 05f325d..f77ef72 100644 --- a/Source/cmGeneratorTarget_Options.cxx +++ b/Source/cmGeneratorTarget_Options.cxx @@ -217,8 +217,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions( std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr, - nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + this, "COMPILE_OPTIONS", nullptr, nullptr, this->LocalGenerator, config); cmList debugProperties{ this->Makefile->GetDefinition( "CMAKE_DEBUG_TARGET_PROPERTIES") }; @@ -258,8 +258,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures( std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueFeatures; - cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr, - nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + this, "COMPILE_FEATURES", nullptr, nullptr, this->LocalGenerator, config); cmList debugProperties{ this->Makefile->GetDefinition( "CMAKE_DEBUG_TARGET_PROPERTIES") }; @@ -308,8 +308,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( std::vector<BT<std::string>> list; std::unordered_set<std::string> uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker( - this, "COMPILE_DEFINITIONS", nullptr, nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS", + nullptr, nullptr, + this->LocalGenerator, config); cmList debugProperties{ this->Makefile->GetDefinition( "CMAKE_DEBUG_TARGET_PROPERTIES") }; @@ -372,8 +373,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders( } std::unordered_set<std::string> uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker( - this, "PRECOMPILE_HEADERS", nullptr, nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker(this, "PRECOMPILE_HEADERS", + nullptr, nullptr, + this->LocalGenerator, config); cmList debugProperties{ this->Makefile->GetDefinition( "CMAKE_DEBUG_TARGET_PROPERTIES") }; @@ -430,8 +432,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr, - nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + this, "LINK_OPTIONS", nullptr, nullptr, this->LocalGenerator, config); cmList debugProperties{ this->Makefile->GetDefinition( "CMAKE_DEBUG_TARGET_PROPERTIES") }; @@ -599,8 +601,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions( std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker( - this, "STATIC_LIBRARY_OPTIONS", nullptr, nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS", + nullptr, nullptr, + this->LocalGenerator, config); EvaluatedTargetPropertyEntries entries; if (cmValue linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { @@ -631,8 +634,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends( { std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr, - nullptr, this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + this, "LINK_DEPENDS", nullptr, nullptr, this->LocalGenerator, config); EvaluatedTargetPropertyEntries entries; if (cmValue linkDepends = this->GetProperty("LINK_DEPENDS")) { diff --git a/Source/cmGeneratorTarget_Sources.cxx b/Source/cmGeneratorTarget_Sources.cxx index de18df5..94e8897 100644 --- a/Source/cmGeneratorTarget_Sources.cxx +++ b/Source/cmGeneratorTarget_Sources.cxx @@ -265,7 +265,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( } cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr, nullptr, - this->LocalGenerator); + this->LocalGenerator, config); EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries( this, config, std::string(), &dagChecker, this->SourceEntries); diff --git a/Source/cmGeneratorTarget_TransitiveProperty.cxx b/Source/cmGeneratorTarget_TransitiveProperty.cxx index f5d9a1a..ac929eb 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" @@ -107,9 +109,9 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( // Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled. This is // a subset of TargetPropertyNode::Evaluate without stringify/parse steps // but sufficient for transitive interface properties. - cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop, - nullptr, dagCheckerParent, - this->LocalGenerator); + cmGeneratorExpressionDAGChecker dagChecker( + context->Backtrace, this, prop, nullptr, dagCheckerParent, + this->LocalGenerator, context->Config); switch (dagChecker.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: dagChecker.ReportError( @@ -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,86 @@ cmGeneratorTarget::IsTransitiveProperty(cm::string_view prop, result = TransitiveProperty{ "INTERFACE_COMPILE_DEFINITIONS"_s, UseTo::Compile }; } + } else if (!evaluatingLinkLibraries) { + // Honor TRANSITIVE_COMPILE_PROPERTIES and TRANSITIVE_LINK_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_LINK_PROPERTIES", UseTo::Link); + addTransitiveProperties("TRANSITIVE_COMPILE_PROPERTIES", UseTo::Compile); + i = ctpm.emplace(config, std::move(ctp)).first; + } + return i->second; +} diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 44af9ce..ee53a8e 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1918,14 +1918,14 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() info.SetBool("MOC_RELAXED_MODE", this->Moc.RelaxedMode); info.SetBool("MOC_PATH_PREFIX", this->Moc.PathPrefix); - cmGeneratorExpressionDAGChecker dagChecker(this->GenTarget, - "AUTOMOC_MACRO_NAMES", nullptr, - nullptr, this->LocalGen); EvaluatedTargetPropertyEntries InterfaceAutoMocMacroNamesEntries; if (this->MultiConfig) { for (auto const& cfg : this->ConfigsList) { if (!cfg.empty()) { + cmGeneratorExpressionDAGChecker dagChecker( + this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr, nullptr, + this->LocalGen, cfg); AddInterfaceEntries(this->GenTarget, cfg, "INTERFACE_AUTOMOC_MACRO_NAMES", "CXX", &dagChecker, InterfaceAutoMocMacroNamesEntries, @@ -1933,6 +1933,9 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() } } } else { + cmGeneratorExpressionDAGChecker dagChecker( + this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr, nullptr, + this->LocalGen, this->ConfigDefault); AddInterfaceEntries(this->GenTarget, this->ConfigDefault, "INTERFACE_AUTOMOC_MACRO_NAMES", "CXX", &dagChecker, InterfaceAutoMocMacroNamesEntries, |