Move the code for generating dot-files into separate class cmGraphVizWriter
Alex
This commit is contained in:
parent
a60b09927d
commit
84ce612c65
|
@ -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
|
||||||
|
@ -332,7 +334,7 @@ ENDIF (WIN32)
|
||||||
|
|
||||||
# create a library used by the command line and the GUI
|
# create a library used by the command line and the GUI
|
||||||
ADD_LIBRARY(CMakeLib ${SRCS})
|
ADD_LIBRARY(CMakeLib ${SRCS})
|
||||||
TARGET_LINK_LIBRARIES(CMakeLib cmsys
|
TARGET_LINK_LIBRARIES(CMakeLib cmsys
|
||||||
${CMAKE_EXPAT_LIBRARIES} ${CMAKE_ZLIB_LIBRARIES}
|
${CMAKE_EXPAT_LIBRARIES} ${CMAKE_ZLIB_LIBRARIES}
|
||||||
${CMAKE_TAR_LIBRARIES} ${CMAKE_COMPRESS_LIBRARIES}
|
${CMAKE_TAR_LIBRARIES} ${CMAKE_COMPRESS_LIBRARIES}
|
||||||
${CMAKE_CURL_LIBRARIES} )
|
${CMAKE_CURL_LIBRARIES} )
|
||||||
|
@ -432,7 +434,7 @@ IF(CYGWIN)
|
||||||
CPack/cmCPackCygwinSourceGenerator.cxx
|
CPack/cmCPackCygwinSourceGenerator.cxx
|
||||||
)
|
)
|
||||||
ENDIF(CYGWIN)
|
ENDIF(CYGWIN)
|
||||||
|
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
SET(CPACK_SRCS ${CPACK_SRCS}
|
SET(CPACK_SRCS ${CPACK_SRCS}
|
||||||
CPack/cmCPackDebGenerator.cxx
|
CPack/cmCPackDebGenerator.cxx
|
||||||
|
|
|
@ -0,0 +1,370 @@
|
||||||
|
/*============================================================================
|
||||||
|
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")
|
||||||
|
,LocalGenerators(localGenerators)
|
||||||
|
{
|
||||||
|
int cnt = collectAllTargets();
|
||||||
|
collectAllExternalLibs(cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
for(std::map<cmStdString, const cmTarget*>::const_iterator ptrIt =
|
||||||
|
this->TargetPtrs.begin();
|
||||||
|
ptrIt != this->TargetPtrs.end();
|
||||||
|
++ptrIt)
|
||||||
|
{
|
||||||
|
if (ptrIt->second == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ptrIt->second->GetType() != cmTarget::EXECUTABLE)
|
||||||
|
&& (ptrIt->second->GetType() != cmTarget::STATIC_LIBRARY)
|
||||||
|
&& (ptrIt->second->GetType() != cmTarget::SHARED_LIBRARY)
|
||||||
|
&& (ptrIt->second->GetType() != cmTarget::MODULE_LIBRARY))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Writing %s...\n", currentFilename.c_str());
|
||||||
|
this->WriteHeader(str);
|
||||||
|
|
||||||
|
this->WriteConnections(ptrIt->first.c_str(),
|
||||||
|
insertedNodes, insertedConnections, str);
|
||||||
|
this->WriteFooter(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cmGraphVizWriter::WriteGlobalFile(const char* fileName)
|
||||||
|
{
|
||||||
|
cmGeneratedFileStream str(fileName);
|
||||||
|
if ( !str )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->WriteHeader(str);
|
||||||
|
|
||||||
|
fprintf(stderr, "Writing %s...\n", fileName);
|
||||||
|
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 ((ptrIt->second->GetType() != cmTarget::EXECUTABLE)
|
||||||
|
&& (ptrIt->second->GetType() != cmTarget::STATIC_LIBRARY)
|
||||||
|
&& (ptrIt->second->GetType() != cmTarget::SHARED_LIBRARY)
|
||||||
|
&& (ptrIt->second->GetType() != cmTarget::MODULE_LIBRARY))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) const
|
||||||
|
{
|
||||||
|
return (this->TargetsToIgnore.find(name) != this->TargetsToIgnore.end());
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
#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"
|
||||||
|
|
||||||
|
|
||||||
|
/** 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:
|
||||||
|
|
||||||
|
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) const;
|
||||||
|
|
||||||
|
cmStdString GraphType;
|
||||||
|
cmStdString GraphName;
|
||||||
|
cmStdString GraphHeader;
|
||||||
|
cmStdString GraphNodePrefix;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
std::set<cmStdString> TargetsToIgnore;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
336
Source/cmake.cxx
336
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>
|
||||||
|
@ -2836,339 +2837,26 @@ const char* cmake::GetCPackCommand()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void writeNode(const char* targetName, const cmTarget* target,
|
|
||||||
const std::map<cmStdString, cmStdString>& targetNamesNodes,
|
|
||||||
std::set<std::string>& insertedNodes,
|
|
||||||
cmGeneratedFileStream& str)
|
|
||||||
{
|
|
||||||
if (insertedNodes.find(targetName) == insertedNodes.end())
|
|
||||||
{
|
|
||||||
insertedNodes.insert(targetName);
|
|
||||||
std::map<cmStdString, cmStdString>::const_iterator nameIt =
|
|
||||||
targetNamesNodes.find(targetName);
|
|
||||||
|
|
||||||
str << " \"" << nameIt->second.c_str() << "\" [ label=\""
|
|
||||||
<< targetName << "\" shape=\"" << getShapeForTarget(target)
|
|
||||||
<< "\"];" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void cmake::GenerateGraphViz(const char* fileName) const
|
void cmake::GenerateGraphViz(const char* fileName) const
|
||||||
{
|
{
|
||||||
cmake cm;
|
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||||
cmGlobalGenerator ggi;
|
std::auto_ptr<cmGraphVizWriter> gvWriter(
|
||||||
ggi.SetCMakeInstance(&cm);
|
new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators()));
|
||||||
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";
|
|
||||||
if ( !cmSystemTools::FileExists(infile.c_str()) )
|
|
||||||
{
|
|
||||||
infile = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !infile.empty() )
|
gvWriter->ReadSettings(settingsFile.c_str(), fallbackSettingsFile.c_str());
|
||||||
{
|
|
||||||
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) \
|
gvWriter->WritePerTargetFiles(fileName);
|
||||||
const char* var = mf->GetDefinition(cmakeDefinition); \
|
gvWriter->WriteGlobalFile(fileName);
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<cmStdString, const cmTarget*> targetPtrs;
|
#endif
|
||||||
std::map<cmStdString, cmStdString> targetNamesNodes; // maps from the actual strings to node names in dot
|
|
||||||
int cnt = getAllTargets(ignoreTargetsSet, targetNamesNodes, targetPtrs,
|
|
||||||
graphNodePrefix);
|
|
||||||
|
|
||||||
cnt = getAllExternalLibs(ignoreTargetsSet, targetNamesNodes, targetPtrs,
|
|
||||||
graphNodePrefix, cnt);
|
|
||||||
|
|
||||||
for(std::map<cmStdString, const cmTarget*>::const_iterator ptrIt =
|
|
||||||
targetPtrs.begin();
|
|
||||||
ptrIt != targetPtrs.end();
|
|
||||||
++ptrIt)
|
|
||||||
{
|
|
||||||
if (ptrIt->second == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ptrIt->second->GetType() != cmTarget::EXECUTABLE)
|
|
||||||
&& (ptrIt->second->GetType() != cmTarget::STATIC_LIBRARY)
|
|
||||||
&& (ptrIt->second->GetType() != cmTarget::SHARED_LIBRARY)
|
|
||||||
&& (ptrIt->second->GetType() != cmTarget::MODULE_LIBRARY))
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Writing %s...\n", currentFilename.c_str());
|
|
||||||
str << graphType << " " << graphName << " {" << std::endl;
|
|
||||||
str << graphHeader << std::endl;
|
|
||||||
|
|
||||||
writeDotConnections(ptrIt->first.c_str(), targetNamesNodes, targetPtrs,
|
|
||||||
insertedNodes, insertedConnections, str);
|
|
||||||
str << "}" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmGeneratedFileStream str(fileName);
|
|
||||||
if ( !str )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
str << graphType << " " << graphName << " {" << std::endl;
|
|
||||||
str << graphHeader << std::endl;
|
|
||||||
|
|
||||||
fprintf(stderr, "Writing %s...\n", fileName);
|
|
||||||
std::set<std::string> insertedConnections;
|
|
||||||
std::set<std::string> insertedNodes;
|
|
||||||
|
|
||||||
for(std::map<cmStdString, const cmTarget*>::const_iterator ptrIt =
|
|
||||||
targetPtrs.begin();
|
|
||||||
ptrIt != targetPtrs.end();
|
|
||||||
++ptrIt)
|
|
||||||
{
|
|
||||||
if (ptrIt->second == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ptrIt->second->GetType() != cmTarget::EXECUTABLE)
|
|
||||||
&& (ptrIt->second->GetType() != cmTarget::STATIC_LIBRARY)
|
|
||||||
&& (ptrIt->second->GetType() != cmTarget::SHARED_LIBRARY)
|
|
||||||
&& (ptrIt->second->GetType() != cmTarget::MODULE_LIBRARY))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeDotConnections(ptrIt->first.c_str(), targetNamesNodes, targetPtrs,
|
|
||||||
insertedNodes, insertedConnections, str);
|
|
||||||
}
|
|
||||||
str << "}" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void cmake::writeDotConnections(const char* targetName,
|
|
||||||
const std::map<cmStdString, cmStdString>& targetNamesNodes,
|
|
||||||
const std::map<cmStdString, const cmTarget*>& targetPtrs,
|
|
||||||
std::set<std::string>& insertedNodes,
|
|
||||||
std::set<std::string>& insertedConnections,
|
|
||||||
cmGeneratedFileStream& str) const
|
|
||||||
{
|
|
||||||
std::map<cmStdString, const cmTarget* >::const_iterator targetPtrIt =
|
|
||||||
targetPtrs.find(targetName);
|
|
||||||
|
|
||||||
if (targetPtrIt == targetPtrs.end()) // not found at all
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeNode(targetName, targetPtrIt->second, targetNamesNodes, insertedNodes,
|
|
||||||
str);
|
|
||||||
|
|
||||||
if (targetPtrIt->second == NULL) // it's an external library
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string myNodeName = 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 =
|
|
||||||
targetNamesNodes.find(libName);
|
|
||||||
|
|
||||||
std::string connectionName = myNodeName;
|
|
||||||
connectionName += "-";
|
|
||||||
connectionName += libNameIt->second;
|
|
||||||
if (insertedConnections.find(connectionName) == insertedConnections.end())
|
|
||||||
{
|
|
||||||
insertedConnections.insert(connectionName);
|
|
||||||
writeNode(libName, targetPtrs.find(libName)->second, targetNamesNodes,
|
|
||||||
insertedNodes, str);
|
|
||||||
|
|
||||||
str << " \"" << myNodeName.c_str() << "\" -> \""
|
|
||||||
<< libNameIt->second.c_str() << "\"";
|
|
||||||
str << " // " << targetName << " -> " << libName << std::endl;
|
|
||||||
writeDotConnections(libName, targetNamesNodes, targetPtrs, insertedNodes,
|
|
||||||
insertedConnections, str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int cmake::getAllTargets(const std::set<cmStdString>& ignoreTargetsSet,
|
|
||||||
std::map<cmStdString, cmStdString>& targetNamesNodes,
|
|
||||||
std::map<cmStdString, const cmTarget*>& targetPtrs,
|
|
||||||
const char* graphNodePrefix) const
|
|
||||||
{
|
|
||||||
int cnt = 0;
|
|
||||||
const std::vector<cmLocalGenerator*>& localGenerators =
|
|
||||||
this->GetGlobalGenerator()->GetLocalGenerators();
|
|
||||||
// First pass get the list of all cmake targets
|
|
||||||
for (std::vector<cmLocalGenerator*>::const_iterator lit =
|
|
||||||
localGenerators.begin();
|
|
||||||
lit != 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 ( 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int cmake::getAllExternalLibs(const std::set<cmStdString>& ignoreTargetsSet,
|
|
||||||
std::map<cmStdString, cmStdString>& targetNamesNodes,
|
|
||||||
std::map<cmStdString, const cmTarget*>& targetPtrs,
|
|
||||||
const char* graphNodePrefix, int cnt) const
|
|
||||||
{
|
|
||||||
const std::vector<cmLocalGenerator*>& localGenerators =
|
|
||||||
this->GetGlobalGenerator()->GetLocalGenerators();
|
|
||||||
// Ok, now find all the stuff we link to that is not in cmake
|
|
||||||
for (std::vector<cmLocalGenerator*>::const_iterator lit =
|
|
||||||
localGenerators.begin();
|
|
||||||
lit != 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 ( ignoreTargetsSet.find(realTargetName) != ignoreTargetsSet.end() )
|
|
||||||
{
|
|
||||||
// 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 ( ignoreTargetsSet.find(libName) != ignoreTargetsSet.end() )
|
|
||||||
{
|
|
||||||
// Skip ignored targets
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<cmStdString, const cmTarget*>::const_iterator tarIt =
|
|
||||||
targetPtrs.find(libName);
|
|
||||||
if ( tarIt == targetPtrs.end() )
|
|
||||||
{
|
|
||||||
cmOStringStream ostr;
|
|
||||||
ostr << graphNodePrefix << cnt++;
|
|
||||||
targetNamesNodes[libName] = ostr.str();
|
|
||||||
targetPtrs[libName] = NULL;
|
|
||||||
//str << " \"" << ostr.c_str() << "\" [ label=\"" << libName
|
|
||||||
//<< "\" shape=\"ellipse\"];" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
int cmake::SymlinkLibrary(std::vector<std::string>& args)
|
int cmake::SymlinkLibrary(std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
|
|
|
@ -433,23 +433,6 @@ protected:
|
||||||
int* retCodeOut = 0);
|
int* retCodeOut = 0);
|
||||||
cmVariableWatch* VariableWatch;
|
cmVariableWatch* VariableWatch;
|
||||||
|
|
||||||
int getAllTargets(const std::set<cmStdString>& ignoreTargetsSet,
|
|
||||||
std::map<cmStdString, cmStdString>& targetNamesNodes,
|
|
||||||
std::map<cmStdString, const cmTarget*>& targetPtrs,
|
|
||||||
const char* graphNodePrefix) const;
|
|
||||||
|
|
||||||
int getAllExternalLibs(const std::set<cmStdString>& ignoreTargetsSet,
|
|
||||||
std::map<cmStdString, cmStdString>& targetNamesNodes,
|
|
||||||
std::map<cmStdString, const cmTarget*>& targetPtrs,
|
|
||||||
const char* graphNodePrefix, int cnt) const;
|
|
||||||
|
|
||||||
void writeDotConnections(const char* targetName,
|
|
||||||
const std::map<cmStdString, cmStdString>& targetNamesNodes,
|
|
||||||
const std::map<cmStdString, const cmTarget*>& targetPtrs,
|
|
||||||
std::set<std::string>& insertedNodes,
|
|
||||||
std::set<std::string>& insertedConnections,
|
|
||||||
cmGeneratedFileStream& str) const;
|
|
||||||
|
|
||||||
///! Find the full path to one of the cmake programs like ctest, cpack, etc.
|
///! Find the full path to one of the cmake programs like ctest, cpack, etc.
|
||||||
std::string FindCMakeProgram(const char* name) const;
|
std::string FindCMakeProgram(const char* name) const;
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue