From 9d13e1679f2b52e88748a710edd201ed9fba7447 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jul 2014 11:14:26 -0400 Subject: [PATCH 1/6] cmTarget: Remove duplicate link interface map No target is both imported and not imported so we do not need separate link interface maps for them. --- Source/cmTarget.cxx | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 9d00591e9..dc8384d63 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -141,11 +141,6 @@ public: LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap; bool PolicyWarnedCMP0022; - typedef std::map - ImportLinkInterfaceMapType; - ImportLinkInterfaceMapType ImportLinkInterfaceMap; - ImportLinkInterfaceMapType ImportLinkInterfaceUsageRequirementsOnlyMap; - typedef std::map OutputInfoMapType; OutputInfoMapType OutputInfoMap; @@ -528,8 +523,6 @@ void cmTarget::ClearLinkMaps() this->Internal->LinkImplMap.clear(); this->Internal->LinkInterfaceMap.clear(); this->Internal->LinkInterfaceUsageRequirementsOnlyMap.clear(); - this->Internal->ImportLinkInterfaceMap.clear(); - this->Internal->ImportLinkInterfaceUsageRequirementsOnlyMap.clear(); this->Internal->LinkClosureMap.clear(); for (cmTargetLinkInformationMap::const_iterator it = this->LinkInformation.begin(); @@ -5826,10 +5819,10 @@ cmTarget::GetImportLinkInterface(const std::string& config, } TargetConfigPair key(headTarget, cmSystemTools::UpperCase(config)); - cmTargetInternals::ImportLinkInterfaceMapType& lim = + cmTargetInternals::LinkInterfaceMapType& lim = (usage_requirements_only ? - this->Internal->ImportLinkInterfaceUsageRequirementsOnlyMap : - this->Internal->ImportLinkInterfaceMap); + this->Internal->LinkInterfaceUsageRequirementsOnlyMap : + this->Internal->LinkInterfaceMap); cmTargetInternals::OptionalLinkInterface& iface = lim[key]; if(!iface.AllDone) From fe665fdda8986b3af061ec91a7ab5fbe8f606e4f Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jul 2014 11:26:10 -0400 Subject: [PATCH 2/6] cmTarget: Refactor link interface map storage Convert LinkInterfaceMapType and LinkImplMapType to nested maps that index on configuration first and 'head' target second. --- Source/cmTarget.cxx | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index dc8384d63..52b7e68c5 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -88,11 +88,6 @@ struct cmTarget::CompileInfo std::string CompilePdbDir; }; -struct TargetConfigPair : public std::pair { - TargetConfigPair(cmTarget const* tgt, const std::string &config) - : std::pair(tgt, config) {} -}; - //---------------------------------------------------------------------------- class cmTargetInternals { @@ -135,7 +130,9 @@ public: cmTarget const* head, bool usage_requirements_only); - typedef std::map + struct HeadToLinkInterfaceMap: + public std::map {}; + typedef std::map LinkInterfaceMapType; LinkInterfaceMapType LinkInterfaceMap; LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap; @@ -158,8 +155,10 @@ public: bool LibrariesDone; bool LanguagesDone; }; - typedef std::map LinkImplMapType; + struct HeadToLinkImplementationMap: + public std::map {}; + typedef std::map LinkImplMapType; LinkImplMapType LinkImplMap; typedef std::map LinkClosureMapType; @@ -5746,10 +5745,10 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface( } // Lookup any existing link interface for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); + std::string CONFIG = cmSystemTools::UpperCase(config); cmTargetInternals::OptionalLinkInterface& - iface = this->Internal->LinkInterfaceMap[key]; + iface = this->Internal->LinkInterfaceMap[CONFIG][head]; if(!iface.LibrariesDone) { iface.LibrariesDone = true; @@ -5789,13 +5788,13 @@ cmTarget::GetLinkInterfaceLibraries(const std::string& config, } // Lookup any existing link interface for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); + std::string CONFIG = cmSystemTools::UpperCase(config); cmTargetInternals::LinkInterfaceMapType& lim = (usage_requirements_only ? this->Internal->LinkInterfaceUsageRequirementsOnlyMap : this->Internal->LinkInterfaceMap); - cmTargetInternals::OptionalLinkInterface& iface = lim[key]; + cmTargetInternals::OptionalLinkInterface& iface = lim[CONFIG][head]; if(!iface.LibrariesDone) { iface.LibrariesDone = true; @@ -5818,13 +5817,13 @@ cmTarget::GetImportLinkInterface(const std::string& config, return 0; } - TargetConfigPair key(headTarget, cmSystemTools::UpperCase(config)); cmTargetInternals::LinkInterfaceMapType& lim = (usage_requirements_only ? this->Internal->LinkInterfaceUsageRequirementsOnlyMap : this->Internal->LinkInterfaceMap); - cmTargetInternals::OptionalLinkInterface& iface = lim[key]; + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::OptionalLinkInterface& iface = lim[CONFIG][headTarget]; if(!iface.AllDone) { iface.AllDone = true; @@ -6226,9 +6225,9 @@ cmTarget::GetLinkImplementation(const std::string& config) const } // Populate the link implementation for this configuration. - TargetConfigPair key(this, cmSystemTools::UpperCase(config)); + std::string CONFIG = cmSystemTools::UpperCase(config); cmTargetInternals::OptionalLinkImplementation& - impl = this->Internal->LinkImplMap[key]; + impl = this->Internal->LinkImplMap[CONFIG][this]; if(!impl.LibrariesDone) { impl.LibrariesDone = true; @@ -6261,9 +6260,9 @@ cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config, } // Populate the link implementation libraries for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); + std::string CONFIG = cmSystemTools::UpperCase(config); cmTargetInternals::OptionalLinkImplementation& - impl = this->Internal->LinkImplMap[key]; + impl = this->Internal->LinkImplMap[CONFIG][head]; if(!impl.LibrariesDone) { impl.LibrariesDone = true; From 438d9c7c822f42c4fccd77a47b1a32f52a87e617 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jul 2014 11:36:16 -0400 Subject: [PATCH 3/6] cmTarget: Re-order link interface map lookup logic In GetLinkInterface, GetLinkInterfaceLibraries, and GetImportLinkInterface, lookup the HeadToLinkInterfaceMap for the current configuration first, and then index it by head target. In GetLinkImplementationLibrariesInternal, lookup the HeadToLinkImplementationMap for the current configuration first, and then index it by head target. --- Source/cmTarget.cxx | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 52b7e68c5..df65a68de 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -5746,9 +5746,9 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface( // Lookup any existing link interface for this configuration. std::string CONFIG = cmSystemTools::UpperCase(config); - - cmTargetInternals::OptionalLinkInterface& - iface = this->Internal->LinkInterfaceMap[CONFIG][head]; + cmTargetInternals::HeadToLinkInterfaceMap& hm = + this->Internal->LinkInterfaceMap[CONFIG]; + cmTargetInternals::OptionalLinkInterface& iface = hm[head]; if(!iface.LibrariesDone) { iface.LibrariesDone = true; @@ -5789,12 +5789,11 @@ cmTarget::GetLinkInterfaceLibraries(const std::string& config, // Lookup any existing link interface for this configuration. std::string CONFIG = cmSystemTools::UpperCase(config); - cmTargetInternals::LinkInterfaceMapType& lim = + cmTargetInternals::HeadToLinkInterfaceMap& hm = (usage_requirements_only ? - this->Internal->LinkInterfaceUsageRequirementsOnlyMap : - this->Internal->LinkInterfaceMap); - - cmTargetInternals::OptionalLinkInterface& iface = lim[CONFIG][head]; + this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : + this->Internal->LinkInterfaceMap[CONFIG]); + cmTargetInternals::OptionalLinkInterface& iface = hm[head]; if(!iface.LibrariesDone) { iface.LibrariesDone = true; @@ -5817,13 +5816,12 @@ cmTarget::GetImportLinkInterface(const std::string& config, return 0; } - cmTargetInternals::LinkInterfaceMapType& lim = - (usage_requirements_only ? - this->Internal->LinkInterfaceUsageRequirementsOnlyMap : - this->Internal->LinkInterfaceMap); - std::string CONFIG = cmSystemTools::UpperCase(config); - cmTargetInternals::OptionalLinkInterface& iface = lim[CONFIG][headTarget]; + cmTargetInternals::HeadToLinkInterfaceMap& hm = + (usage_requirements_only ? + this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : + this->Internal->LinkInterfaceMap[CONFIG]); + cmTargetInternals::OptionalLinkInterface& iface = hm[headTarget]; if(!iface.AllDone) { iface.AllDone = true; @@ -6261,8 +6259,9 @@ cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config, // Populate the link implementation libraries for this configuration. std::string CONFIG = cmSystemTools::UpperCase(config); - cmTargetInternals::OptionalLinkImplementation& - impl = this->Internal->LinkImplMap[CONFIG][head]; + cmTargetInternals::HeadToLinkImplementationMap& hm = + this->Internal->LinkImplMap[CONFIG]; + cmTargetInternals::OptionalLinkImplementation& impl = hm[head]; if(!impl.LibrariesDone) { impl.LibrariesDone = true; From 46099b82ed71394f1dc6e0bbb91704d274edab7d Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jul 2014 11:55:56 -0400 Subject: [PATCH 4/6] cmTarget: Move ComputeLinkImplementation* to internals There are no external callers, and this will allow the methods to see the full OptionalLinkImplementation internal structure. --- Source/cmTarget.cxx | 76 +++++++++++++++++++++++++++------------------ Source/cmTarget.h | 5 --- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index df65a68de..353a3a683 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -155,6 +155,15 @@ public: bool LibrariesDone; bool LanguagesDone; }; + void ComputeLinkImplementationLibraries(cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl, + cmTarget const* head) const; + void ComputeLinkImplementationLanguages(cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl + ) const; + struct HeadToLinkImplementationMap: public std::map {}; typedef std::mapComputeLinkImplementationLibraries(config, impl, this); + this->Internal + ->ComputeLinkImplementationLibraries(this, config, impl, this); } if(!impl.LanguagesDone) { impl.LanguagesDone = true; - this->ComputeLinkImplementationLanguages(config, impl); + this->Internal->ComputeLinkImplementationLanguages(this, config, impl); } return &impl; } @@ -6265,51 +6275,54 @@ cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config, if(!impl.LibrariesDone) { impl.LibrariesDone = true; - this->ComputeLinkImplementationLibraries(config, impl, head); + this->Internal + ->ComputeLinkImplementationLibraries(this, config, impl, head); } return &impl; } //---------------------------------------------------------------------------- void -cmTarget::ComputeLinkImplementationLibraries(const std::string& config, - LinkImplementation& impl, - cmTarget const* head) const +cmTargetInternals::ComputeLinkImplementationLibraries( + cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl, + cmTarget const* head) const { // Collect libraries directly linked in this configuration. for (std::vector::const_iterator - le = this->Internal->LinkImplementationPropertyEntries.begin(), - end = this->Internal->LinkImplementationPropertyEntries.end(); + le = this->LinkImplementationPropertyEntries.begin(), + end = this->LinkImplementationPropertyEntries.end(); le != end; ++le) { std::vector llibs; cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), + thisTarget->GetName(), "LINK_LIBRARIES", 0, 0); cmGeneratorExpression ge(&le->Backtrace); cmsys::auto_ptr const cge = ge.Parse(le->Value); std::string const evaluated = - cge->Evaluate(this->Makefile, config, false, head, &dagChecker); + cge->Evaluate(thisTarget->Makefile, config, false, head, &dagChecker); cmSystemTools::ExpandListArgument(evaluated, llibs); for(std::vector::const_iterator li = llibs.begin(); li != llibs.end(); ++li) { // Skip entries that resolve to the target itself or are empty. - std::string name = this->CheckCMP0004(*li); - if(name == this->GetName() || name.empty()) + std::string name = thisTarget->CheckCMP0004(*li); + if(name == thisTarget->GetName() || name.empty()) { - if(name == this->GetName()) + if(name == thisTarget->GetName()) { bool noMessage = false; cmake::MessageType messageType = cmake::FATAL_ERROR; cmOStringStream e; - switch(this->GetPolicyStatusCMP0038()) + switch(thisTarget->GetPolicyStatusCMP0038()) { case cmPolicies::WARN: { - e << (this->Makefile->GetPolicies() + e << (thisTarget->Makefile->GetPolicies() ->GetPolicyWarning(cmPolicies::CMP0038)) << "\n"; messageType = cmake::AUTHOR_WARNING; } @@ -6325,9 +6338,9 @@ cmTarget::ComputeLinkImplementationLibraries(const std::string& config, if(!noMessage) { - e << "Target \"" << this->GetName() << "\" links to itself."; - this->Makefile->GetCMakeInstance()->IssueMessage( - messageType, e.str(), this->GetBacktrace()); + e << "Target \"" << thisTarget->GetName() << "\" links to itself."; + thisTarget->Makefile->GetCMakeInstance()->IssueMessage( + messageType, e.str(), thisTarget->GetBacktrace()); if (messageType == cmake::FATAL_ERROR) { return; @@ -6339,7 +6352,7 @@ cmTarget::ComputeLinkImplementationLibraries(const std::string& config, // The entry is meant for this configuration. impl.Libraries.push_back( - cmLinkImplItem(name, this->FindTargetToLink(name), + cmLinkImplItem(name, thisTarget->FindTargetToLink(name), le->Backtrace, evaluated != le->Value)); } @@ -6347,42 +6360,45 @@ cmTarget::ComputeLinkImplementationLibraries(const std::string& config, for (std::set::const_iterator it = seenProps.begin(); it != seenProps.end(); ++it) { - if (!this->GetProperty(*it)) + if (!thisTarget->GetProperty(*it)) { - this->LinkImplicitNullProperties.insert(*it); + thisTarget->LinkImplicitNullProperties.insert(*it); } } - cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards); + cge->GetMaxLanguageStandard(thisTarget, thisTarget->MaxLanguageStandards); } - cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); - LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries(); + cmTarget::LinkLibraryType linkType = thisTarget->ComputeLinkType(config); + cmTarget::LinkLibraryVectorType const& oldllibs = + thisTarget->GetOriginalLinkLibraries(); for(cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin(); li != oldllibs.end(); ++li) { if(li->second != cmTarget::GENERAL && li->second != linkType) { - std::string name = this->CheckCMP0004(li->first); - if(name == this->GetName() || name.empty()) + std::string name = thisTarget->CheckCMP0004(li->first); + if(name == thisTarget->GetName() || name.empty()) { continue; } // Support OLD behavior for CMP0003. impl.WrongConfigLibraries.push_back( - cmLinkItem(name, this->FindTargetToLink(name))); + cmLinkItem(name, thisTarget->FindTargetToLink(name))); } } } //---------------------------------------------------------------------------- void -cmTarget::ComputeLinkImplementationLanguages(const std::string& config, - LinkImplementation& impl) const +cmTargetInternals::ComputeLinkImplementationLanguages( + cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl) const { // This target needs runtime libraries for its source languages. std::set languages; // Get languages used in our source files. - this->GetLanguages(languages, config); + thisTarget->GetLanguages(languages, config); // Copy the set of langauges to the link implementation. for(std::set::iterator li = languages.begin(); li != languages.end(); ++li) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index b4c8a0fec..f8bed4f7e 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -797,11 +797,6 @@ private: LinkImplementationLibraries const* GetLinkImplementationLibrariesInternal(const std::string& config, cmTarget const* head) const; - void ComputeLinkImplementationLibraries(const std::string& config, - LinkImplementation& impl, - cmTarget const* head) const; - void ComputeLinkImplementationLanguages(const std::string& config, - LinkImplementation& impl) const; void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const; void ExpandLinkItems(std::string const& prop, std::string const& value, From 807e4ffeefb0e10ef0546e0eb7383f3d5533809b Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jul 2014 13:02:22 -0400 Subject: [PATCH 5/6] Genex: Track whether an expression depends on the 'head' target --- Source/cmGeneratorExpression.cxx | 3 +++ Source/cmGeneratorExpression.h | 5 +++++ Source/cmGeneratorExpressionEvaluator.cxx | 14 ++++++++++++++ Source/cmGeneratorExpressionEvaluator.h | 1 + 4 files changed, 23 insertions(+) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 2b4d955e0..7fc1464c3 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -97,6 +97,7 @@ const char *cmCompiledGeneratorExpression::Evaluate( context.Quiet = quiet; context.HadError = false; context.HadContextSensitiveCondition = false; + context.HadHeadSensitiveCondition = false; context.HeadTarget = headTarget; context.EvaluateForBuildsystem = this->EvaluateForBuildsystem; context.CurrentTarget = currentTarget ? currentTarget : headTarget; @@ -124,6 +125,7 @@ const char *cmCompiledGeneratorExpression::Evaluate( if (!context.HadError) { this->HadContextSensitiveCondition = context.HadContextSensitiveCondition; + this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition; } this->DependTargets = context.DependTargets; @@ -137,6 +139,7 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( const std::string& input) : Backtrace(backtrace), Input(input), HadContextSensitiveCondition(false), + HadHeadSensitiveCondition(false), EvaluateForBuildsystem(false) { cmGeneratorExpressionLexer l; diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 324d23c15..b952520e6 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -111,6 +111,10 @@ public: { return this->HadContextSensitiveCondition; } + bool GetHadHeadSensitiveCondition() const + { + return this->HadHeadSensitiveCondition; + } void SetEvaluateForBuildsystem(bool eval) { @@ -141,6 +145,7 @@ private: MaxLanguageStandard; mutable std::string Output; mutable bool HadContextSensitiveCondition; + mutable bool HadHeadSensitiveCondition; bool EvaluateForBuildsystem; }; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 28879f1c5..7a53d65c9 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -840,6 +840,10 @@ getLinkedTargetsContent( { context->HadContextSensitiveCondition = true; } + if (cge->GetHadHeadSensitiveCondition()) + { + context->HadHeadSensitiveCondition = true; + } } linkedTargetsContent = cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent); @@ -871,6 +875,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode cmTarget const* target = context->HeadTarget; std::string propertyName = *parameters.begin(); + if (parameters.size() == 1) + { + context->HadHeadSensitiveCondition = true; + } if (!target && parameters.size() == 1) { reportError(context, content->GetOriginalExpression(), @@ -1190,6 +1198,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { context->HadContextSensitiveCondition = true; } + if (cge->GetHadHeadSensitiveCondition()) + { + context->HadHeadSensitiveCondition = true; + } if (!linkedTargetsContent.empty()) { result += (result.empty() ? "" : ";") + linkedTargetsContent; @@ -1313,6 +1325,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode "not be used with add_custom_command or add_custom_target."); return std::string(); } + context->HadHeadSensitiveCondition = true; typedef std::map > LangMap; static LangMap availableFeatures; @@ -1446,6 +1459,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode } context->HadContextSensitiveCondition = true; + context->HadHeadSensitiveCondition = true; for (size_t i = 1; i < cmArraySize(targetPolicyWhitelist); ++i) { diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 0ffb86054..8a529e88d 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -41,6 +41,7 @@ struct cmGeneratorExpressionContext bool Quiet; bool HadError; bool HadContextSensitiveCondition; + bool HadHeadSensitiveCondition; bool EvaluateForBuildsystem; }; From 7b743a2e761783f930de41db3f7a706b065bbb2e Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jul 2014 13:04:04 -0400 Subject: [PATCH 6/6] cmTarget: Avoid re-computing head-independent link interfaces --- Source/cmTarget.cxx | 60 +++++++++++++++++++++++++++++++++++++++------ Source/cmTarget.h | 3 ++- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 353a3a683..ca24d2d18 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -114,10 +114,12 @@ public: { OptionalLinkInterface(): LibrariesDone(false), AllDone(false), - Exists(false), ExplicitLibraries(0) {} + Exists(false), HadHeadSensitiveCondition(false), + ExplicitLibraries(0) {} bool LibrariesDone; bool AllDone; bool Exists; + bool HadHeadSensitiveCondition; const char* ExplicitLibraries; }; void ComputeLinkInterface(cmTarget const* thisTarget, @@ -151,9 +153,11 @@ public: struct OptionalLinkImplementation: public cmTarget::LinkImplementation { OptionalLinkImplementation(): - LibrariesDone(false), LanguagesDone(false) {} + LibrariesDone(false), LanguagesDone(false), + HadHeadSensitiveCondition(false) {} bool LibrariesDone; bool LanguagesDone; + bool HadHeadSensitiveCondition; }; void ComputeLinkImplementationLibraries(cmTarget const* thisTarget, const std::string& config, @@ -3435,7 +3439,8 @@ void cmTarget::ExpandLinkItems(std::string const& prop, std::string const& config, cmTarget const* headTarget, bool usage_requirements_only, - std::vector& items) const + std::vector& items, + bool& hadHeadSensitiveCondition) const { cmGeneratorExpression ge; cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, 0, 0); @@ -3446,13 +3451,15 @@ void cmTarget::ExpandLinkItems(std::string const& prop, dagChecker.SetTransitivePropertiesOnly(); } std::vector libs; - cmSystemTools::ExpandListArgument(ge.Parse(value)->Evaluate( + cmsys::auto_ptr cge = ge.Parse(value); + cmSystemTools::ExpandListArgument(cge->Evaluate( this->Makefile, config, false, headTarget, this, &dagChecker), libs); this->LookupLinkItems(libs, items); + hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); } //---------------------------------------------------------------------------- @@ -5757,6 +5764,14 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface( std::string CONFIG = cmSystemTools::UpperCase(config); cmTargetInternals::HeadToLinkInterfaceMap& hm = this->Internal->LinkInterfaceMap[CONFIG]; + + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + cmTargetInternals::OptionalLinkInterface& iface = hm[head]; if(!iface.LibrariesDone) { @@ -5802,6 +5817,14 @@ cmTarget::GetLinkInterfaceLibraries(const std::string& config, (usage_requirements_only ? this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : this->Internal->LinkInterfaceMap[CONFIG]); + + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + cmTargetInternals::OptionalLinkInterface& iface = hm[head]; if(!iface.LibrariesDone) { @@ -5830,6 +5853,14 @@ cmTarget::GetImportLinkInterface(const std::string& config, (usage_requirements_only ? this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : this->Internal->LinkInterfaceMap[CONFIG]); + + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + cmTargetInternals::OptionalLinkInterface& iface = hm[headTarget]; if(!iface.AllDone) { @@ -5838,7 +5869,8 @@ cmTarget::GetImportLinkInterface(const std::string& config, cmSystemTools::ExpandListArgument(info->Languages, iface.Languages); this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, headTarget, usage_requirements_only, - iface.Libraries); + iface.Libraries, + iface.HadHeadSensitiveCondition); std::vector deps; cmSystemTools::ExpandListArgument(info->SharedDeps, deps); this->LookupLinkItems(deps, iface.SharedDeps); @@ -6022,7 +6054,8 @@ cmTargetInternals::ComputeLinkInterfaceLibraries( // The interface libraries have been explicitly set. thisTarget->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, headTarget, usage_requirements_only, - iface.Libraries); + iface.Libraries, + iface.HadHeadSensitiveCondition); } else if (thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN || thisTarget->PolicyStatusCMP0022 == cmPolicies::OLD) @@ -6045,9 +6078,10 @@ cmTargetInternals::ComputeLinkInterfaceLibraries( static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; if(const char* newExplicitLibraries = thisTarget->GetProperty(newProp)) { + bool hadHeadSensitiveConditionDummy = false; thisTarget->ExpandLinkItems(newProp, newExplicitLibraries, config, headTarget, usage_requirements_only, - ifaceLibs); + ifaceLibs, hadHeadSensitiveConditionDummy); } if (ifaceLibs != iface.Libraries) { @@ -6271,6 +6305,14 @@ cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config, std::string CONFIG = cmSystemTools::UpperCase(config); cmTargetInternals::HeadToLinkImplementationMap& hm = this->Internal->LinkImplMap[CONFIG]; + + // If the link implementation does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + cmTargetInternals::OptionalLinkImplementation& impl = hm[head]; if(!impl.LibrariesDone) { @@ -6305,6 +6347,10 @@ cmTargetInternals::ComputeLinkImplementationLibraries( std::string const evaluated = cge->Evaluate(thisTarget->Makefile, config, false, head, &dagChecker); cmSystemTools::ExpandListArgument(evaluated, llibs); + if(cge->GetHadHeadSensitiveCondition()) + { + impl.HadHeadSensitiveCondition = true; + } for(std::vector::const_iterator li = llibs.begin(); li != llibs.end(); ++li) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index f8bed4f7e..333e2ae0c 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -802,7 +802,8 @@ private: void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, cmTarget const* headTarget, bool usage_requirements_only, - std::vector& items) const; + std::vector& items, + bool& hadHeadSensitiveCondition) const; void LookupLinkItems(std::vector const& names, std::vector& items) const;