From de2b2bf9efe88bbde1b66857d00538084cc6c591 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Sun, 31 Oct 2010 15:58:18 +0100 Subject: Move the code for collecting targets and libraries into separate functions Found bug: targets which don't link to anything don't get inserted in the dot file. Alex --- Source/cmake.cxx | 208 +++++++++++++++++++++++++++++++++---------------------- Source/cmake.h | 86 +++++++++++++---------- 2 files changed, 175 insertions(+), 119 deletions(-) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index de8db79..6ccb2d2 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2835,6 +2835,11 @@ const char* cmake::GetCPackCommand() return this->CPackCommand.c_str(); } +// for target deps +#define DOT_DEP_TARGET 1 +#define DOT_DEP_EXTERNAL 2 +#define DOT_DEP_NONE 0 + void cmake::GenerateGraphViz(const char* fileName) const { cmGeneratedFileStream str(fileName); @@ -2904,90 +2909,17 @@ void cmake::GenerateGraphViz(const char* fileName) const const cmGlobalGenerator* gg = this->GetGlobalGenerator(); const std::vector& localGenerators = gg->GetLocalGenerators(); - std::vector::const_iterator lit; - // for target deps - // 1 - cmake target - // 2 - external target - // 0 - no deps + std::map targetDeps; std::map targetPtrs; - std::map targetNamesNodes; + std::map targetNamesNodes; // maps from the actual strings to node names in dot 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()); - 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; - } - } + cnt += getAllTargets(ignoreTargetsSet, targetNamesNodes, targetPtrs, + graphNodePrefix); + + cnt += getAllExternalLibs(ignoreTargetsSet, targetNamesNodes, targetPtrs, + targetDeps, graphNodePrefix); - // 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()); - for ( cmTargets::const_iterator tit = targets->begin(); - tit != targets->end(); - ++ tit ) - { - const cmTarget::LinkLibraryVectorType* ll = - &(tit->second.GetOriginalLinkLibraries()); - 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 (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin(); - llit != ll->end(); - ++ llit ) - { - const char* libName = llit->first.c_str(); - std::map::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::const_iterator depIt - = targetDeps.find(libName); - if ( depIt == targetDeps.end() ) - { - targetDeps[libName] = 1; - } - } - } - } - } // Write out nodes for(std::map::const_iterator depIt = targetDeps.begin(); @@ -3008,7 +2940,7 @@ void cmake::GenerateGraphViz(const char* fileName) const str << " \"" << tarIt->second.c_str() << "\" [ label=\"" << newTargetName << "\" shape=\""; - if ( depIt->second == 1 ) + if ( depIt->second == DOT_DEP_TARGET ) { std::map::const_iterator tarTypeIt = targetPtrs.find(newTargetName); @@ -3047,7 +2979,10 @@ void cmake::GenerateGraphViz(const char* fileName) const } // Now generate the connectivity - for ( lit = localGenerators.begin(); lit != localGenerators.end(); ++ lit ) + for ( std::vector::const_iterator lit = + localGenerators.begin(); + lit != localGenerators.end(); + ++ lit ) { const cmTargets* targets = &((*lit)->GetMakefile()->GetTargets()); for (cmTargets::const_iterator tit = targets->begin(); @@ -3092,6 +3027,115 @@ void cmake::GenerateGraphViz(const char* fileName) const str << "}" << std::endl; } + +int cmake::getAllTargets(const std::set& ignoreTargetsSet, + std::map& targetNamesNodes, + std::map& targetPtrs, + const char* graphNodePrefix) const +{ + int cnt = 0; + const std::vector& localGenerators = + this->GetGlobalGenerator()->GetLocalGenerators(); + // First pass get the list of all cmake targets + for (std::vector::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& ignoreTargetsSet, + std::map& targetNamesNodes, + std::map& targetPtrs, + std::map& targetDeps, + const char* graphNodePrefix) const +{ + int cnt = 0; + + const std::vector& localGenerators = + this->GetGlobalGenerator()->GetLocalGenerators(); + // Ok, now find all the stuff we link to that is not in cmake + for (std::vector::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()); + if ( ll->size() > 0 ) + { + targetDeps[realTargetName] = DOT_DEP_TARGET; + fprintf(stderr, " + %s\n", realTargetName); + } + 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::const_iterator tarIt = + targetNamesNodes.find(libName); + if ( tarIt == targetNamesNodes.end() ) + { + cmOStringStream ostr; + ostr << graphNodePrefix << cnt++; + targetDeps[libName] = DOT_DEP_EXTERNAL; + targetNamesNodes[libName] = ostr.str(); + //str << " \"" << ostr.c_str() << "\" [ label=\"" << libName + //<< "\" shape=\"ellipse\"];" << std::endl; + } + else + { + std::map::const_iterator depIt = + targetDeps.find(libName); + if ( depIt == targetDeps.end() ) + { + targetDeps[libName] = DOT_DEP_TARGET; + } + } + } + } + } + return cnt; +} + //---------------------------------------------------------------------------- int cmake::SymlinkLibrary(std::vector& args) { diff --git a/Source/cmake.h b/Source/cmake.h index 8312795..6d6fd94 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -21,14 +21,14 @@ // command line arguments. // 3) Load the cache by calling LoadCache (duh) // 4) if you are using command line arguments with -D or -C flags then -// call SetCacheArgs (or if for some other reason you want to modify the +// call SetCacheArgs (or if for some other reason you want to modify the // cache, do it now. // 5) Finally call Configure // 6) Let the user change values and go back to step 5 // 7) call Generate // // If your GUI allows the user to change the start & home directories then -// you must at a minimum redo steps 2 through 7. +// you must at a minimum redo steps 2 through 7. // @@ -50,6 +50,7 @@ class cmExternalMakefileProjectGenerator; class cmDocumentationSection; class cmPolicies; class cmListFileBacktrace; +class cmTarget; class cmake { @@ -73,14 +74,14 @@ class cmake static const char *GetCMakeFilesDirectory() {return "/CMakeFiles";}; static const char *GetCMakeFilesDirectoryPostSlash() { return "CMakeFiles/";}; - + //@{ /** * Set/Get the home directory (or output directory) in the project. The * home directory is the top directory of the project. It is where * cmake was run. Remember that CMake processes * CMakeLists files by recursing up the tree starting at the StartDirectory - * and going up until it reaches the HomeDirectory. + * and going up until it reaches the HomeDirectory. */ void SetHomeDirectory(const char* dir); const char* GetHomeDirectory() const @@ -100,9 +101,9 @@ class cmake * is the directory of the CMakeLists.txt file that started the current * round of processing. Remember that CMake processes CMakeLists files by * recursing up the tree starting at the StartDirectory and going up until - * it reaches the HomeDirectory. + * it reaches the HomeDirectory. */ - void SetStartDirectory(const char* dir) + void SetStartDirectory(const char* dir) { this->cmStartDirectory = dir; cmSystemTools::ConvertToUnixSlashes(this->cmStartDirectory); @@ -158,7 +159,7 @@ class cmake ///! Return the global generator assigned to this instance of cmake cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; } ///! Return the global generator assigned to this instance of cmake, const - const cmGlobalGenerator* GetGlobalGenerator() const + const cmGlobalGenerator* GetGlobalGenerator() const { return this->GlobalGenerator; } ///! Return the global generator assigned to this instance of cmake @@ -169,25 +170,25 @@ class cmake ///! get the cmCachemManager used by this invocation of cmake cmCacheManager *GetCacheManager() { return this->CacheManager; } - + ///! set the cmake command this instance of cmake should use void SetCMakeCommand(const char* cmd) { this->CMakeCommand = cmd; } - + /** * Given a variable name, return its value (as a string). */ const char* GetCacheDefinition(const char*) const; ///! Add an entry into the cache - void AddCacheEntry(const char* key, const char* value, - const char* helpString, + void AddCacheEntry(const char* key, const char* value, + const char* helpString, int type); - /** + /** * Execute commands during the build process. Supports options such * as echo, remove file etc. */ static int ExecuteCMakeCommand(std::vector&); - /** + /** * Get the system information and write it to the file specified */ int GetSystemInformation(std::vector&); @@ -210,16 +211,16 @@ class cmake /** Check if a command exists. */ bool CommandExists(const char* name) const; - + ///! Parse command line arguments void SetArgs(const std::vector&); ///! Is this cmake running as a result of a TRY_COMPILE command bool GetIsInTryCompile() { return this->InTryCompile; } - + ///! Is this cmake running as a result of a TRY_COMPILE command void SetIsInTryCompile(bool i) { this->InTryCompile = i; } - + ///! Parse command line arguments that might set cache values bool SetCacheArgs(const std::vector&); @@ -227,9 +228,9 @@ class cmake (const char*msg, float progress, void *); /** * Set the function used by GUI's to receive progress updates - * Function gets passed: message as a const char*, a progress + * Function gets passed: message as a const char*, a progress * amount ranging from 0 to 1.0 and client data. The progress - * number provided may be negative in cases where a message is + * number provided may be negative in cases where a message is * to be displayed without any progress percentage. */ void SetProgressCallback(ProgressCallbackType f, void* clientData=0); @@ -244,14 +245,14 @@ class cmake cmVariableWatch* GetVariableWatch() { return this->VariableWatch; } /** Get the documentation entries for the supported commands. - * If withCurrentCommands is true, the documentation for the + * If withCurrentCommands is true, the documentation for the * recommended set of commands is included. * If withCompatCommands is true, the documentation for discouraged * (compatibility) commands is included. * You probably don't want to set both to false. */ - void GetCommandDocumentation(std::vector& entries, - bool withCurrentCommands = true, + void GetCommandDocumentation(std::vector& entries, + bool withCurrentCommands = true, bool withCompatCommands = true) const; void GetPropertiesDocumentation(std::map&); @@ -278,7 +279,7 @@ class cmake */ void SetScriptMode(bool mode) { this->ScriptMode = mode; } bool GetScriptMode() { return this->ScriptMode; } - + ///! Debug the try compile stuff by not delelting the files bool GetDebugTryCompile(){return this->DebugTryCompile;} void DebugTryCompileOn(){this->DebugTryCompile = true;} @@ -310,7 +311,7 @@ class cmake void DefineProperty(const char *name, cmProperty::ScopeType scope, const char *ShortDescription, const char *FullDescription, - bool chain = false, + bool chain = false, const char *variableGroup = 0); // get property definition @@ -338,7 +339,7 @@ class cmake } void SetSuppressDevWarnings(bool v) { - this->SuppressDevWarnings = v; + this->SuppressDevWarnings = v; this->DoSuppressDevWarnings = true; } @@ -357,10 +358,10 @@ protected: cmPropertyMap Properties; std::set > AccessedProperties; - std::map + std::map PropertyDefinitions; - typedef + typedef cmExternalMakefileProjectGenerator* (*CreateExtraGeneratorFunctionType)(); typedef std::map RegisteredExtraGeneratorsMap; @@ -374,15 +375,15 @@ protected: void AddDefaultCommands(); void AddDefaultGenerators(); void AddDefaultExtraGenerators(); - void AddExtraGenerator(const char* name, + void AddExtraGenerator(const char* name, CreateExtraGeneratorFunctionType newFunction); - cmPolicies *Policies; + cmPolicies *Policies; cmGlobalGenerator *GlobalGenerator; cmCacheManager *CacheManager; - std::string cmHomeDirectory; + std::string cmHomeDirectory; std::string HomeOutputDirectory; - std::string cmStartDirectory; + std::string cmStartDirectory; std::string StartOutputDirectory; bool SuppressDevWarnings; bool DoSuppressDevWarnings; @@ -393,7 +394,7 @@ protected: ///! Check if CMAKE_CACHEFILE_DIR is set. If it is not, delete the log file. /// If it is set, truncate it to 50kb void TruncateOutputLog(const char* fname); - + /** * Method called to check build system integrity at build time. * Returns 1 if CMake should rerun and 0 otherwise. @@ -416,24 +417,35 @@ protected: static int ExecuteLinkScript(std::vector& args); static int VisualStudioLink(std::vector& args, int type); static int VisualStudioLinkIncremental(std::vector& args, - int type, + int type, bool verbose); static int VisualStudioLinkNonIncremental(std::vector& args, int type, bool hasManifest, bool verbose); - static int ParseVisualStudioLinkCommand(std::vector& args, - std::vector& command, + static int ParseVisualStudioLinkCommand(std::vector& args, + std::vector& command, std::string& targetName); static bool RunCommand(const char* comment, std::vector& command, bool verbose, int* retCodeOut = 0); cmVariableWatch* VariableWatch; - + + int getAllTargets(const std::set& ignoreTargetsSet, + std::map& targetNamesNodes, + std::map& targetPtrs, + const char* graphNodePrefix) const; + + int getAllExternalLibs(const std::set& ignoreTargetsSet, + std::map& targetNamesNodes, + std::map& targetPtrs, + std::map& targetDeps, + const char* graphNodePrefix) const; + ///! Find the full path to one of the cmake programs like ctest, cpack, etc. std::string FindCMakeProgram(const char* name) const; -private: +private: cmake(const cmake&); // Not implemented. void operator=(const cmake&); // Not implemented. ProgressCallbackType ProgressCallback; @@ -458,7 +470,7 @@ private: cmFileTimeComparison* FileComparison; std::string GraphVizFile; std::vector DebugConfigs; - + void UpdateConversionPathTable(); }; -- cgit v0.12