ENH: Add support for exporting graphviz of the project dependencies
This commit is contained in:
parent
93c95f1cc5
commit
bc4e5581ee
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
177
Source/cmake.cxx
177
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue