summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorAndy Cedilnik <andy.cedilnik@kitware.com>2006-03-03 19:24:31 (GMT)
committerAndy Cedilnik <andy.cedilnik@kitware.com>2006-03-03 19:24:31 (GMT)
commitbc4e5581ee62d0826625bf1344c3bad7f8711dbc (patch)
treedfd717c95e59bbac822e81cbadece640123069a2 /Source
parent93c95f1cc5207d043b4bfaa617a611d1dffc7016 (diff)
downloadCMake-bc4e5581ee62d0826625bf1344c3bad7f8711dbc.zip
CMake-bc4e5581ee62d0826625bf1344c3bad7f8711dbc.tar.gz
CMake-bc4e5581ee62d0826625bf1344c3bad7f8711dbc.tar.bz2
ENH: Add support for exporting graphviz of the project dependencies
Diffstat (limited to 'Source')
-rw-r--r--Source/cmTarget.cxx5
-rw-r--r--Source/cmTarget.h2
-rw-r--r--Source/cmake.cxx177
-rw-r--r--Source/cmake.h3
4 files changed, 187 insertions, 0 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 3fd75a5..a562f25 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -606,6 +606,11 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
// The dependency map.
DependencyMap dep_map;
+ if ( m_OriginalLinkLibraries.size() == 0 )
+ {
+ m_OriginalLinkLibraries = m_LinkLibraries;
+ }
+
// 1. Build the dependency graph
//
for(LinkLibraries::reverse_iterator lib = m_LinkLibraries.rbegin();
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index a605a35..9990cdd 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -95,6 +95,7 @@ public:
enum LinkLibraryType {GENERAL, DEBUG, OPTIMIZED};
typedef std::vector<std::pair<std::string,LinkLibraryType> > LinkLibraries;
const LinkLibraries &GetLinkLibraries() {return m_LinkLibraries;}
+ const LinkLibraries &GetOriginalLinkLibraries() {return m_OriginalLinkLibraries;}
/**
* Clear the dependency information recorded for this target, if any.
@@ -321,6 +322,7 @@ private:
std::vector<cmSourceFile*> m_SourceFiles;
LinkLibraries m_LinkLibraries;
LinkLibraries m_PrevLinkedLibraries;
+ LinkLibraries m_OriginalLinkLibraries;
bool m_LinkLibrariesAnalyzed;
bool m_LinkDirectoriesComputed;
std::vector<std::string> m_Frameworks;
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 42a2d2d..8865e10 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -22,6 +22,7 @@
#include "cmCommands.h"
#include "cmCommand.h"
#include "cmFileTimeComparison.h"
+#include "cmGeneratedFileStream.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
@@ -398,6 +399,17 @@ void cmake::SetArgs(const std::vector<std::string>& args)
// skip for now
i++;
}
+ else if(arg.find("--graphviz=",0) == 0)
+ {
+ std::string path = arg.substr(strlen("--graphviz="));
+ path = cmSystemTools::CollapseFullPath(path.c_str());
+ cmSystemTools::ConvertToUnixSlashes(path);
+ m_GraphVizFile = path;
+ if ( m_GraphVizFile.empty() )
+ {
+ cmSystemTools::Error("No file specified for --graphviz");
+ }
+ }
else if(arg.find("--debug-trycompile",0) == 0)
{
std::cout << "debug trycompile on\n";
@@ -1383,6 +1395,11 @@ int cmake::Configure()
{
this->m_CacheManager->SaveCache(this->GetHomeOutputDirectory());
}
+ if ( !m_GraphVizFile.empty() )
+ {
+ std::cout << "Generate graphviz: " << m_GraphVizFile << std::endl;
+ this->GenerateGraphViz(m_GraphVizFile.c_str());
+ }
if(cmSystemTools::GetErrorOccuredFlag())
{
return -1;
@@ -1980,3 +1997,163 @@ const char* cmake::GetCPackCommand()
return m_CPackCommand.c_str();
}
+void cmake::GenerateGraphViz(const char* fileName)
+{
+ cmGeneratedFileStream str(fileName);
+ if ( !str )
+ {
+ return;
+ }
+ str << "digraph G {" << std::endl;
+ str << "node [" << std::endl;
+ str << " fontsize = \"12\"" << std::endl;
+ str << "];" << std::endl;
+
+ cmGlobalGenerator* gg = this->GetGlobalGenerator();
+ std::vector<cmLocalGenerator*> localGenerators;
+ gg->GetLocalGenerators(localGenerators);
+ std::vector<cmLocalGenerator*>::iterator lit;
+ // for target deps
+ // 1 - cmake target
+ // 2 - external target
+ // 0 - no deps
+ std::map<cmStdString, int> targetDeps;
+ std::map<cmStdString, cmTarget*> targetPtrs;
+ std::map<cmStdString, cmStdString> targetNamesNodes;
+ char tgtName[100];
+ int cnt = 0;
+ // First pass get the list of all cmake targets
+ for ( lit = localGenerators.begin(); lit != localGenerators.end(); ++ lit )
+ {
+ cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
+ cmTargets::iterator tit;
+ for ( tit = targets->begin(); tit != targets->end(); ++ tit )
+ {
+ //std::cout << "Found target: " << tit->first.c_str() << std::endl;
+ sprintf(tgtName, "node%d", cnt++);
+ targetNamesNodes[tit->first.c_str()] = tgtName;
+ targetPtrs[tit->first.c_str()] = &tit->second;
+ //str << " \"" << tgtName << "\" [ label=\"" << tit->first.c_str() << "\" shape=\"box\"];" << std::endl;
+ }
+ }
+ // Ok, now find all the stuff we link to that is not in cmake
+ for ( lit = localGenerators.begin(); lit != localGenerators.end(); ++ lit )
+ {
+ cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
+ cmTargets::iterator tit;
+ for ( tit = targets->begin(); tit != targets->end(); ++ tit )
+ {
+ const cmTarget::LinkLibraries* ll = &(tit->second.GetOriginalLinkLibraries());
+ cmTarget::LinkLibraries::const_iterator llit;
+ if ( ll->size() > 0 )
+ {
+ targetDeps[tit->first.c_str()] = 1;
+ }
+ for ( llit = ll->begin(); llit != ll->end(); ++ llit )
+ {
+ const char* libName = llit->first.c_str();
+ std::map<cmStdString, cmStdString>::iterator tarIt = targetNamesNodes.find(libName);
+ if ( tarIt == targetNamesNodes.end() )
+ {
+ sprintf(tgtName, "node%d", cnt++);
+ targetDeps[libName] = 2;
+ targetNamesNodes[libName] = tgtName;
+ //str << " \"" << tgtName << "\" [ label=\"" << libName << "\" shape=\"ellipse\"];" << std::endl;
+ }
+ else
+ {
+ std::map<cmStdString, int>::iterator depIt = targetDeps.find(libName);
+ if ( depIt == targetDeps.end() )
+ {
+ targetDeps[libName] = 1;
+ }
+ }
+ }
+ }
+ }
+
+ // Write out nodes
+ std::map<cmStdString, int>::iterator depIt;
+ for ( depIt = targetDeps.begin(); depIt != targetDeps.end(); ++ depIt )
+ {
+ const char* tgtName = depIt->first.c_str();
+ std::map<cmStdString, cmStdString>::iterator tarIt = targetNamesNodes.find(tgtName);
+ if ( tarIt == targetNamesNodes.end() )
+ {
+ // We should not be here.
+ std::cout << "Cannot find library: " << tgtName << " even though it was added in the previous pass" << std::endl;
+ abort();
+ }
+
+ str << " \"" << tarIt->second.c_str() << "\" [ label=\"" << tgtName << "\" shape=\"";
+ if ( depIt->second == 1 )
+ {
+ std::map<cmStdString, cmTarget*>::iterator tarTypeIt= targetPtrs.find(tgtName);
+ if ( tarTypeIt == targetNamesNodes.end() )
+ {
+ // We should not be here.
+ std::cout << "Cannot find library: " << tgtName << " even though it was added in the previous pass" << std::endl;
+ abort();
+ }
+ cmTarget* tg = tarTypeIt->second;
+ switch ( tg->GetType() )
+ {
+ case cmTarget::EXECUTABLE:
+ str << "house";
+ break;
+ case cmTarget::STATIC_LIBRARY:
+ str << "diamond";
+ break;
+ case cmTarget::SHARED_LIBRARY:
+ str << "polygon";
+ break;
+ case cmTarget::MODULE_LIBRARY:
+ str << "octagon";
+ break;
+ default:
+ str << "box";
+ }
+ }
+ else
+ {
+ str << "ellipse";
+ }
+ str << "\"];" << std::endl;
+ }
+
+ // Now generate the connectivity
+ for ( lit = localGenerators.begin(); lit != localGenerators.end(); ++ lit )
+ {
+ cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
+ cmTargets::iterator tit;
+ for ( tit = targets->begin(); tit != targets->end(); ++ tit )
+ {
+ std::map<cmStdString, int>::iterator depIt = targetDeps.find(tit->first.c_str());
+ if ( depIt == targetDeps.end() )
+ {
+ continue;
+ }
+ std::map<cmStdString, cmStdString>::iterator cmakeTarIt = targetNamesNodes.find(tit->first.c_str());
+ const cmTarget::LinkLibraries* ll = &(tit->second.GetOriginalLinkLibraries());
+ cmTarget::LinkLibraries::const_iterator llit;
+ for ( llit = ll->begin(); llit != ll->end(); ++ llit )
+ {
+ const char* libName = llit->first.c_str();
+ std::map<cmStdString, cmStdString>::iterator tarIt = targetNamesNodes.find(libName);
+ if ( tarIt == targetNamesNodes.end() )
+ {
+ // We should not be here.
+ std::cout << "Cannot find library: " << libName << " even though it was added in the previous pass" << std::endl;
+ abort();
+ }
+ str << " \"" << cmakeTarIt->second.c_str() << "\" -> \"" << tarIt->second.c_str() << "\"" << std::endl;
+ }
+ }
+ }
+
+ // TODO: Use dotted or something for external libraries
+ //str << " \"node0\":f4 -> \"node12\"[color=\"#0000ff\" style=dotted]" << std::endl;
+ //
+ str << "}" << std::endl;
+}
+
diff --git a/Source/cmake.h b/Source/cmake.h
index e74b885..8c4eaaf 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -311,6 +311,8 @@ protected:
//! Make sure all commands are what they say they are and there is no macros.
void CleanupCommandsAndMacros();
+
+ void GenerateGraphViz(const char* fileName);
cmVariableWatch* m_VariableWatch;
@@ -329,6 +331,7 @@ private:
bool m_ClearBuildSystem;
bool m_DebugTryCompile;
cmFileTimeComparison* m_FileComparison;
+ std::string m_GraphVizFile;
void UpdateConversionPathTable();
};