From 2836fc43e79cd5497f2e63ae091ca67f1cb2485d Mon Sep 17 00:00:00 2001 From: Brad King Date: Sat, 22 Dec 2007 13:08:26 -0500 Subject: [PATCH] BUG: Support cyclic dependencies among STATIC libraries by removing one from the generated Makefile rules. --- Source/cmGlobalUnixMakefileGenerator3.cxx | 83 ++++++++++++++++++++++- Source/cmGlobalUnixMakefileGenerator3.h | 8 +++ 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index a0b1c2a82..792ee5678 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -905,7 +905,8 @@ cmGlobalUnixMakefileGenerator3 emitted.insert(target.GetName()); // Loop over all library dependencies. - const cmTarget::LinkLibraryVectorType& tlibs = target.GetLinkLibraries(); + const cmTarget::LinkLibraryVectorType& + tlibs = target.GetOriginalLinkLibraries(); for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin(); lib != tlibs.end(); ++lib) { @@ -960,6 +961,13 @@ cmGlobalUnixMakefileGenerator3 // if a match was found then ... if (result) { + // Avoid creating cyclic dependencies. + if(!this->AllowTargetDepends(&target, result)) + { + return; + } + + // Create the target-level dependency. std::string tgtName = lg3->GetRelativeTargetDirectory(*result); tgtName += "/all"; depends.push_back(tgtName); @@ -1049,3 +1057,76 @@ bool cmGlobalUnixMakefileGenerator3 } return false; } + +//---------------------------------------------------------------------------- +bool +cmGlobalUnixMakefileGenerator3 +::AllowTargetDepends(cmTarget const* depender, cmTarget const* dependee) +{ + // Check whether the depender is among the dependee's dependencies. + std::vector steps; + if(this->FindDependency(depender, dependee, steps)) + { + // This creates a cyclic dependency. + bool isStatic = depender->GetType() == cmTarget::STATIC_LIBRARY; + cmOStringStream e; + e << "Cyclic dependency among targets:\n" + << " " << depender->GetName() << "\n"; + for(unsigned int i = static_cast(steps.size()); + i > 0; --i) + { + cmTarget const* step = steps[i-1]; + e << " -> " << step->GetName() << "\n"; + isStatic = isStatic && step->GetType() == cmTarget::STATIC_LIBRARY; + } + if(isStatic) + { + e << " All targets are STATIC libraries.\n"; + e << " Dropping " + << depender->GetName() << " -> " << dependee->GetName() + << " to resolve.\n"; + cmSystemTools::Message(e.str().c_str()); + } + else + { + e << " At least one target is not a STATIC library.\n"; + cmSystemTools::Error(e.str().c_str()); + } + return false; + } + else + { + // This does not create a cyclic dependency. + this->TargetDependencies[depender].insert(dependee); + return true; + } +} + +//---------------------------------------------------------------------------- +bool +cmGlobalUnixMakefileGenerator3 +::FindDependency(cmTarget const* goal, cmTarget const* current, + std::vector& steps) +{ + if(current == goal) + { + steps.push_back(current); + return true; + } + TargetDependMap::const_iterator i = this->TargetDependencies.find(current); + if(i == this->TargetDependencies.end()) + { + return false; + } + TargetDependSet const& depends = i->second; + for(TargetDependSet::const_iterator j = depends.begin(); + j != depends.end(); ++j) + { + if(this->FindDependency(goal, *j, steps)) + { + steps.push_back(current); + return true; + } + } + return false; +} diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 988d7cc13..8ee023c27 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -179,6 +179,14 @@ protected: std::map TargetSourceFileCount; bool ForceVerboseMakefiles; + + bool AllowTargetDepends(cmTarget const* depender, + cmTarget const* dependee); + bool FindDependency(cmTarget const* goal, cmTarget const* current, + std::vector& steps); + class TargetDependSet: public std::set {}; + typedef std::map TargetDependMap; + TargetDependMap TargetDependencies; }; #endif