diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 1c350ab2d..b61e26f2a 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1122,7 +1122,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode else if(!interfacePropertyName.empty()) { if(cmLinkImplementationLibraries const* impl = - target->GetLinkImplementationLibraries(context->Config)) + gtgt->GetLinkImplementationLibraries(context->Config)) { linkedTargetsContent = getLinkedTargetsContent(impl->Libraries, target, diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1a0bbe8cd..278194e5c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -847,7 +847,7 @@ static void AddInterfaceEntries( std::vector& entries) { if(cmLinkImplementationLibraries const* impl = - thisTarget->Target->GetLinkImplementationLibraries(config)) + thisTarget->GetLinkImplementationLibraries(config)) { for (std::vector::const_iterator it = impl->Libraries.begin(), end = impl->Libraries.end(); @@ -1901,7 +1901,7 @@ cmGeneratorTarget::GetLinkImplementationClosure( std::set emitted; cmLinkImplementationLibraries const* impl - = this->Target->GetLinkImplementationLibraries(config); + = this->GetLinkImplementationLibraries(config); for(std::vector::const_iterator it = impl->Libraries.begin(); @@ -2501,7 +2501,7 @@ cmGeneratorTarget::GetIncludeDirectories(const std::string& config, if(this->Makefile->IsOn("APPLE")) { cmLinkImplementationLibraries const* impl = - this->Target->GetLinkImplementationLibraries(config); + this->GetLinkImplementationLibraries(config); for(std::vector::const_iterator it = impl->Libraries.begin(); it != impl->Libraries.end(); ++it) @@ -4363,8 +4363,7 @@ void cmGeneratorTarget::ComputeLinkInterface(const std::string& config, { // The link implementation is the default link interface. cmLinkImplementationLibraries const* - impl = this->Target->GetLinkImplementationLibrariesInternal(config, - headTarget); + impl = this->GetLinkImplementationLibrariesInternal(config, headTarget); iface.ImplementationIsInterface = true; iface.WrongConfigLibraries = impl->WrongConfigLibraries; } @@ -4558,8 +4557,7 @@ cmGeneratorTarget::ComputeLinkInterfaceLibraries( { // The link implementation is the default link interface. cmLinkImplementationLibraries const* impl = - this->Target->GetLinkImplementationLibrariesInternal(config, - headTarget); + this->GetLinkImplementationLibrariesInternal(config, headTarget); iface.Libraries.insert(iface.Libraries.end(), impl->Libraries.begin(), impl->Libraries.end()); if(this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN && @@ -4674,12 +4672,12 @@ cmGeneratorTarget::GetLinkImplementation(const std::string& config) const return 0; } - cmOptionalLinkImplementation& impl = this->Target->GetLinkImplMap(config); + std::string CONFIG = cmSystemTools::UpperCase(config); + cmOptionalLinkImplementation& impl = this->LinkImplMap[CONFIG][this->Target]; if(!impl.LibrariesDone) { impl.LibrariesDone = true; - this->Target->ComputeLinkImplementationLibraries(config, impl, - this->Target); + this->ComputeLinkImplementationLibraries(config, impl, this->Target); } if(!impl.LanguagesDone) { @@ -4819,9 +4817,161 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const return false; } if(cmLinkImplementationLibraries const* impl = - this->Target->GetLinkImplementationLibraries(config)) + this->GetLinkImplementationLibraries(config)) { return !impl->Libraries.empty(); } return false; } + +//---------------------------------------------------------------------------- +cmLinkImplementationLibraries const* +cmGeneratorTarget::GetLinkImplementationLibraries( + const std::string& config) const +{ + return this->GetLinkImplementationLibrariesInternal(config, this->Target); +} + +//---------------------------------------------------------------------------- +cmLinkImplementationLibraries const* +cmGeneratorTarget::GetLinkImplementationLibrariesInternal( + const std::string& config, cmTarget const* head) const +{ + // There is no link implementation for imported targets. + if(this->IsImported()) + { + return 0; + } + + // Populate the link implementation libraries for this configuration. + std::string CONFIG = cmSystemTools::UpperCase(config); + HeadToLinkImplementationMap& hm = + this->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; + } + + cmOptionalLinkImplementation& impl = hm[head]; + if(!impl.LibrariesDone) + { + impl.LibrariesDone = true; + this->ComputeLinkImplementationLibraries(config, impl, head); + } + return &impl; +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::ComputeLinkImplementationLibraries( + const std::string& config, + cmOptionalLinkImplementation& impl, + cmTarget const* head) const +{ + cmStringRange entryRange = + this->Target->GetLinkImplementationEntries(); + cmBacktraceRange btRange = + this->Target->GetLinkImplementationBacktraces(); + cmBacktraceRange::const_iterator btIt = btRange.begin(); + // Collect libraries directly linked in this configuration. + for (cmStringRange::const_iterator le = entryRange.begin(), + end = entryRange.end(); le != end; ++le, ++btIt) + { + std::vector llibs; + cmGeneratorExpressionDAGChecker dagChecker( + this->GetName(), + "LINK_LIBRARIES", 0, 0); + cmGeneratorExpression ge(*btIt); + cmsys::auto_ptr const cge = + ge.Parse(*le); + std::string const evaluated = + cge->Evaluate(this->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) + { + // Skip entries that resolve to the target itself or are empty. + std::string name = this->Target->CheckCMP0004(*li); + if(name == this->GetName() || name.empty()) + { + if(name == this->GetName()) + { + bool noMessage = false; + cmake::MessageType messageType = cmake::FATAL_ERROR; + std::ostringstream e; + switch(this->Target->GetPolicyStatusCMP0038()) + { + case cmPolicies::WARN: + { + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0038) << "\n"; + messageType = cmake::AUTHOR_WARNING; + } + break; + case cmPolicies::OLD: + noMessage = true; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Issue the fatal message. + break; + } + + if(!noMessage) + { + e << "Target \"" << this->GetName() << "\" links to itself."; + this->LocalGenerator->GetCMakeInstance()->IssueMessage( + messageType, e.str(), this->Target->GetBacktrace()); + if (messageType == cmake::FATAL_ERROR) + { + return; + } + } + } + continue; + } + + // The entry is meant for this configuration. + impl.Libraries.push_back( + cmLinkImplItem(name, this->Target->FindTargetToLink(name), + *btIt, evaluated != *le)); + } + + std::set const& seenProps = cge->GetSeenTargetProperties(); + for (std::set::const_iterator it = seenProps.begin(); + it != seenProps.end(); ++it) + { + if (!this->GetProperty(*it)) + { + this->Target->LinkImplicitNullProperties.insert(*it); + } + } + cge->GetMaxLanguageStandard(this->Target, + this->MaxLanguageStandards); + } + + cmTarget::LinkLibraryType linkType = this->Target->ComputeLinkType(config); + cmTarget::LinkLibraryVectorType const& oldllibs = + this->Target->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->Target->CheckCMP0004(li->first); + if(name == this->GetName() || name.empty()) + { + continue; + } + // Support OLD behavior for CMP0003. + impl.WrongConfigLibraries.push_back( + cmLinkItem(name, this->Target->FindTargetToLink(name))); + } + } +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index e8c5e0479..f5805f1cd 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -207,6 +207,13 @@ public: cmOptionalLinkImplementation& impl ) const; + cmLinkImplementationLibraries const* + GetLinkImplementationLibraries(const std::string& config) const; + + void ComputeLinkImplementationLibraries(const std::string& config, + cmOptionalLinkImplementation& impl, + cmTarget const* head) const; + // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change // when source file properties are changed and we do not have enough @@ -462,6 +469,16 @@ private: void GetSourceFiles(std::vector& files, const std::string& config) const; + struct HeadToLinkImplementationMap: + public std::map {}; + typedef std::map LinkImplMapType; + mutable LinkImplMapType LinkImplMap; + + cmLinkImplementationLibraries const* + GetLinkImplementationLibrariesInternal(const std::string& config, + cmTarget const* head) const; + typedef std::pair OutputNameKey; typedef std::map OutputNameMapType; mutable OutputNameMapType OutputNameMap; @@ -477,6 +494,12 @@ public: std::vector const& GetLinkImplementationClosure(const std::string& config) const; + mutable std::map MaxLanguageStandards; + std::map const& + GetMaxLanguageStandards() const + { + return this->MaxLanguageStandards; + } }; struct cmStrictTargetComparison { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 6647894d1..06eb004e0 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1152,8 +1152,8 @@ void cmLocalGenerator::AddCompileOptions( } for(std::map::const_iterator it - = target->GetMaxLanguageStandards().begin(); - it != target->GetMaxLanguageStandards().end(); ++it) + = gtgt->GetMaxLanguageStandards().begin(); + it != gtgt->GetMaxLanguageStandards().end(); ++it) { const char* standard = target->GetProperty(it->first + "_STANDARD"); if(!standard) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 63c7740e5..e1642cc95 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -95,12 +95,6 @@ public: typedef std::map ImportInfoMapType; ImportInfoMapType ImportInfoMap; - struct HeadToLinkImplementationMap: - public std::map {}; - typedef std::map LinkImplMapType; - LinkImplMapType LinkImplMap; - std::set UtilityItems; bool UtilityItemsDone; @@ -405,7 +399,6 @@ void cmTarget::FinishConfigure() // on-demand during the configuration. This ensures that build // system generation uses up-to-date information even if other cache // invalidation code in this source file is buggy. - this->ClearLinkMaps(); #if defined(_WIN32) && !defined(__CYGWIN__) // Do old-style link dependency analysis only for CM_USE_OLD_VS6. @@ -416,12 +409,6 @@ void cmTarget::FinishConfigure() #endif } -//---------------------------------------------------------------------------- -void cmTarget::ClearLinkMaps() -{ - this->Internal->LinkImplMap.clear(); -} - //---------------------------------------------------------------------------- cmListFileBacktrace const& cmTarget::GetBacktrace() const { @@ -884,7 +871,6 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, this->LinkLibrariesForVS6.push_back( tmp ); #endif this->OriginalLinkLibraries.push_back(tmp); - this->ClearLinkMaps(); // Add the explicit dependency information for this target. This is // simply a set of libraries separated by ";". There should always @@ -983,6 +969,16 @@ cmBacktraceRange cmTarget::GetSourceBacktraces() const return cmMakeRange(this->Internal->SourceBacktraces); } +cmStringRange cmTarget::GetLinkImplementationEntries() const +{ + return cmMakeRange(this->Internal->LinkImplementationPropertyEntries); +} + +cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const +{ + return cmMakeRange(this->Internal->LinkImplementationPropertyBacktraces); +} + #if defined(_WIN32) && !defined(__CYGWIN__) //---------------------------------------------------------------------------- void @@ -1611,10 +1607,6 @@ void cmTarget::MaybeInvalidatePropertyCache(const std::string& prop) { this->Internal->ImportInfoMap.clear(); } - if(!this->IsImported() && cmHasLiteralPrefix(prop, "LINK_INTERFACE_")) - { - this->ClearLinkMaps(); - } } //---------------------------------------------------------------------------- @@ -3162,163 +3154,6 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, } } -cmOptionalLinkImplementation& -cmTarget::GetLinkImplMap(std::string const& config) const -{ - // Populate the link implementation for this configuration. - std::string CONFIG = cmSystemTools::UpperCase(config); - return Internal->LinkImplMap[CONFIG][this]; -} - -//---------------------------------------------------------------------------- -cmLinkImplementationLibraries const* -cmTarget::GetLinkImplementationLibraries(const std::string& config) const -{ - return this->GetLinkImplementationLibrariesInternal(config, this); -} - -//---------------------------------------------------------------------------- -cmLinkImplementationLibraries const* -cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config, - cmTarget const* head) const -{ - // There is no link implementation for imported targets. - if(this->IsImported()) - { - return 0; - } - - // Populate the link implementation libraries for this configuration. - 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; - } - - cmOptionalLinkImplementation& impl = hm[head]; - if(!impl.LibrariesDone) - { - impl.LibrariesDone = true; - this->ComputeLinkImplementationLibraries(config, impl, head); - } - return &impl; -} - -//---------------------------------------------------------------------------- -void cmTarget::ComputeLinkImplementationLibraries( - const std::string& config, - cmOptionalLinkImplementation& impl, - cmTarget const* head) const -{ - std::vector::const_iterator btIt = - this->Internal->LinkImplementationPropertyBacktraces.begin(); - // Collect libraries directly linked in this configuration. - for (std::vector::const_iterator - le = this->Internal->LinkImplementationPropertyEntries.begin(), - end = this->Internal->LinkImplementationPropertyEntries.end(); - le != end; ++le, ++btIt) - { - std::vector llibs; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), - "LINK_LIBRARIES", 0, 0); - cmGeneratorExpression ge(*btIt); - cmsys::auto_ptr const cge = - ge.Parse(*le); - std::string const evaluated = - cge->Evaluate(this->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) - { - // Skip entries that resolve to the target itself or are empty. - std::string name = this->CheckCMP0004(*li); - if(name == this->GetName() || name.empty()) - { - if(name == this->GetName()) - { - bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; - std::ostringstream e; - switch(this->GetPolicyStatusCMP0038()) - { - case cmPolicies::WARN: - { - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0038) << "\n"; - messageType = cmake::AUTHOR_WARNING; - } - break; - case cmPolicies::OLD: - noMessage = true; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - // Issue the fatal message. - break; - } - - if(!noMessage) - { - e << "Target \"" << this->GetName() << "\" links to itself."; - this->Makefile->GetCMakeInstance()->IssueMessage( - messageType, e.str(), this->GetBacktrace()); - if (messageType == cmake::FATAL_ERROR) - { - return; - } - } - } - continue; - } - - // The entry is meant for this configuration. - impl.Libraries.push_back( - cmLinkImplItem(name, this->FindTargetToLink(name), - *btIt, evaluated != *le)); - } - - std::set const& seenProps = cge->GetSeenTargetProperties(); - for (std::set::const_iterator it = seenProps.begin(); - it != seenProps.end(); ++it) - { - if (!this->GetProperty(*it)) - { - this->LinkImplicitNullProperties.insert(*it); - } - } - cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards); - } - - cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); - cmTarget::LinkLibraryVectorType const& oldllibs = - this->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()) - { - continue; - } - // Support OLD behavior for CMP0003. - impl.WrongConfigLibraries.push_back( - cmLinkItem(name, this->FindTargetToLink(name))); - } - } -} - //---------------------------------------------------------------------------- cmTarget const* cmTarget::FindTargetToLink(std::string const& name) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 354eda292..aab9582bb 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -225,16 +225,6 @@ public: void GetObjectLibrariesCMP0026(std::vector& objlibs) const; - cmLinkImplementationLibraries const* - GetLinkImplementationLibraries(const std::string& config) const; - - void ComputeLinkImplementationLibraries(const std::string& config, - cmOptionalLinkImplementation& impl, - cmTarget const* head) const; - - cmOptionalLinkImplementation& - GetLinkImplMap(std::string const& config) const; - cmTarget const* FindTargetToLink(std::string const& name) const; /** Strip off leading and trailing whitespace from an item named in @@ -365,12 +355,6 @@ public: bool LinkLanguagePropagatesToDependents() const { return this->TargetTypeValue == STATIC_LIBRARY; } - std::map const& - GetMaxLanguageStandards() const - { - return this->MaxLanguageStandards; - } - cmStringRange GetIncludeDirectoriesEntries() const; cmBacktraceRange GetIncludeDirectoriesBacktraces() const; @@ -385,6 +369,9 @@ public: cmStringRange GetSourceEntries() const; cmBacktraceRange GetSourceBacktraces() const; + cmStringRange GetLinkImplementationEntries() const; + cmBacktraceRange GetLinkImplementationBacktraces() const; + #if defined(_WIN32) && !defined(__CYGWIN__) const LinkLibraryVectorType &GetLinkLibrariesForVS6() const { @@ -471,7 +458,6 @@ private: std::set Utilities; mutable std::set LinkImplicitNullProperties; std::map UtilityBacktraces; - mutable std::map MaxLanguageStandards; cmPolicies::PolicyMap PolicyMap; std::string Name; std::string InstallPath; @@ -529,14 +515,8 @@ private: void ComputeImportInfo(std::string const& desired_config, ImportInfo& info) const; - cmLinkImplementationLibraries const* - GetLinkImplementationLibrariesInternal(const std::string& config, - cmTarget const* head) const; - std::string ProcessSourceItemCMP0049(const std::string& s); - void ClearLinkMaps(); - void MaybeInvalidatePropertyCache(const std::string& prop); // Internal representation details.