cmake/Source/cmGraphVizWriter.cxx

591 lines
18 KiB
C++
Raw Normal View History

2016-10-30 18:24:19 +01:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
2011-01-16 11:35:12 +01:00
#include "cmGraphVizWriter.h"
2018-01-26 17:06:56 +01:00
#include <cstddef>
2017-04-14 19:02:05 +02:00
#include <iostream>
2018-01-26 17:06:56 +01:00
#include <memory> // IWYU pragma: keep
2017-04-14 19:02:05 +02:00
#include <sstream>
#include <utility>
2016-07-09 11:21:54 +02:00
#include "cmGeneratedFileStream.h"
2016-10-30 18:24:19 +01:00
#include "cmGeneratorTarget.h"
2016-07-09 11:21:54 +02:00
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
2017-04-14 19:02:05 +02:00
#include "cmStateSnapshot.h"
2016-10-30 18:24:19 +01:00
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
2018-01-26 17:06:56 +01:00
namespace {
enum LinkLibraryScopeType
{
LLT_SCOPE_PUBLIC,
LLT_SCOPE_PRIVATE,
LLT_SCOPE_INTERFACE
};
const char* const GRAPHVIZ_PRIVATE_EDEGE_STYLE = "dashed";
const char* const GRAPHVIZ_INTERFACE_EDEGE_STYLE = "dotted";
std::string getLinkLibraryStyle(const LinkLibraryScopeType& type)
{
std::string style;
switch (type) {
case LLT_SCOPE_PRIVATE:
style = "[style = " + std::string(GRAPHVIZ_PRIVATE_EDEGE_STYLE) + "]";
break;
case LLT_SCOPE_INTERFACE:
style = "[style = " + std::string(GRAPHVIZ_INTERFACE_EDEGE_STYLE) + "]";
break;
default:
break;
}
return style;
}
const char* getShapeForTarget(const cmGeneratorTarget* target)
2011-01-16 11:35:12 +01:00
{
2016-07-09 11:21:54 +02:00
if (!target) {
2011-01-16 11:35:12 +01:00
return "ellipse";
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
2016-07-09 11:21:54 +02:00
switch (target->GetType()) {
2017-04-14 19:02:05 +02:00
case cmStateEnums::EXECUTABLE:
2011-01-16 11:35:12 +01:00
return "house";
2017-04-14 19:02:05 +02:00
case cmStateEnums::STATIC_LIBRARY:
2011-01-16 11:35:12 +01:00
return "diamond";
2017-04-14 19:02:05 +02:00
case cmStateEnums::SHARED_LIBRARY:
2011-01-16 11:35:12 +01:00
return "polygon";
2017-04-14 19:02:05 +02:00
case cmStateEnums::MODULE_LIBRARY:
2011-01-16 11:35:12 +01:00
return "octagon";
default:
break;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
return "box";
}
2018-01-26 17:06:56 +01:00
std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget(
cmTarget* Target)
{
char sep = ';';
std::map<std::string, LinkLibraryScopeType> tokens;
size_t start = 0, end = 0;
const char* pInterfaceLinkLibraries =
Target->GetProperty("INTERFACE_LINK_LIBRARIES");
const char* pLinkLibraries = Target->GetProperty("LINK_LIBRARIES");
if (!pInterfaceLinkLibraries && !pLinkLibraries) {
return tokens; // target is not linked against any other libraries
}
// make sure we don't touch a null-ptr
auto interfaceLinkLibraries =
std::string(pInterfaceLinkLibraries ? pInterfaceLinkLibraries : "");
auto linkLibraries = std::string(pLinkLibraries ? pLinkLibraries : "");
// first extract interfaceLinkLibraries
while (start < interfaceLinkLibraries.length()) {
if ((end = interfaceLinkLibraries.find(sep, start)) == std::string::npos) {
end = interfaceLinkLibraries.length();
}
std::string element = interfaceLinkLibraries.substr(start, end - start);
if (std::string::npos == element.find("$<LINK_ONLY:", 0)) {
// we assume first, that this library is an interface library.
// if we find it again in the linklibraries property, we promote it to an
// public library.
tokens[element] = LLT_SCOPE_INTERFACE;
} else {
// this is an private linked static library.
// we take care of this case in the second iterator.
}
start = end + 1;
}
// second extract linkLibraries
start = 0;
while (start < linkLibraries.length()) {
if ((end = linkLibraries.find(sep, start)) == std::string::npos) {
end = linkLibraries.length();
}
std::string element = linkLibraries.substr(start, end - start);
if (tokens.find(element) == tokens.end()) {
// this library is not found in interfaceLinkLibraries but in
// linkLibraries.
// this results in a private linked library.
tokens[element] = LLT_SCOPE_PRIVATE;
} else if (LLT_SCOPE_INTERFACE == tokens[element]) {
// this library is found in interfaceLinkLibraries and linkLibraries.
// this results in a public linked library.
tokens[element] = LLT_SCOPE_PUBLIC;
} else {
// private and public linked libraries should not be changed anymore.
}
start = end + 1;
}
return tokens;
}
}
2016-07-09 11:21:54 +02:00
cmGraphVizWriter::cmGraphVizWriter(
const std::vector<cmLocalGenerator*>& localGenerators)
: GraphType("digraph")
, GraphName("GG")
, GraphHeader("node [\n fontsize = \"12\"\n];")
, GraphNodePrefix("node")
, LocalGenerators(localGenerators)
, GenerateForExecutables(true)
, GenerateForStaticLibs(true)
, GenerateForSharedLibs(true)
, GenerateForModuleLibs(true)
2018-01-26 17:06:56 +01:00
, GenerateForInterface(true)
2016-07-09 11:21:54 +02:00
, GenerateForExternals(true)
, GeneratePerTarget(true)
, GenerateDependers(true)
, HaveTargetsAndLibs(false)
2011-01-16 11:35:12 +01:00
{
}
void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
const char* fallbackSettingsFileName)
{
2017-07-20 19:35:53 +02:00
cmake cm(cmake::RoleScript);
2015-08-17 11:37:30 +02:00
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
2016-03-13 13:35:51 +01:00
cm.GetCurrentSnapshot().SetDefaultDefinitions();
2015-08-17 11:37:30 +02:00
cmGlobalGenerator ggi(&cm);
2018-01-26 17:06:56 +01:00
cmMakefile mf(&ggi, cm.GetCurrentSnapshot());
std::unique_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator(&mf));
2011-01-16 11:35:12 +01:00
const char* inFileName = settingsFileName;
2016-07-09 11:21:54 +02:00
if (!cmSystemTools::FileExists(inFileName)) {
2011-01-16 11:35:12 +01:00
inFileName = fallbackSettingsFileName;
2016-07-09 11:21:54 +02:00
if (!cmSystemTools::FileExists(inFileName)) {
2011-01-16 11:35:12 +01:00
return;
}
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
2018-01-26 17:06:56 +01:00
if (!mf.ReadListFile(inFileName)) {
2011-01-16 11:35:12 +01:00
cmSystemTools::Error("Problem opening GraphViz options file: ",
inFileName);
return;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
std::cout << "Reading GraphViz options file: " << inFileName << std::endl;
2016-07-09 11:21:54 +02:00
#define __set_if_set(var, cmakeDefinition) \
{ \
2018-01-26 17:06:56 +01:00
const char* value = mf.GetDefinition(cmakeDefinition); \
2016-07-09 11:21:54 +02:00
if (value) { \
2016-10-30 18:24:19 +01:00
(var) = value; \
2016-07-09 11:21:54 +02:00
} \
2011-01-16 11:35:12 +01:00
}
__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");
2016-07-09 11:21:54 +02:00
#define __set_bool_if_set(var, cmakeDefinition) \
{ \
2018-01-26 17:06:56 +01:00
const char* value = mf.GetDefinition(cmakeDefinition); \
2016-07-09 11:21:54 +02:00
if (value) { \
2018-01-26 17:06:56 +01:00
(var) = mf.IsOn(cmakeDefinition); \
2016-07-09 11:21:54 +02:00
} \
2011-01-16 11:35:12 +01:00
}
__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");
2011-06-19 15:41:06 +03:00
__set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS");
2018-01-26 17:06:56 +01:00
__set_bool_if_set(this->GenerateForInterface, "GRAPHVIZ_INTERFACE");
2011-06-19 15:41:06 +03:00
__set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS");
2014-08-03 19:52:23 +02:00
__set_bool_if_set(this->GeneratePerTarget, "GRAPHVIZ_GENERATE_PER_TARGET");
__set_bool_if_set(this->GenerateDependers, "GRAPHVIZ_GENERATE_DEPENDERS");
2011-01-16 11:35:12 +01:00
2015-04-27 22:25:09 +02:00
std::string ignoreTargetsRegexes;
2011-06-19 15:41:06 +03:00
__set_if_set(ignoreTargetsRegexes, "GRAPHVIZ_IGNORE_TARGETS");
this->TargetsToIgnoreRegex.clear();
2016-07-09 11:21:54 +02:00
if (!ignoreTargetsRegexes.empty()) {
2011-06-19 15:41:06 +03:00
std::vector<std::string> ignoreTargetsRegExVector;
cmSystemTools::ExpandListArgument(ignoreTargetsRegexes,
ignoreTargetsRegExVector);
2018-01-26 17:06:56 +01:00
for (std::string const& currentRegexString : ignoreTargetsRegExVector) {
2011-06-19 15:41:06 +03:00
cmsys::RegularExpression currentRegex;
2018-04-23 21:13:27 +02:00
if (!currentRegex.compile(currentRegexString)) {
2011-06-19 15:41:06 +03:00
std::cerr << "Could not compile bad regex \"" << currentRegexString
<< "\"" << std::endl;
2011-01-16 11:35:12 +01:00
}
2018-04-23 21:13:27 +02:00
this->TargetsToIgnoreRegex.push_back(std::move(currentRegex));
2011-01-16 11:35:12 +01:00
}
2016-07-09 11:21:54 +02:00
}
2011-06-19 15:41:06 +03:00
}
// Iterate over all targets and write for each one a graph which shows
// which other targets depend on it.
void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName)
{
2016-10-30 18:24:19 +01:00
if (!this->GenerateDependers) {
2014-08-03 19:52:23 +02:00
return;
2016-07-09 11:21:54 +02:00
}
2014-08-03 19:52:23 +02:00
2011-06-19 15:41:06 +03:00
this->CollectTargetsAndLibs();
2018-01-26 17:06:56 +01:00
for (auto const& ptr : this->TargetPtrs) {
if (ptr.second == nullptr) {
2011-06-19 15:41:06 +03:00
continue;
2016-07-09 11:21:54 +02:00
}
2011-06-19 15:41:06 +03:00
2018-01-26 17:06:56 +01:00
if (!this->GenerateForTargetType(ptr.second->GetType())) {
2011-06-19 15:41:06 +03:00
continue;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
2011-06-19 15:41:06 +03:00
std::string currentFilename = fileName;
currentFilename += ".";
2018-01-26 17:06:56 +01:00
currentFilename += ptr.first;
2011-06-19 15:41:06 +03:00
currentFilename += ".dependers";
cmGeneratedFileStream str(currentFilename.c_str());
2016-07-09 11:21:54 +02:00
if (!str) {
2011-06-19 15:41:06 +03:00
return;
2016-07-09 11:21:54 +02:00
}
2011-06-19 15:41:06 +03:00
std::set<std::string> insertedConnections;
std::set<std::string> insertedNodes;
std::cout << "Writing " << currentFilename << "..." << std::endl;
this->WriteHeader(str);
2018-01-26 17:06:56 +01:00
this->WriteDependerConnections(ptr.first, insertedNodes,
2016-07-09 11:21:54 +02:00
insertedConnections, str);
2011-06-19 15:41:06 +03:00
this->WriteFooter(str);
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
}
2011-06-19 15:41:06 +03:00
// Iterate over all targets and write for each one a graph which shows
// on which targets it depends.
2011-01-16 11:35:12 +01:00
void cmGraphVizWriter::WritePerTargetFiles(const char* fileName)
{
2016-10-30 18:24:19 +01:00
if (!this->GeneratePerTarget) {
2014-08-03 19:52:23 +02:00
return;
2016-07-09 11:21:54 +02:00
}
2014-08-03 19:52:23 +02:00
2011-01-16 11:35:12 +01:00
this->CollectTargetsAndLibs();
2018-01-26 17:06:56 +01:00
for (auto const& ptr : this->TargetPtrs) {
if (ptr.second == nullptr) {
2011-01-16 11:35:12 +01:00
continue;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
2018-01-26 17:06:56 +01:00
if (!this->GenerateForTargetType(ptr.second->GetType())) {
2011-01-16 11:35:12 +01:00
continue;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
std::set<std::string> insertedConnections;
std::set<std::string> insertedNodes;
std::string currentFilename = fileName;
currentFilename += ".";
2018-01-26 17:06:56 +01:00
currentFilename += ptr.first;
2011-01-16 11:35:12 +01:00
cmGeneratedFileStream str(currentFilename.c_str());
2016-07-09 11:21:54 +02:00
if (!str) {
2011-01-16 11:35:12 +01:00
return;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
std::cout << "Writing " << currentFilename << "..." << std::endl;
this->WriteHeader(str);
2018-01-26 17:06:56 +01:00
this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str);
2011-01-16 11:35:12 +01:00
this->WriteFooter(str);
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
}
void cmGraphVizWriter::WriteGlobalFile(const char* fileName)
{
this->CollectTargetsAndLibs();
cmGeneratedFileStream str(fileName);
2016-07-09 11:21:54 +02:00
if (!str) {
2011-01-16 11:35:12 +01:00
return;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
this->WriteHeader(str);
std::cout << "Writing " << fileName << "..." << std::endl;
std::set<std::string> insertedConnections;
std::set<std::string> insertedNodes;
2018-01-26 17:06:56 +01:00
for (auto const& ptr : this->TargetPtrs) {
if (ptr.second == nullptr) {
2011-01-16 11:35:12 +01:00
continue;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
2018-01-26 17:06:56 +01:00
if (!this->GenerateForTargetType(ptr.second->GetType())) {
2011-01-16 11:35:12 +01:00
continue;
}
2016-07-09 11:21:54 +02:00
2018-01-26 17:06:56 +01:00
this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str);
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
this->WriteFooter(str);
}
void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& str) const
{
2016-03-13 13:35:51 +01:00
str << this->GraphType << " \"" << this->GraphName << "\" {" << std::endl;
2011-01-16 11:35:12 +01:00
str << this->GraphHeader << std::endl;
}
void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& str) const
{
str << "}" << std::endl;
}
2016-07-09 11:21:54 +02:00
void cmGraphVizWriter::WriteConnections(
const std::string& targetName, std::set<std::string>& insertedNodes,
std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
2011-01-16 11:35:12 +01:00
{
2016-07-09 11:21:54 +02:00
std::map<std::string, const cmGeneratorTarget*>::const_iterator targetPtrIt =
this->TargetPtrs.find(targetName);
2011-01-16 11:35:12 +01:00
2016-07-09 11:21:54 +02:00
if (targetPtrIt == this->TargetPtrs.end()) // not found at all
{
2011-01-16 11:35:12 +01:00
return;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);
2018-01-26 17:06:56 +01:00
if (targetPtrIt->second == nullptr) // it's an external library
2016-07-09 11:21:54 +02:00
{
2011-01-16 11:35:12 +01:00
return;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
2018-01-26 17:06:56 +01:00
std::map<std::string, LinkLibraryScopeType> ll =
getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target);
2011-01-16 11:35:12 +01:00
2018-01-26 17:06:56 +01:00
for (auto const& llit : ll) {
const char* libName = llit.first.c_str();
2015-04-27 22:25:09 +02:00
std::map<std::string, std::string>::const_iterator libNameIt =
2016-07-09 11:21:54 +02:00
this->TargetNamesNodes.find(libName);
2011-01-16 11:35:12 +01:00
2011-02-19 15:09:36 +02:00
// can happen e.g. if GRAPHVIZ_TARGET_IGNORE_REGEX is used
2016-07-09 11:21:54 +02:00
if (libNameIt == this->TargetNamesNodes.end()) {
2011-02-19 15:09:36 +02:00
continue;
2016-07-09 11:21:54 +02:00
}
2011-02-19 15:09:36 +02:00
2011-01-16 11:35:12 +01:00
std::string connectionName = myNodeName;
connectionName += "-";
connectionName += libNameIt->second;
2016-07-09 11:21:54 +02:00
if (insertedConnections.find(connectionName) ==
insertedConnections.end()) {
2011-01-16 11:35:12 +01:00
insertedConnections.insert(connectionName);
this->WriteNode(libName, this->TargetPtrs.find(libName)->second,
insertedNodes, str);
2016-07-09 11:21:54 +02:00
str << " \"" << myNodeName << "\" -> \"" << libNameIt->second << "\"";
2018-01-26 17:06:56 +01:00
str << getLinkLibraryStyle(llit.second);
2011-01-16 11:35:12 +01:00
str << " // " << targetName << " -> " << libName << std::endl;
this->WriteConnections(libName, insertedNodes, insertedConnections, str);
}
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
}
2016-07-09 11:21:54 +02:00
void cmGraphVizWriter::WriteDependerConnections(
const std::string& targetName, std::set<std::string>& insertedNodes,
std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
2011-06-19 15:41:06 +03:00
{
2016-07-09 11:21:54 +02:00
std::map<std::string, const cmGeneratorTarget*>::const_iterator targetPtrIt =
this->TargetPtrs.find(targetName);
2011-06-19 15:41:06 +03:00
2016-07-09 11:21:54 +02:00
if (targetPtrIt == this->TargetPtrs.end()) // not found at all
{
2011-06-19 15:41:06 +03:00
return;
2016-07-09 11:21:54 +02:00
}
2011-06-19 15:41:06 +03:00
this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);
2018-01-26 17:06:56 +01:00
if (targetPtrIt->second == nullptr) // it's an external library
2016-07-09 11:21:54 +02:00
{
2011-06-19 15:41:06 +03:00
return;
2016-07-09 11:21:54 +02:00
}
2011-06-19 15:41:06 +03:00
std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
// now search who links against me
2018-01-26 17:06:56 +01:00
for (auto const& tptr : this->TargetPtrs) {
if (tptr.second == nullptr) {
2011-06-19 15:41:06 +03:00
continue;
2016-07-09 11:21:54 +02:00
}
2011-06-19 15:41:06 +03:00
2018-01-26 17:06:56 +01:00
if (!this->GenerateForTargetType(tptr.second->GetType())) {
2011-06-19 15:41:06 +03:00
continue;
2016-07-09 11:21:54 +02:00
}
2011-06-19 15:41:06 +03:00
// Now we have a target, check whether it links against targetName.
// If so, draw a connection, and then continue with dependers on that one.
2018-01-26 17:06:56 +01:00
std::map<std::string, LinkLibraryScopeType> ll =
getScopedLinkLibrariesFromTarget(tptr.second->Target);
2011-06-19 15:41:06 +03:00
2018-01-26 17:06:56 +01:00
for (auto const& llit : ll) {
if (llit.first == targetName) {
2011-06-19 15:41:06 +03:00
// So this target links against targetName.
2015-04-27 22:25:09 +02:00
std::map<std::string, std::string>::const_iterator dependerNodeNameIt =
2018-01-26 17:06:56 +01:00
this->TargetNamesNodes.find(tptr.first);
2011-06-19 15:41:06 +03:00
2016-07-09 11:21:54 +02:00
if (dependerNodeNameIt != this->TargetNamesNodes.end()) {
2011-06-19 15:41:06 +03:00
std::string connectionName = dependerNodeNameIt->second;
connectionName += "-";
connectionName += myNodeName;
if (insertedConnections.find(connectionName) ==
2016-07-09 11:21:54 +02:00
insertedConnections.end()) {
2011-06-19 15:41:06 +03:00
insertedConnections.insert(connectionName);
2018-01-26 17:06:56 +01:00
this->WriteNode(tptr.first, tptr.second, insertedNodes, str);
2011-06-19 15:41:06 +03:00
str << " \"" << dependerNodeNameIt->second << "\" -> \""
<< myNodeName << "\"";
2018-01-26 17:06:56 +01:00
str << " // " << targetName << " -> " << tptr.first << std::endl;
str << getLinkLibraryStyle(llit.second);
this->WriteDependerConnections(tptr.first, insertedNodes,
2016-07-09 11:21:54 +02:00
insertedConnections, str);
2011-06-19 15:41:06 +03:00
}
}
2016-07-09 11:21:54 +02:00
break;
2011-06-19 15:41:06 +03:00
}
}
2016-07-09 11:21:54 +02:00
}
2011-06-19 15:41:06 +03:00
}
2015-04-27 22:25:09 +02:00
void cmGraphVizWriter::WriteNode(const std::string& targetName,
2016-03-13 13:35:51 +01:00
const cmGeneratorTarget* target,
2011-01-16 11:35:12 +01:00
std::set<std::string>& insertedNodes,
cmGeneratedFileStream& str) const
{
2016-07-09 11:21:54 +02:00
if (insertedNodes.find(targetName) == insertedNodes.end()) {
2011-01-16 11:35:12 +01:00
insertedNodes.insert(targetName);
2015-04-27 22:25:09 +02:00
std::map<std::string, std::string>::const_iterator nameIt =
2016-07-09 11:21:54 +02:00
this->TargetNamesNodes.find(targetName);
2011-01-16 11:35:12 +01:00
2016-07-09 11:21:54 +02:00
str << " \"" << nameIt->second << "\" [ label=\"" << targetName
<< "\" shape=\"" << getShapeForTarget(target) << "\"];" << std::endl;
2011-01-16 11:35:12 +01:00
}
}
void cmGraphVizWriter::CollectTargetsAndLibs()
{
2016-10-30 18:24:19 +01:00
if (!this->HaveTargetsAndLibs) {
2011-01-16 11:35:12 +01:00
this->HaveTargetsAndLibs = true;
int cnt = this->CollectAllTargets();
2016-07-09 11:21:54 +02:00
if (this->GenerateForExternals) {
2011-06-19 15:41:06 +03:00
this->CollectAllExternalLibs(cnt);
2011-01-16 11:35:12 +01:00
}
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
}
int cmGraphVizWriter::CollectAllTargets()
{
int cnt = 0;
// First pass get the list of all cmake targets
2018-01-26 17:06:56 +01:00
for (cmLocalGenerator* lg : this->LocalGenerators) {
const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
for (cmGeneratorTarget* target : targets) {
const char* realTargetName = target->GetName().c_str();
2016-07-09 11:21:54 +02:00
if (this->IgnoreThisTarget(realTargetName)) {
2011-01-16 11:35:12 +01:00
// Skip ignored targets
continue;
2016-07-09 11:21:54 +02:00
}
2016-10-30 18:24:19 +01:00
// std::cout << "Found target: " << tit->first << std::endl;
2015-04-27 22:25:09 +02:00
std::ostringstream ostr;
2011-01-16 11:35:12 +01:00
ostr << this->GraphNodePrefix << cnt++;
this->TargetNamesNodes[realTargetName] = ostr.str();
2018-01-26 17:06:56 +01:00
this->TargetPtrs[realTargetName] = target;
2011-01-16 11:35:12 +01:00
}
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
return cnt;
}
int cmGraphVizWriter::CollectAllExternalLibs(int cnt)
{
// Ok, now find all the stuff we link to that is not in cmake
2018-01-26 17:06:56 +01:00
for (cmLocalGenerator* lg : this->LocalGenerators) {
const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
for (cmGeneratorTarget* target : targets) {
const char* realTargetName = target->GetName().c_str();
2016-07-09 11:21:54 +02:00
if (this->IgnoreThisTarget(realTargetName)) {
2011-01-16 11:35:12 +01:00
// Skip ignored targets
continue;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
const cmTarget::LinkLibraryVectorType* ll =
2018-01-26 17:06:56 +01:00
&(target->Target->GetOriginalLinkLibraries());
for (auto const& llit : *ll) {
const char* libName = llit.first.c_str();
2016-07-09 11:21:54 +02:00
if (this->IgnoreThisTarget(libName)) {
2011-01-16 11:35:12 +01:00
// Skip ignored targets
continue;
2016-07-09 11:21:54 +02:00
}
2011-01-16 11:35:12 +01:00
2016-07-09 11:21:54 +02:00
std::map<std::string, const cmGeneratorTarget*>::const_iterator tarIt =
this->TargetPtrs.find(libName);
if (tarIt == this->TargetPtrs.end()) {
2015-04-27 22:25:09 +02:00
std::ostringstream ostr;
2011-01-16 11:35:12 +01:00
ostr << this->GraphNodePrefix << cnt++;
this->TargetNamesNodes[libName] = ostr.str();
2018-01-26 17:06:56 +01:00
this->TargetPtrs[libName] = nullptr;
2016-10-30 18:24:19 +01:00
// str << " \"" << ostr << "\" [ label=\"" << libName
2014-08-03 19:52:23 +02:00
// << "\" shape=\"ellipse\"];" << std::endl;
2011-01-16 11:35:12 +01:00
}
}
}
2016-07-09 11:21:54 +02:00
}
return cnt;
2011-01-16 11:35:12 +01:00
}
2015-04-27 22:25:09 +02:00
bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name)
2011-01-16 11:35:12 +01:00
{
2018-01-26 17:06:56 +01:00
for (cmsys::RegularExpression& regEx : this->TargetsToIgnoreRegex) {
2016-07-09 11:21:54 +02:00
if (regEx.is_valid()) {
if (regEx.find(name)) {
2011-06-19 15:41:06 +03:00
return true;
2011-01-16 11:35:12 +01:00
}
}
2016-07-09 11:21:54 +02:00
}
2011-06-19 15:41:06 +03:00
return false;
2011-01-16 11:35:12 +01:00
}
2016-07-09 11:21:54 +02:00
bool cmGraphVizWriter::GenerateForTargetType(
2017-04-14 19:02:05 +02:00
cmStateEnums::TargetType targetType) const
2011-01-16 11:35:12 +01:00
{
2016-07-09 11:21:54 +02:00
switch (targetType) {
2017-04-14 19:02:05 +02:00
case cmStateEnums::EXECUTABLE:
2011-01-16 11:35:12 +01:00
return this->GenerateForExecutables;
2017-04-14 19:02:05 +02:00
case cmStateEnums::STATIC_LIBRARY:
2011-01-16 11:35:12 +01:00
return this->GenerateForStaticLibs;
2017-04-14 19:02:05 +02:00
case cmStateEnums::SHARED_LIBRARY:
2011-01-16 11:35:12 +01:00
return this->GenerateForSharedLibs;
2017-04-14 19:02:05 +02:00
case cmStateEnums::MODULE_LIBRARY:
2011-01-16 11:35:12 +01:00
return this->GenerateForModuleLibs;
2018-01-26 17:06:56 +01:00
case cmStateEnums::INTERFACE_LIBRARY:
return this->GenerateForInterface;
2011-01-16 11:35:12 +01:00
default:
break;
}
return false;
}