Merge topic 'ImprovedDotSupport2'
78c86f4 Exclude targets from the graphviz file based on a regex 5ea1e4c Collect targets and libs on demand instead of in the ctor 2a5790a Use std::cout instead of fprintf 7ba2d36 Enable/disable generating graphs depending on the target type 84ce612 Move the code for generating dot-files into separate class cmGraphVizWriter a60b099 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 functions f7d56df 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.cxx
|
||||||
cmGlobalUnixMakefileGenerator3.h
|
cmGlobalUnixMakefileGenerator3.h
|
||||||
cmGraphAdjacencyList.h
|
cmGraphAdjacencyList.h
|
||||||
|
cmGraphVizWriter.cxx
|
||||||
|
cmGraphVizWriter.h
|
||||||
cmInstallGenerator.h
|
cmInstallGenerator.h
|
||||||
cmInstallGenerator.cxx
|
cmInstallGenerator.cxx
|
||||||
cmInstallExportGenerator.cxx
|
cmInstallExportGenerator.cxx
|
||||||
|
435
Source/cmGraphVizWriter.cxx
Normal file
435
Source/cmGraphVizWriter.cxx
Normal file
@ -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;
|
||||||
|
}
|
84
Source/cmGraphVizWriter.h
Normal file
84
Source/cmGraphVizWriter.h
Normal file
@ -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
|
257
Source/cmake.cxx
257
Source/cmake.cxx
@ -26,6 +26,7 @@
|
|||||||
#include "cmDocumentationFormatterText.h"
|
#include "cmDocumentationFormatterText.h"
|
||||||
|
|
||||||
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
||||||
|
# include "cmGraphVizWriter.h"
|
||||||
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
|
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
|
||||||
# include "cmVariableWatch.h"
|
# include "cmVariableWatch.h"
|
||||||
# include <cmsys/Terminal.h>
|
# include <cmsys/Terminal.h>
|
||||||
@ -2835,252 +2836,26 @@ const char* cmake::GetCPackCommand()
|
|||||||
return this->CPackCommand.c_str();
|
return this->CPackCommand.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void cmake::GenerateGraphViz(const char* fileName) const
|
void cmake::GenerateGraphViz(const char* fileName) const
|
||||||
{
|
{
|
||||||
cmGeneratedFileStream str(fileName);
|
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||||
if ( !str )
|
std::auto_ptr<cmGraphVizWriter> gvWriter(
|
||||||
{
|
new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators()));
|
||||||
return;
|
|
||||||
}
|
|
||||||
cmake cm;
|
|
||||||
cmGlobalGenerator ggi;
|
|
||||||
ggi.SetCMakeInstance(&cm);
|
|
||||||
std::auto_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator());
|
|
||||||
cmMakefile *mf = lg->GetMakefile();
|
|
||||||
|
|
||||||
std::string infile = this->GetHomeOutputDirectory();
|
std::string settingsFile = this->GetHomeOutputDirectory();
|
||||||
infile += "/CMakeGraphVizOptions.cmake";
|
settingsFile += "/CMakeGraphVizOptions.cmake";
|
||||||
if ( !cmSystemTools::FileExists(infile.c_str()) )
|
std::string fallbackSettingsFile = this->GetHomeDirectory();
|
||||||
{
|
fallbackSettingsFile += "/CMakeGraphVizOptions.cmake";
|
||||||
infile = this->GetHomeDirectory();
|
|
||||||
infile += "/CMakeGraphVizOptions.cmake";
|
gvWriter->ReadSettings(settingsFile.c_str(), fallbackSettingsFile.c_str());
|
||||||
if ( !cmSystemTools::FileExists(infile.c_str()) )
|
|
||||||
{
|
gvWriter->WritePerTargetFiles(fileName);
|
||||||
infile = "";
|
gvWriter->WriteGlobalFile(fileName);
|
||||||
}
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
int cmake::SymlinkLibrary(std::vector<std::string>& args)
|
int cmake::SymlinkLibrary(std::vector<std::string>& args)
|
||||||
|
@ -50,6 +50,8 @@ class cmExternalMakefileProjectGenerator;
|
|||||||
class cmDocumentationSection;
|
class cmDocumentationSection;
|
||||||
class cmPolicies;
|
class cmPolicies;
|
||||||
class cmListFileBacktrace;
|
class cmListFileBacktrace;
|
||||||
|
class cmTarget;
|
||||||
|
class cmGeneratedFileStream;
|
||||||
|
|
||||||
class cmake
|
class cmake
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user