summaryrefslogtreecommitdiffstats
path: root/Source/cmGlobalGenerator.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-02-06 04:10:41 (GMT)
committerBrad King <brad.king@kitware.com>2008-02-06 04:10:41 (GMT)
commit523ddedac59756e485818a88c59949355c1b9267 (patch)
treee4d2a1c74ef039f76913981c9073f185e9c2b9fb /Source/cmGlobalGenerator.cxx
parent5b9fccdc0e5e5e3b723f0375f95983b7950be933 (diff)
downloadCMake-523ddedac59756e485818a88c59949355c1b9267.zip
CMake-523ddedac59756e485818a88c59949355c1b9267.tar.gz
CMake-523ddedac59756e485818a88c59949355c1b9267.tar.bz2
ENH: Analyze inter-target dependencies to safely fix cycles
- Cycles may be formed among static libraries - Native build system should not have cycles in target deps - Create cmComputeTargetDepends to analyze dependencies - Identify conneced components and use them to fix deps - Diagnose cycles containing non-STATIC targets - Add debug mode property GLOBAL_DEPENDS_DEBUG_MODE - Use results in cmGlobalGenerator as target direct depends
Diffstat (limited to 'Source/cmGlobalGenerator.cxx')
-rw-r--r--Source/cmGlobalGenerator.cxx152
1 files changed, 14 insertions, 138 deletions
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 0c7845f..25d1bef 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -26,6 +26,7 @@
#include "cmSourceFile.h"
#include "cmVersion.h"
#include "cmExportInstallFileGenerator.h"
+#include "cmComputeTargetDepends.h"
#include <cmsys/Directory.hxx>
@@ -788,6 +789,18 @@ void cmGlobalGenerator::Generate()
this->LocalGenerators[i]->GenerateTargetManifest();
}
+ // Compute the inter-target dependencies.
+ {
+ cmComputeTargetDepends ctd(this);
+ ctd.Compute();
+ std::vector<cmTarget*> const& targets = ctd.GetTargets();
+ for(std::vector<cmTarget*>::const_iterator ti = targets.begin();
+ ti != targets.end(); ++ti)
+ {
+ ctd.GetTargetDirectDepends(*ti, this->TargetDependencies[*ti]);
+ }
+ }
+
// Create a map from local generator to the complete set of targets
// it builds by default.
this->FillLocalGeneratorToTargetMap();
@@ -1718,144 +1731,7 @@ void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
cmGlobalGenerator::TargetDependSet &
cmGlobalGenerator::GetTargetDirectDepends(cmTarget & target)
{
- // Clarify the role of the input target.
- cmTarget * depender = &target;
-
- // if the depends are already in the map then return
- TargetDependMap::iterator tgtI =
- this->TargetDependencies.find(depender);
- if(tgtI != this->TargetDependencies.end())
- {
- return tgtI->second;
- }
-
- // Create an entry for this depender.
- TargetDependSet& depender_depends = this->TargetDependencies[depender];
-
- // Keep track of dependencies already listed.
- std::set<cmStdString> emitted;
-
- // A target should not depend on itself.
- emitted.insert(depender->GetName());
-
- // Loop over all targets linked directly.
- cmTarget::LinkLibraryVectorType const& tlibs =
- target.GetOriginalLinkLibraries();
- for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
- lib != tlibs.end(); ++lib)
- {
- // Don't emit the same library twice for this target.
- if(emitted.insert(lib->first).second)
- {
- this->ConsiderTargetDepends(depender, depender_depends,
- lib->first.c_str());
- }
- }
-
- // Loop over all utility dependencies.
- std::set<cmStdString> const& tutils = target.GetUtilities();
- for(std::set<cmStdString>::const_iterator util = tutils.begin();
- util != tutils.end(); ++util)
- {
- // Don't emit the same utility twice for this target.
- if(emitted.insert(*util).second)
- {
- this->ConsiderTargetDepends(depender, depender_depends,
- util->c_str());
- }
- }
-
- return depender_depends;
-}
-
-//----------------------------------------------------------------------------
-bool
-cmGlobalGenerator::ConsiderTargetDepends(cmTarget * depender,
- TargetDependSet& depender_depends,
- const char* dependee_name)
-{
- // Check the target's makefile first.
- cmTarget * dependee =
- depender->GetMakefile()->FindTarget(dependee_name);
-
- // Then search globally.
- if(!dependee)
- {
- dependee = this->FindTarget(0, dependee_name);
- }
-
- // If not found then skip then the dependee.
- if(!dependee)
- {
- return false;
- }
-
- // Check whether the depender is among the dependee's dependencies.
- std::vector<cmTarget *> 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<unsigned int>(steps.size());
- i > 0; --i)
- {
- cmTarget * 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.
- depender_depends.insert(dependee);
- return true;
- }
-}
-
-//----------------------------------------------------------------------------
-bool
-cmGlobalGenerator
-::FindDependency(cmTarget * goal, cmTarget * current,
- std::vector<cmTarget*>& steps)
-{
- if(current == goal)
- {
- steps.push_back(current);
- return true;
- }
- TargetDependMap::iterator i = this->TargetDependencies.find(current);
- if(i == this->TargetDependencies.end())
- {
- return false;
- }
- TargetDependSet & depends = i->second;
- for(TargetDependSet::iterator j = depends.begin();
- j != depends.end(); ++j)
- {
- if(this->FindDependency(goal, *j, steps))
- {
- steps.push_back(current);
- return true;
- }
- }
- return false;
+ return this->TargetDependencies[&target];
}
void cmGlobalGenerator::AddTarget(cmTargets::value_type &v)