| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 | 
							- /*============================================================================
 
-   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"
 
- 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)
 
- ,GenerateForExternals(true)
 
- ,LocalGenerators(localGenerators)
 
- ,HaveTargetsAndLibs(false)
 
- {
 
- }
 
- void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
 
-                                     const char* fallbackSettingsFileName)
 
- {
 
-   cmake cm;
 
-   cmGlobalGenerator ggi;
 
-   ggi.SetCMakeInstance(&cm);
 
-   cmsys::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");
 
-   __set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS");
 
-   cmStdString ignoreTargetsRegexes;
 
-   __set_if_set(ignoreTargetsRegexes, "GRAPHVIZ_IGNORE_TARGETS");
 
-   this->TargetsToIgnoreRegex.clear();
 
-   if (ignoreTargetsRegexes.size() > 0)
 
-     {
 
-     std::vector<std::string> ignoreTargetsRegExVector;
 
-     cmSystemTools::ExpandListArgument(ignoreTargetsRegexes,
 
-                                       ignoreTargetsRegExVector);
 
-     for(std::vector<std::string>::const_iterator itvIt
 
-                                             = ignoreTargetsRegExVector.begin();
 
-         itvIt != ignoreTargetsRegExVector.end();
 
-         ++ itvIt )
 
-       {
 
-       cmStdString currentRegexString(*itvIt);
 
-       cmsys::RegularExpression currentRegex;
 
-       if (!currentRegex.compile(currentRegexString.c_str()))
 
-         {
 
-         std::cerr << "Could not compile bad regex \"" << currentRegexString
 
-                   << "\"" << std::endl;
 
-         }
 
-       this->TargetsToIgnoreRegex.push_back(currentRegex);
 
-       }
 
-     }
 
- }
 
- // 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)
 
- {
 
-   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::string currentFilename = fileName;
 
-     currentFilename += ".";
 
-     currentFilename += ptrIt->first;
 
-     currentFilename += ".dependers";
 
-     cmGeneratedFileStream str(currentFilename.c_str());
 
-     if ( !str )
 
-       {
 
-       return;
 
-       }
 
-     std::set<std::string> insertedConnections;
 
-     std::set<std::string> insertedNodes;
 
-     std::cout << "Writing " << currentFilename << "..." << std::endl;
 
-     this->WriteHeader(str);
 
-     this->WriteDependerConnections(ptrIt->first.c_str(),
 
-                                    insertedNodes, insertedConnections, str);
 
-     this->WriteFooter(str);
 
-     }
 
- }
 
- // Iterate over all targets and write for each one a graph which shows
 
- // on which targets it depends.
 
- 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);
 
-     // can happen e.g. if GRAPHVIZ_TARGET_IGNORE_REGEX is used
 
-     if(libNameIt == this->TargetNamesNodes.end())
 
-       {
 
-       continue;
 
-       }
 
-     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::WriteDependerConnections(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;
 
-   // now search who links against me
 
-   for(std::map<cmStdString, const cmTarget*>::const_iterator dependerIt =
 
-                                                       this->TargetPtrs.begin();
 
-       dependerIt != this->TargetPtrs.end();
 
-       ++dependerIt)
 
-     {
 
-     if (dependerIt->second == NULL)
 
-       {
 
-       continue;
 
-       }
 
-     if (this->GenerateForTargetType(dependerIt->second->GetType()) == false)
 
-       {
 
-       continue;
 
-       }
 
-     // Now we have a target, check whether it links against targetName.
 
-     // If so, draw a connection, and then continue with dependers on that one.
 
-     const cmTarget::LinkLibraryVectorType* ll =
 
-                             &(dependerIt->second->GetOriginalLinkLibraries());
 
-     for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin();
 
-          llit != ll->end();
 
-          ++ llit )
 
-       {
 
-       std::string libName = llit->first.c_str();
 
-       if (libName == targetName)
 
-         {
 
-         // So this target links against targetName.
 
-         std::map<cmStdString, cmStdString>::const_iterator dependerNodeNameIt =
 
-                                 this->TargetNamesNodes.find(dependerIt->first);
 
-         if(dependerNodeNameIt != this->TargetNamesNodes.end())
 
-           {
 
-           std::string connectionName = dependerNodeNameIt->second;
 
-           connectionName += "-";
 
-           connectionName += myNodeName;
 
-           if (insertedConnections.find(connectionName) ==
 
-                                                      insertedConnections.end())
 
-             {
 
-             insertedConnections.insert(connectionName);
 
-             this->WriteNode(dependerIt->first.c_str(), dependerIt->second,
 
-                             insertedNodes, str);
 
-             str << "    \"" << dependerNodeNameIt->second << "\" -> \""
 
-                 << myNodeName << "\"";
 
-             str << " // " <<targetName<< " -> " <<dependerIt->first<<std::endl;
 
-             this->WriteDependerConnections(dependerIt->first.c_str(),
 
-                                       insertedNodes, insertedConnections, str);
 
-             }
 
-           }
 
-         break;
 
-         }
 
-       }
 
-     }
 
- }
 
- 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();
 
-     if (this->GenerateForExternals)
 
-       {
 
-       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)
 
- {
 
-   for(std::vector<cmsys::RegularExpression>::iterator itvIt
 
-                                           = this->TargetsToIgnoreRegex.begin();
 
-       itvIt != this->TargetsToIgnoreRegex.end();
 
-       ++ itvIt )
 
-     {
 
-     cmsys::RegularExpression& regEx = *itvIt;
 
-     if (regEx.is_valid())
 
-       {
 
-       if (regEx.find(name))
 
-         {
 
-         return true;
 
-         }
 
-       }
 
-     }
 
-   return false;
 
- }
 
- 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;
 
- }
 
 
  |