Merge topic 'ImprovedDotSupport2'
78c86f4
Exclude targets from the graphviz file based on a regex5ea1e4c
Collect targets and libs on demand instead of in the ctor2a5790a
Use std::cout instead of fprintf7ba2d36
Enable/disable generating graphs depending on the target type84ce612
Move the code for generating dot-files into separate class cmGraphVizWritera60b099
Generate separate dot files for each target, and a big one with everything.487bd57
Properly insert all targets, also those which don't link to anything.de2b2bf
Move the code for collecting targets and libraries into separate functionsf7d56df
Remove trailing whitespace and minor formatting changes for the dot-code
This commit is contained in:
commit
651120b7af
|
@ -183,6 +183,8 @@ SET(SRCS
|
|||
cmGlobalUnixMakefileGenerator3.cxx
|
||||
cmGlobalUnixMakefileGenerator3.h
|
||||
cmGraphAdjacencyList.h
|
||||
cmGraphVizWriter.cxx
|
||||
cmGraphVizWriter.h
|
||||
cmInstallGenerator.h
|
||||
cmInstallGenerator.cxx
|
||||
cmInstallExportGenerator.cxx
|
||||
|
|
|
@ -0,0 +1,435 @@
|
|||
/*============================================================================
|
||||
CMake - Cross Platform Makefile Generator
|
||||
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
||||
|
||||
Distributed under the OSI-approved BSD License (the "License");
|
||||
see accompanying file Copyright.txt for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the License for more information.
|
||||
============================================================================*/
|
||||
#include "cmGraphVizWriter.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
static const char* getShapeForTarget(const cmTarget* target)
|
||||
{
|
||||
if (!target)
|
||||
{
|
||||
return "ellipse";
|
||||
}
|
||||
|
||||
switch ( target->GetType() )
|
||||
{
|
||||
case cmTarget::EXECUTABLE:
|
||||
return "house";
|
||||
case cmTarget::STATIC_LIBRARY:
|
||||
return "diamond";
|
||||
case cmTarget::SHARED_LIBRARY:
|
||||
return "polygon";
|
||||
case cmTarget::MODULE_LIBRARY:
|
||||
return "octagon";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "box";
|
||||
}
|
||||
|
||||
|
||||
cmGraphVizWriter::cmGraphVizWriter(const std::vector<cmLocalGenerator*>&
|
||||
localGenerators)
|
||||
:GraphType("digraph")
|
||||
,GraphName("GG")
|
||||
,GraphHeader("node [\n fontsize = \"12\"\n];")
|
||||
,GraphNodePrefix("node")
|
||||
,GenerateForExecutables(true)
|
||||
,GenerateForStaticLibs(true)
|
||||
,GenerateForSharedLibs(true)
|
||||
,GenerateForModuleLibs(true)
|
||||
,LocalGenerators(localGenerators)
|
||||
,HaveTargetsAndLibs(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
|
||||
const char* fallbackSettingsFileName)
|
||||
{
|
||||
cmake cm;
|
||||
cmGlobalGenerator ggi;
|
||||
ggi.SetCMakeInstance(&cm);
|
||||
std::auto_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator());
|
||||
cmMakefile *mf = lg->GetMakefile();
|
||||
|
||||
const char* inFileName = settingsFileName;
|
||||
|
||||
if ( !cmSystemTools::FileExists(inFileName) )
|
||||
{
|
||||
inFileName = fallbackSettingsFileName;
|
||||
if ( !cmSystemTools::FileExists(inFileName) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mf->ReadListFile(0, inFileName) )
|
||||
{
|
||||
cmSystemTools::Error("Problem opening GraphViz options file: ",
|
||||
inFileName);
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Reading GraphViz options file: " << inFileName << std::endl;
|
||||
|
||||
#define __set_if_set(var, cmakeDefinition) \
|
||||
{ \
|
||||
const char* value = mf->GetDefinition(cmakeDefinition); \
|
||||
if ( value ) \
|
||||
{ \
|
||||
var = value; \
|
||||
} \
|
||||
}
|
||||
|
||||
__set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE");
|
||||
__set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME");
|
||||
__set_if_set(this->GraphHeader, "GRAPHVIZ_GRAPH_HEADER");
|
||||
__set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX");
|
||||
|
||||
#define __set_bool_if_set(var, cmakeDefinition) \
|
||||
{ \
|
||||
const char* value = mf->GetDefinition(cmakeDefinition); \
|
||||
if ( value ) \
|
||||
{ \
|
||||
var = mf->IsOn(cmakeDefinition); \
|
||||
} \
|
||||
}
|
||||
|
||||
__set_bool_if_set(this->GenerateForExecutables, "GRAPHVIZ_EXECUTABLES");
|
||||
__set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS");
|
||||
__set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS");
|
||||
__set_bool_if_set(this->GenerateForModuleLibs , "GRAPHVIZ_MODULE_LIBS");
|
||||
|
||||
cmStdString tmpRegexString;
|
||||
__set_if_set(tmpRegexString, "GRAPHVIZ_TARGET_IGNORE_REGEX");
|
||||
if (tmpRegexString.size() > 0)
|
||||
{
|
||||
if (!this->TargetIgnoreRegex.compile(tmpRegexString.c_str()))
|
||||
{
|
||||
std::cerr << "Could not compile bad regex \"" << tmpRegexString << "\""
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
this->TargetsToIgnore.clear();
|
||||
const char* ignoreTargets = mf->GetDefinition("GRAPHVIZ_IGNORE_TARGETS");
|
||||
if ( ignoreTargets )
|
||||
{
|
||||
std::vector<std::string> ignoreTargetsVector;
|
||||
cmSystemTools::ExpandListArgument(ignoreTargets,ignoreTargetsVector);
|
||||
for(std::vector<std::string>::iterator itvIt = ignoreTargetsVector.begin();
|
||||
itvIt != ignoreTargetsVector.end();
|
||||
++ itvIt )
|
||||
{
|
||||
this->TargetsToIgnore.insert(itvIt->c_str());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cmGraphVizWriter::WritePerTargetFiles(const char* fileName)
|
||||
{
|
||||
this->CollectTargetsAndLibs();
|
||||
|
||||
for(std::map<cmStdString, const cmTarget*>::const_iterator ptrIt =
|
||||
this->TargetPtrs.begin();
|
||||
ptrIt != this->TargetPtrs.end();
|
||||
++ptrIt)
|
||||
{
|
||||
if (ptrIt->second == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this->GenerateForTargetType(ptrIt->second->GetType()) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::set<std::string> insertedConnections;
|
||||
std::set<std::string> insertedNodes;
|
||||
|
||||
std::string currentFilename = fileName;
|
||||
currentFilename += ".";
|
||||
currentFilename += ptrIt->first;
|
||||
cmGeneratedFileStream str(currentFilename.c_str());
|
||||
if ( !str )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Writing " << currentFilename << "..." << std::endl;
|
||||
this->WriteHeader(str);
|
||||
|
||||
this->WriteConnections(ptrIt->first.c_str(),
|
||||
insertedNodes, insertedConnections, str);
|
||||
this->WriteFooter(str);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cmGraphVizWriter::WriteGlobalFile(const char* fileName)
|
||||
{
|
||||
this->CollectTargetsAndLibs();
|
||||
|
||||
cmGeneratedFileStream str(fileName);
|
||||
if ( !str )
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->WriteHeader(str);
|
||||
|
||||
std::cout << "Writing " << fileName << "..." << std::endl;
|
||||
|
||||
std::set<std::string> insertedConnections;
|
||||
std::set<std::string> insertedNodes;
|
||||
|
||||
for(std::map<cmStdString, const cmTarget*>::const_iterator ptrIt =
|
||||
this->TargetPtrs.begin();
|
||||
ptrIt != this->TargetPtrs.end();
|
||||
++ptrIt)
|
||||
{
|
||||
if (ptrIt->second == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this->GenerateForTargetType(ptrIt->second->GetType()) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
this->WriteConnections(ptrIt->first.c_str(),
|
||||
insertedNodes, insertedConnections, str);
|
||||
}
|
||||
this->WriteFooter(str);
|
||||
}
|
||||
|
||||
|
||||
void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& str) const
|
||||
{
|
||||
str << this->GraphType << " " << this->GraphName << " {" << std::endl;
|
||||
str << this->GraphHeader << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& str) const
|
||||
{
|
||||
str << "}" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void cmGraphVizWriter::WriteConnections(const char* targetName,
|
||||
std::set<std::string>& insertedNodes,
|
||||
std::set<std::string>& insertedConnections,
|
||||
cmGeneratedFileStream& str) const
|
||||
{
|
||||
std::map<cmStdString, const cmTarget* >::const_iterator targetPtrIt =
|
||||
this->TargetPtrs.find(targetName);
|
||||
|
||||
if (targetPtrIt == this->TargetPtrs.end()) // not found at all
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);
|
||||
|
||||
if (targetPtrIt->second == NULL) // it's an external library
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
|
||||
|
||||
const cmTarget::LinkLibraryVectorType* ll =
|
||||
&(targetPtrIt->second->GetOriginalLinkLibraries());
|
||||
|
||||
for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin();
|
||||
llit != ll->end();
|
||||
++ llit )
|
||||
{
|
||||
const char* libName = llit->first.c_str();
|
||||
std::map<cmStdString, cmStdString>::const_iterator libNameIt =
|
||||
this->TargetNamesNodes.find(libName);
|
||||
|
||||
std::string connectionName = myNodeName;
|
||||
connectionName += "-";
|
||||
connectionName += libNameIt->second;
|
||||
if (insertedConnections.find(connectionName) == insertedConnections.end())
|
||||
{
|
||||
insertedConnections.insert(connectionName);
|
||||
this->WriteNode(libName, this->TargetPtrs.find(libName)->second,
|
||||
insertedNodes, str);
|
||||
|
||||
str << " \"" << myNodeName.c_str() << "\" -> \""
|
||||
<< libNameIt->second.c_str() << "\"";
|
||||
str << " // " << targetName << " -> " << libName << std::endl;
|
||||
this->WriteConnections(libName, insertedNodes, insertedConnections, str);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cmGraphVizWriter::WriteNode(const char* targetName,
|
||||
const cmTarget* target,
|
||||
std::set<std::string>& insertedNodes,
|
||||
cmGeneratedFileStream& str) const
|
||||
{
|
||||
if (insertedNodes.find(targetName) == insertedNodes.end())
|
||||
{
|
||||
insertedNodes.insert(targetName);
|
||||
std::map<cmStdString, cmStdString>::const_iterator nameIt =
|
||||
this->TargetNamesNodes.find(targetName);
|
||||
|
||||
str << " \"" << nameIt->second.c_str() << "\" [ label=\""
|
||||
<< targetName << "\" shape=\"" << getShapeForTarget(target)
|
||||
<< "\"];" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmGraphVizWriter::CollectTargetsAndLibs()
|
||||
{
|
||||
if (this->HaveTargetsAndLibs == false)
|
||||
{
|
||||
this->HaveTargetsAndLibs = true;
|
||||
int cnt = this->CollectAllTargets();
|
||||
this->CollectAllExternalLibs(cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int cmGraphVizWriter::CollectAllTargets()
|
||||
{
|
||||
int cnt = 0;
|
||||
// First pass get the list of all cmake targets
|
||||
for (std::vector<cmLocalGenerator*>::const_iterator lit =
|
||||
this->LocalGenerators.begin();
|
||||
lit != this->LocalGenerators.end();
|
||||
++ lit )
|
||||
{
|
||||
const cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
|
||||
for ( cmTargets::const_iterator tit = targets->begin();
|
||||
tit != targets->end();
|
||||
++ tit )
|
||||
{
|
||||
const char* realTargetName = tit->first.c_str();
|
||||
if(this->IgnoreThisTarget(realTargetName))
|
||||
{
|
||||
// Skip ignored targets
|
||||
continue;
|
||||
}
|
||||
//std::cout << "Found target: " << tit->first.c_str() << std::endl;
|
||||
cmOStringStream ostr;
|
||||
ostr << this->GraphNodePrefix << cnt++;
|
||||
this->TargetNamesNodes[realTargetName] = ostr.str();
|
||||
this->TargetPtrs[realTargetName] = &tit->second;
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
int cmGraphVizWriter::CollectAllExternalLibs(int cnt)
|
||||
{
|
||||
// Ok, now find all the stuff we link to that is not in cmake
|
||||
for (std::vector<cmLocalGenerator*>::const_iterator lit =
|
||||
this->LocalGenerators.begin();
|
||||
lit != this->LocalGenerators.end();
|
||||
++ lit )
|
||||
{
|
||||
const cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
|
||||
for ( cmTargets::const_iterator tit = targets->begin();
|
||||
tit != targets->end();
|
||||
++ tit )
|
||||
{
|
||||
const char* realTargetName = tit->first.c_str();
|
||||
if (this->IgnoreThisTarget(realTargetName))
|
||||
{
|
||||
// Skip ignored targets
|
||||
continue;
|
||||
}
|
||||
const cmTarget::LinkLibraryVectorType* ll =
|
||||
&(tit->second.GetOriginalLinkLibraries());
|
||||
for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin();
|
||||
llit != ll->end();
|
||||
++ llit )
|
||||
{
|
||||
const char* libName = llit->first.c_str();
|
||||
if (this->IgnoreThisTarget(libName))
|
||||
{
|
||||
// Skip ignored targets
|
||||
continue;
|
||||
}
|
||||
|
||||
std::map<cmStdString, const cmTarget*>::const_iterator tarIt =
|
||||
this->TargetPtrs.find(libName);
|
||||
if ( tarIt == this->TargetPtrs.end() )
|
||||
{
|
||||
cmOStringStream ostr;
|
||||
ostr << this->GraphNodePrefix << cnt++;
|
||||
this->TargetNamesNodes[libName] = ostr.str();
|
||||
this->TargetPtrs[libName] = NULL;
|
||||
//str << " \"" << ostr.c_str() << "\" [ label=\"" << libName
|
||||
//<< "\" shape=\"ellipse\"];" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
bool cmGraphVizWriter::IgnoreThisTarget(const char* name)
|
||||
{
|
||||
if (this->TargetIgnoreRegex.is_valid())
|
||||
{
|
||||
if (this->TargetIgnoreRegex.find(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (this->TargetsToIgnore.find(name) != this->TargetsToIgnore.end());
|
||||
}
|
||||
|
||||
|
||||
bool cmGraphVizWriter::GenerateForTargetType(cmTarget::TargetType targetType)
|
||||
const
|
||||
{
|
||||
switch (targetType)
|
||||
{
|
||||
case cmTarget::EXECUTABLE:
|
||||
return this->GenerateForExecutables;
|
||||
case cmTarget::STATIC_LIBRARY:
|
||||
return this->GenerateForStaticLibs;
|
||||
case cmTarget::SHARED_LIBRARY:
|
||||
return this->GenerateForSharedLibs;
|
||||
case cmTarget::MODULE_LIBRARY:
|
||||
return this->GenerateForModuleLibs;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
#ifndef CMGRAPHVIZWRITER_H
|
||||
#define CMGRAPHVIZWRITER_H
|
||||
/*============================================================================
|
||||
CMake - Cross Platform Makefile Generator
|
||||
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
||||
|
||||
Distributed under the OSI-approved BSD License (the "License");
|
||||
see accompanying file Copyright.txt for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the License for more information.
|
||||
============================================================================*/
|
||||
#include "cmStandardIncludes.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmTarget.h"
|
||||
#include <cmsys/RegularExpression.hxx>
|
||||
|
||||
|
||||
/** This class implements writing files for graphviz (dot) for graphs
|
||||
* representing the dependencies between the targets in the project. */
|
||||
class cmGraphVizWriter
|
||||
{
|
||||
public:
|
||||
|
||||
cmGraphVizWriter(const std::vector<cmLocalGenerator*>& localGenerators);
|
||||
|
||||
void ReadSettings(const char* settingsFileName,
|
||||
const char* fallbackSettingsFileName);
|
||||
|
||||
void WritePerTargetFiles(const char* fileName);
|
||||
|
||||
void WriteGlobalFile(const char* fileName);
|
||||
|
||||
protected:
|
||||
|
||||
void CollectTargetsAndLibs();
|
||||
|
||||
int CollectAllTargets();
|
||||
|
||||
int CollectAllExternalLibs(int cnt);
|
||||
|
||||
void WriteHeader(cmGeneratedFileStream& str) const;
|
||||
|
||||
void WriteConnections(const char* targetName,
|
||||
std::set<std::string>& insertedNodes,
|
||||
std::set<std::string>& insertedConnections,
|
||||
cmGeneratedFileStream& str) const;
|
||||
|
||||
void WriteNode(const char* targetName, const cmTarget* target,
|
||||
std::set<std::string>& insertedNodes,
|
||||
cmGeneratedFileStream& str) const;
|
||||
|
||||
void WriteFooter(cmGeneratedFileStream& str) const;
|
||||
|
||||
bool IgnoreThisTarget(const char* name);
|
||||
|
||||
bool GenerateForTargetType(cmTarget::TargetType targetType) const;
|
||||
|
||||
cmStdString GraphType;
|
||||
cmStdString GraphName;
|
||||
cmStdString GraphHeader;
|
||||
cmStdString GraphNodePrefix;
|
||||
|
||||
bool GenerateForExecutables;
|
||||
bool GenerateForStaticLibs;
|
||||
bool GenerateForSharedLibs;
|
||||
bool GenerateForModuleLibs;
|
||||
|
||||
cmsys::RegularExpression TargetIgnoreRegex;
|
||||
|
||||
std::set<cmStdString> TargetsToIgnore;
|
||||
|
||||
const std::vector<cmLocalGenerator*>& LocalGenerators;
|
||||
|
||||
std::map<cmStdString, const cmTarget*> TargetPtrs;
|
||||
// maps from the actual target names to node names in dot:
|
||||
std::map<cmStdString, cmStdString> TargetNamesNodes;
|
||||
|
||||
bool HaveTargetsAndLibs;
|
||||
};
|
||||
|
||||
#endif
|
253
Source/cmake.cxx
253
Source/cmake.cxx
|
@ -26,6 +26,7 @@
|
|||
#include "cmDocumentationFormatterText.h"
|
||||
|
||||
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
||||
# include "cmGraphVizWriter.h"
|
||||
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
|
||||
# include "cmVariableWatch.h"
|
||||
# include <cmsys/Terminal.h>
|
||||
|
@ -2835,253 +2836,27 @@ const char* cmake::GetCPackCommand()
|
|||
return this->CPackCommand.c_str();
|
||||
}
|
||||
|
||||
|
||||
void cmake::GenerateGraphViz(const char* fileName) const
|
||||
{
|
||||
cmGeneratedFileStream str(fileName);
|
||||
if ( !str )
|
||||
{
|
||||
return;
|
||||
}
|
||||
cmake cm;
|
||||
cmGlobalGenerator ggi;
|
||||
ggi.SetCMakeInstance(&cm);
|
||||
std::auto_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator());
|
||||
cmMakefile *mf = lg->GetMakefile();
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
std::auto_ptr<cmGraphVizWriter> gvWriter(
|
||||
new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators()));
|
||||
|
||||
std::string infile = this->GetHomeOutputDirectory();
|
||||
infile += "/CMakeGraphVizOptions.cmake";
|
||||
if ( !cmSystemTools::FileExists(infile.c_str()) )
|
||||
{
|
||||
infile = this->GetHomeDirectory();
|
||||
infile += "/CMakeGraphVizOptions.cmake";
|
||||
if ( !cmSystemTools::FileExists(infile.c_str()) )
|
||||
{
|
||||
infile = "";
|
||||
}
|
||||
}
|
||||
std::string settingsFile = this->GetHomeOutputDirectory();
|
||||
settingsFile += "/CMakeGraphVizOptions.cmake";
|
||||
std::string fallbackSettingsFile = this->GetHomeDirectory();
|
||||
fallbackSettingsFile += "/CMakeGraphVizOptions.cmake";
|
||||
|
||||
if ( !infile.empty() )
|
||||
{
|
||||
if ( !mf->ReadListFile(0, infile.c_str()) )
|
||||
{
|
||||
cmSystemTools::Error("Problem opening GraphViz options file: ",
|
||||
infile.c_str());
|
||||
return;
|
||||
}
|
||||
std::cout << "Read GraphViz options file: " << infile.c_str()
|
||||
<< std::endl;
|
||||
}
|
||||
gvWriter->ReadSettings(settingsFile.c_str(), fallbackSettingsFile.c_str());
|
||||
|
||||
#define __set_if_not_set(var, value, cmakeDefinition) \
|
||||
const char* var = mf->GetDefinition(cmakeDefinition); \
|
||||
if ( !var ) \
|
||||
{ \
|
||||
var = value; \
|
||||
}
|
||||
__set_if_not_set(graphType, "digraph", "GRAPHVIZ_GRAPH_TYPE");
|
||||
__set_if_not_set(graphName, "GG", "GRAPHVIZ_GRAPH_NAME");
|
||||
__set_if_not_set(graphHeader, "node [\n fontsize = \"12\"\n];",
|
||||
"GRAPHVIZ_GRAPH_HEADER");
|
||||
__set_if_not_set(graphNodePrefix, "node", "GRAPHVIZ_NODE_PREFIX");
|
||||
const char* ignoreTargets = mf->GetDefinition("GRAPHVIZ_IGNORE_TARGETS");
|
||||
std::set<cmStdString> ignoreTargetsSet;
|
||||
if ( ignoreTargets )
|
||||
{
|
||||
std::vector<std::string> ignoreTargetsVector;
|
||||
cmSystemTools::ExpandListArgument(ignoreTargets,ignoreTargetsVector);
|
||||
std::vector<std::string>::iterator itvIt;
|
||||
for ( itvIt = ignoreTargetsVector.begin();
|
||||
itvIt != ignoreTargetsVector.end();
|
||||
++ itvIt )
|
||||
{
|
||||
ignoreTargetsSet.insert(itvIt->c_str());
|
||||
}
|
||||
}
|
||||
gvWriter->WritePerTargetFiles(fileName);
|
||||
gvWriter->WriteGlobalFile(fileName);
|
||||
|
||||
str << graphType << " " << graphName << " {" << std::endl;
|
||||
str << graphHeader << std::endl;
|
||||
|
||||
const cmGlobalGenerator* gg = this->GetGlobalGenerator();
|
||||
const std::vector<cmLocalGenerator*>& localGenerators =
|
||||
gg->GetLocalGenerators();
|
||||
std::vector<cmLocalGenerator*>::const_iterator lit;
|
||||
// for target deps
|
||||
// 1 - cmake target
|
||||
// 2 - external target
|
||||
// 0 - no deps
|
||||
std::map<cmStdString, int> targetDeps;
|
||||
std::map<cmStdString, const cmTarget*> targetPtrs;
|
||||
std::map<cmStdString, cmStdString> targetNamesNodes;
|
||||
int cnt = 0;
|
||||
// First pass get the list of all cmake targets
|
||||
for ( lit = localGenerators.begin(); lit != localGenerators.end(); ++ lit )
|
||||
{
|
||||
const cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
|
||||
cmTargets::const_iterator tit;
|
||||
for ( tit = targets->begin(); tit != targets->end(); ++ tit )
|
||||
{
|
||||
const char* realTargetName = tit->first.c_str();
|
||||
if ( ignoreTargetsSet.find(realTargetName) != ignoreTargetsSet.end() )
|
||||
{
|
||||
// Skip ignored targets
|
||||
continue;
|
||||
}
|
||||
//std::cout << "Found target: " << tit->first.c_str() << std::endl;
|
||||
cmOStringStream ostr;
|
||||
ostr << graphNodePrefix << cnt++;
|
||||
targetNamesNodes[realTargetName] = ostr.str();
|
||||
targetPtrs[realTargetName] = &tit->second;
|
||||
}
|
||||
}
|
||||
// Ok, now find all the stuff we link to that is not in cmake
|
||||
for ( lit = localGenerators.begin(); lit != localGenerators.end(); ++ lit )
|
||||
{
|
||||
const cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
|
||||
cmTargets::const_iterator tit;
|
||||
for ( tit = targets->begin(); tit != targets->end(); ++ tit )
|
||||
{
|
||||
const cmTarget::LinkLibraryVectorType* ll
|
||||
= &(tit->second.GetOriginalLinkLibraries());
|
||||
cmTarget::LinkLibraryVectorType::const_iterator llit;
|
||||
const char* realTargetName = tit->first.c_str();
|
||||
if ( ignoreTargetsSet.find(realTargetName) != ignoreTargetsSet.end() )
|
||||
{
|
||||
// Skip ignored targets
|
||||
continue;
|
||||
}
|
||||
if ( ll->size() > 0 )
|
||||
{
|
||||
targetDeps[realTargetName] = 1;
|
||||
}
|
||||
for ( llit = ll->begin(); llit != ll->end(); ++ llit )
|
||||
{
|
||||
const char* libName = llit->first.c_str();
|
||||
std::map<cmStdString, cmStdString>::const_iterator tarIt
|
||||
= targetNamesNodes.find(libName);
|
||||
if ( ignoreTargetsSet.find(libName) != ignoreTargetsSet.end() )
|
||||
{
|
||||
// Skip ignored targets
|
||||
continue;
|
||||
}
|
||||
if ( tarIt == targetNamesNodes.end() )
|
||||
{
|
||||
cmOStringStream ostr;
|
||||
ostr << graphNodePrefix << cnt++;
|
||||
targetDeps[libName] = 2;
|
||||
targetNamesNodes[libName] = ostr.str();
|
||||
//str << " \"" << ostr.c_str() << "\" [ label=\"" << libName
|
||||
//<< "\" shape=\"ellipse\"];" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::map<cmStdString, int>::const_iterator depIt
|
||||
= targetDeps.find(libName);
|
||||
if ( depIt == targetDeps.end() )
|
||||
{
|
||||
targetDeps[libName] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write out nodes
|
||||
std::map<cmStdString, int>::const_iterator depIt;
|
||||
for ( depIt = targetDeps.begin(); depIt != targetDeps.end(); ++ depIt )
|
||||
{
|
||||
const char* newTargetName = depIt->first.c_str();
|
||||
std::map<cmStdString, cmStdString>::const_iterator tarIt
|
||||
= targetNamesNodes.find(newTargetName);
|
||||
if ( tarIt == targetNamesNodes.end() )
|
||||
{
|
||||
// We should not be here.
|
||||
std::cout << __LINE__ << " Cannot find library: " << newTargetName
|
||||
<< " even though it was added in the previous pass" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
str << " \"" << tarIt->second.c_str() << "\" [ label=\""
|
||||
<< newTargetName << "\" shape=\"";
|
||||
if ( depIt->second == 1 )
|
||||
{
|
||||
std::map<cmStdString, const cmTarget*>::const_iterator tarTypeIt =
|
||||
targetPtrs.find(newTargetName);
|
||||
if ( tarTypeIt == targetPtrs.end() )
|
||||
{
|
||||
// We should not be here.
|
||||
std::cout << __LINE__ << " Cannot find library: " << newTargetName
|
||||
<< " even though it was added in the previous pass" << std::endl;
|
||||
abort();
|
||||
}
|
||||
const 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 )
|
||||
{
|
||||
const cmTargets* targets = &((*lit)->GetMakefile()->GetTargets());
|
||||
cmTargets::const_iterator tit;
|
||||
for ( tit = targets->begin(); tit != targets->end(); ++ tit )
|
||||
{
|
||||
std::map<cmStdString, int>::iterator dependIt
|
||||
= targetDeps.find(tit->first.c_str());
|
||||
if ( dependIt == targetDeps.end() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::map<cmStdString, cmStdString>::iterator cmakeTarIt
|
||||
= targetNamesNodes.find(tit->first.c_str());
|
||||
const cmTarget::LinkLibraryVectorType* ll
|
||||
= &(tit->second.GetOriginalLinkLibraries());
|
||||
cmTarget::LinkLibraryVectorType::const_iterator llit;
|
||||
for ( llit = ll->begin(); llit != ll->end(); ++ llit )
|
||||
{
|
||||
const char* libName = llit->first.c_str();
|
||||
std::map<cmStdString, cmStdString>::const_iterator tarIt
|
||||
= targetNamesNodes.find(libName);
|
||||
if ( tarIt == targetNamesNodes.end() )
|
||||
{
|
||||
// We should not be here.
|
||||
std::cout << __LINE__ << " 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;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int cmake::SymlinkLibrary(std::vector<std::string>& args)
|
||||
{
|
||||
|
|
|
@ -50,6 +50,8 @@ class cmExternalMakefileProjectGenerator;
|
|||
class cmDocumentationSection;
|
||||
class cmPolicies;
|
||||
class cmListFileBacktrace;
|
||||
class cmTarget;
|
||||
class cmGeneratedFileStream;
|
||||
|
||||
class cmake
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue