diff --git a/Source/cmMakeDepend.cxx b/Source/cmMakeDepend.cxx index 55b3d90f1..9b181e958 100644 --- a/Source/cmMakeDepend.cxx +++ b/Source/cmMakeDepend.cxx @@ -42,6 +42,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cmStandardIncludes.h" #include "cmSystemTools.h" + +void cmDependInformation::AddDependencies(cmDependInformation* info) +{ + if(this != info) + { + m_DependencySet.insert(info); + for (cmDependInformation::DependencySet::const_iterator + d = info->m_DependencySet.begin(); + d != info->m_DependencySet.end(); ++d) + { + m_DependencySet.insert(*d); + } + } +} + cmMakeDepend::cmMakeDepend() { m_Verbose = false; @@ -52,12 +67,11 @@ cmMakeDepend::cmMakeDepend() cmMakeDepend::~cmMakeDepend() { - for(DependArray::iterator i = m_DependInformation.begin(); - i != m_DependInformation.end(); ++i) + for(DependInformationMap::iterator i = m_DependInformationMap.begin(); + i != m_DependInformationMap.end(); ++i) { - delete *i; + delete i->second; } - m_DependInformation.clear(); } @@ -76,114 +90,57 @@ void cmMakeDepend::SetMakefile(const cmMakefile* makefile) m_Makefile->m_ComplainFileRegularExpression.c_str()); // Now extract any include paths from the makefile flags - const std::vector& includes = m_Makefile->GetIncludeDirectories(); - std::vector::const_iterator j; - for(j = includes.begin(); j != includes.end(); ++j) + const std::vector& includes = + m_Makefile->GetIncludeDirectories(); + for(std::vector::const_iterator j = includes.begin(); + j != includes.end(); ++j) { this->AddSearchPath(j->c_str()); } - - // Now create cmDependInformation objects for files in the directory - const cmTargets &tgts = m_Makefile->GetTargets(); - for(cmTargets::const_iterator l = tgts.begin(); - l != tgts.end(); l++) - { - const std::vector &classes = l->second.GetSourceFiles(); - for(std::vector::const_iterator i = classes.begin(); - i != classes.end(); ++i) - { - if(!i->GetIsAHeaderFileOnly()) - { - cmDependInformation* info = new cmDependInformation; - info->m_FullPath = this->FullPath(i->GetFullPath().c_str()); - this->AddFileToSearchPath(info->m_FullPath.c_str()); - info->m_IncludeName = i->GetFullPath(); - info->m_ClassFileIndex = &*i; - m_DependInformation.push_back(info); - } - } - } } -// Compute the depends. -void cmMakeDepend::GenerateDependInformation() +const cmDependInformation* cmMakeDepend::FindDependencies(const char* file) { - // The size of the m_DependInformation will change as - // Depend is called so do not use an iterater but rather - // depend on the size of the array. - unsigned int j = 0; - while(j != m_DependInformation.size()) - { - cmDependInformation* info = m_DependInformation[j]; - // compute the depend information for the info object - // this may add more objects to the m_DependInformation - // array - this->Depend(info); - ++j; - } + cmDependInformation* info = this->GetDependInformation(file); + this->GenerateDependInformation(info); + return info; } -const cmDependInformation * -cmMakeDepend::GetDependInformationForSourceFile(const cmSourceFile &sf) const +void cmMakeDepend::GenerateDependInformation(cmDependInformation* info) { - // Now update the depend information for each cmSourceFile - // in the cmMakefile m_Makefile - for(DependArray::const_iterator i = m_DependInformation.begin(); - i != m_DependInformation.end(); ++i) + // If dependencies are already done, stop now. + if(info->m_DependDone) { - cmDependInformation* info = *i; - // find the class - if(info->m_ClassFileIndex == &sf) - { - return info; - } + return; } - return 0; -} - -const cmDependInformation * -cmMakeDepend::GetDependInformationForSourceFile(const char *fname) const -{ - // Now update the depend information for each cmSourceFile - // in the cmMakefile m_Makefile - for(DependArray::const_iterator i = m_DependInformation.begin(); - i != m_DependInformation.end(); ++i) + else { - cmDependInformation* info = *i; - // find the class - if(info->m_FullPath == fname) - { - return info; - } + // Make sure we don't visit the same file more than once. + info->m_DependDone = true; } - return 0; -} - -void cmMakeDepend::Depend(cmDependInformation* info) -{ + const char* path = info->m_FullPath.c_str(); if(!path) { - cmSystemTools::Error("no full path for object", 0); + cmSystemTools::Error("Attempt to find dependencies for file without path!"); return; } - + // If the file exists, use it to find dependency information. if(cmSystemTools::FileExists(path)) { // Use the real file to find its dependencies. - this->DependWalk(info, path); - info->m_DependDone = true; + this->DependWalk(info); return; } // The file doesn't exist. See if the cmSourceFile for it has any files // specified as dependency hints. - if(info->m_ClassFileIndex != 0) + if(info->m_cmSourceFile != 0) { // Get the cmSourceFile corresponding to this. - const cmSourceFile& cFile = *(info->m_ClassFileIndex); + const cmSourceFile& cFile = *(info->m_cmSourceFile); // See if there are any hints for finding dependencies for the missing // file. if(!cFile.GetDepends().empty()) @@ -212,24 +169,24 @@ void cmMakeDepend::Depend(cmDependInformation* info) // Destroy the name of the file so that it won't be output as a // dependency. info->m_FullPath = ""; - } + } } - // This function actually reads the file specified and scans it for // #include directives -void cmMakeDepend::DependWalk(cmDependInformation* info, const char* file) +void cmMakeDepend::DependWalk(cmDependInformation* info) { cmRegularExpression includeLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]"); - std::ifstream fin(file); + std::ifstream fin(info->m_FullPath.c_str()); if(!fin) { - cmSystemTools::Error("error can not open ", file); + cmSystemTools::Error("Cannot open ", info->m_FullPath.c_str()); return; } - + + // TODO: Write real read loop (see cmSystemTools::CopyFile). char line[255]; - for(fin.getline(line, 255); !fin.eof()&&!fin.fail(); fin.getline(line, 255)) + for(fin.getline(line, 255); fin; fin.getline(line, 255)) { if(includeLine.find(line)) { @@ -243,7 +200,7 @@ void cmMakeDepend::DependWalk(cmDependInformation* info, const char* file) std::string message = "Skipping "; message += includeFile; message += " for file "; - message += file; + message += info->m_FullPath.c_str(); cmSystemTools::Error(message.c_str(), 0); } continue; @@ -258,68 +215,60 @@ void cmMakeDepend::DependWalk(cmDependInformation* info, const char* file) void cmMakeDepend::AddDependency(cmDependInformation* info, const char* file) { - // find the index of the include file in the - // m_DependInformation array, if it is not - // there then FindInformation will create it - int index = this->FindInformation(file); - // add the index to the depends of the current - // depend info object - info->m_IndexSet.insert(index); - // Get the depend information object for the include file - cmDependInformation* dependInfo = m_DependInformation[index]; - // if the depends are not known for an include file, then compute them - // recursively - if(!dependInfo->m_DependDone) - { - // stop the recursion here - dependInfo->m_DependDone = true; - this->Depend(dependInfo); - } - // add the depends of the included file to the includer - info->MergeInfo(dependInfo); + cmDependInformation* dependInfo = this->GetDependInformation(file); + this->GenerateDependInformation(dependInfo); + info->AddDependencies(dependInfo); } - -// Find the cmDependInformation array index of the -// given include file. Create a new cmDependInformation -// object if one is not found -int cmMakeDepend::FindInformation(const char* fname) +cmDependInformation* cmMakeDepend::GetDependInformation(const char* file) { - unsigned int i = 0; + // Get the full path for the file so that lookup is unambiguous. + std::string fullPath = this->FullPath(file); - while(i < m_DependInformation.size()) + // Try to find the file's instance of cmDependInformation. + DependInformationMap::const_iterator result = + m_DependInformationMap.find(fullPath); + if(result != m_DependInformationMap.end()) { - if(m_DependInformation[i]->m_IncludeName == fname) - { - return i; - } - ++i; + // Found an instance, return it. + return result->second; + } + else + { + // Didn't find an instance. Create a new one and save it. + cmDependInformation* info = new cmDependInformation; + info->m_FullPath = fullPath; + info->m_IncludeName = file; + m_DependInformationMap[fullPath] = info; + return info; } - cmDependInformation* newinfo = new cmDependInformation; - newinfo->m_FullPath = this->FullPath(fname); - // Add the directory where this file was found to the search path - // may have been foo/bar.h, but bar may include files from the foo - // directory without the foo prefix - this->AddFileToSearchPath(newinfo->m_FullPath.c_str()); - newinfo->m_IncludeName = fname; - m_DependInformation.push_back(newinfo); - return m_DependInformation.size()-1; } -// add the depend information from info to the m_IndexSet varible of this class. -void cmDependInformation::MergeInfo(cmDependInformation* info) +void cmMakeDepend::GenerateMakefileDependencies() { - if(this != info) + // Now create cmDependInformation objects for files in the directory + const cmTargets &tgts = m_Makefile->GetTargets(); + for(cmTargets::const_iterator l = tgts.begin(); + l != tgts.end(); l++) { - for (std::set::const_iterator p = info->m_IndexSet.begin(); - p != info->m_IndexSet.end(); ++p) + const std::vector &classes = l->second.GetSourceFiles(); + for(std::vector::const_iterator i = classes.begin(); + i != classes.end(); ++i) { - m_IndexSet.insert(*p); + if(!i->GetIsAHeaderFileOnly()) + { + cmDependInformation* info = + this->GetDependInformation(i->GetFullPath().c_str()); + this->AddFileToSearchPath(info->m_FullPath.c_str()); + info->m_cmSourceFile = &*i; + this->GenerateDependInformation(info); + } } } } + // find the full path to fname by searching the m_IncludeDirectories array std::string cmMakeDepend::FullPath(const char* fname) { @@ -368,4 +317,17 @@ void cmMakeDepend::AddFileToSearchPath(const char* file) } } - +const cmDependInformation* +cmMakeDepend::GetDependInformationForSourceFile(const cmSourceFile &sf) const +{ + for(DependInformationMap::const_iterator i = m_DependInformationMap.begin(); + i != m_DependInformationMap.end(); ++i) + { + const cmDependInformation* info = i->second; + if(info->m_cmSourceFile == &sf) + { + return info; + } + } + return 0; +} diff --git a/Source/cmMakeDepend.h b/Source/cmMakeDepend.h index b49f8cd25..fabb47fa2 100644 --- a/Source/cmMakeDepend.h +++ b/Source/cmMakeDepend.h @@ -58,46 +58,40 @@ public: * Construct with dependency generation marked not done; instance * not placed in cmMakefile's list. */ - cmDependInformation() - { - m_DependDone = false; - m_ClassFileIndex = 0; - } + cmDependInformation(): m_DependDone(false), m_cmSourceFile(0) {} /** - * A set of indices into the m_DependInformation array of cmMakeDepend. - * The index represents the files that this file depends on. - * This must be a "set" to keep indices unique. + * The set of files on which this one depends. */ - typedef std::set IndexSet; - IndexSet m_IndexSet; + typedef std::set DependencySet; + DependencySet m_DependencySet; - /** - * Full path to this file. - */ - std::string m_FullPath; - - /** - * Name that the include directive uses. - */ - std::string m_IncludeName; - - /** - * The index into the cmMakefile::m_Classes list. - * The index value of 0 indicates that it is not in the list. - */ - const cmSourceFile *m_ClassFileIndex; - /** * This flag indicates whether dependency checking has been * performed for this file. */ bool m_DependDone; + + /** + * If this object corresponds to a cmSourceFile instance, this points + * to it. + */ + const cmSourceFile *m_cmSourceFile; + + /** + * Full path to this file. + */ + std::string m_FullPath; + + /** + * Name used to #include this file. + */ + std::string m_IncludeName; /** * This method adds the dependencies of another file to this one. */ - void MergeInfo(cmDependInformation*); + void AddDependencies(cmDependInformation*); }; @@ -121,59 +115,60 @@ public: */ virtual void SetMakefile(const cmMakefile* makefile); - /** - * Generate the depend information - */ - virtual void GenerateDependInformation(); - /** * Get the depend info struct for a source file */ const cmDependInformation *GetDependInformationForSourceFile(const cmSourceFile &sf) const; - const cmDependInformation *GetDependInformationForSourceFile(const char *) const; - - /** - * Get the depend info struct - */ - typedef std::vector DependArray; - const DependArray &GetDependInformation() const { - return m_DependInformation; } /** * Add a directory to the search path for include files. */ virtual void AddSearchPath(const char*); + /** + * Generate dependencies for all the sources of all the targets + * in the makefile. + */ + void GenerateMakefileDependencies(); + + /** + * Generate dependencies for the file given. Returns a pointer to + * the cmDependInformation object for the file. + */ + const cmDependInformation* FindDependencies(const char* file); + protected: /** * Add a source file to the search path. */ void AddFileToSearchPath(const char* filepath); - /** - * Find the index into the m_DependInformation array - * that matches the given m_IncludeName. - */ - virtual int FindInformation(const char* includeName); - /** * Compute the depend information for this class. */ - virtual void Depend(cmDependInformation* info); - - /** - * Compute the depend information for this class. - */ - virtual void DependWalk(cmDependInformation* info, const char* file); + virtual void DependWalk(cmDependInformation* info); /** * Add a dependency. Possibly walk it for more dependencies. */ virtual void AddDependency(cmDependInformation* info, const char* file); - + + /** + * Fill in the given object with dependency information. If the + * information is already complete, nothing is done. + */ + void GenerateDependInformation(cmDependInformation* info); + + /** + * Get an instance of cmDependInformation corresponding to the given file + * name. + */ + cmDependInformation* GetDependInformation(const char* file); + /** * Find the full path name for the given file name. * This uses the include directories. + * TODO: Cache path conversions to reduce FileExists calls. */ std::string FullPath(const char*); @@ -181,8 +176,9 @@ protected: bool m_Verbose; cmRegularExpression m_IncludeFileRegularExpression; cmRegularExpression m_ComplainFileRegularExpression; - DependArray m_DependInformation; std::vector m_IncludeDirectories; + typedef std::map DependInformationMap; + DependInformationMap m_DependInformationMap; }; #endif diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index a99858125..d796ad73a 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -46,15 +46,15 @@ class cmLBDepend : public cmMakeDepend /** * Compute the depend information for this class. */ - void DependWalk(cmDependInformation* info, const char* file); + virtual void DependWalk(cmDependInformation* info); }; -void cmLBDepend::DependWalk(cmDependInformation* info, const char* file) +void cmLBDepend::DependWalk(cmDependInformation* info) { - std::ifstream fin(file); + std::ifstream fin(info->m_FullPath.c_str()); if(!fin) { - cmSystemTools::Error("error can not open ", file); + cmSystemTools::Error("error can not open ", info->m_FullPath.c_str()); return; } @@ -98,7 +98,7 @@ void cmLBDepend::DependWalk(cmDependInformation* info, const char* file) std::string message = "Skipping "; message += includeFile; message += " for file "; - message += file; + message += info->m_FullPath.c_str(); cmSystemTools::Error(message.c_str(), 0); } continue; @@ -208,28 +208,27 @@ void cmOutputRequiredFilesCommand::FinalPass() // compute the list of files cmLBDepend md; md.SetMakefile(m_Makefile); - md.GenerateDependInformation(); // always expand the first argument m_Makefile->ExpandVariablesInString(m_File); m_Makefile->ExpandVariablesInString(m_OutputFile); // find the depends for a file - const cmDependInformation *info = md.GetDependInformationForSourceFile(m_File.c_str()); + const cmDependInformation *info = md.FindDependencies(m_File.c_str()); if (info) { // write them out FILE *fout = fopen(m_OutputFile.c_str(),"w"); - for( cmDependInformation::IndexSet::const_iterator indx = - info->m_IndexSet.begin(); - indx != info->m_IndexSet.end(); ++indx) + for(cmDependInformation::DependencySet::const_iterator d = + info->m_DependencySet.begin(); + d != info->m_DependencySet.end(); ++d) { - std::string tmp = md.GetDependInformation()[*indx]->m_FullPath; + std::string tmp = (*d)->m_FullPath; std::string::size_type pos = tmp.rfind('.'); if(pos != std::string::npos && tmp.substr(pos) == ".cxx") { tmp = tmp.substr(0, pos); - fprintf(fout,"%s\n",md.GetDependInformation()[*indx]->m_FullPath.c_str()); + fprintf(fout,"%s\n",(*d)->m_FullPath.c_str()); } } fclose(fout); diff --git a/Source/cmUnixMakefileGenerator.cxx b/Source/cmUnixMakefileGenerator.cxx index b5799d6f0..5a93a3817 100644 --- a/Source/cmUnixMakefileGenerator.cxx +++ b/Source/cmUnixMakefileGenerator.cxx @@ -95,7 +95,7 @@ void cmUnixMakefileGenerator::GenerateMakefile() // Generate depends cmMakeDepend md; md.SetMakefile(m_Makefile); - md.GenerateDependInformation(); + md.GenerateMakefileDependencies(); this->ProcessDepends(md); // output the makefile fragment this->OutputMakefile("Makefile"); @@ -124,15 +124,15 @@ void cmUnixMakefileGenerator::ProcessDepends(const cmMakeDepend &md) // Now add the real dependencies for the file. if (info) { - for( cmDependInformation::IndexSet::const_iterator indx = - info->m_IndexSet.begin(); - indx != info->m_IndexSet.end(); ++indx) + for(cmDependInformation::DependencySet::const_iterator d = + info->m_DependencySet.begin(); + d != info->m_DependencySet.end(); ++d) { // Make sure the full path is given. If not, the dependency was // not found. - if(md.GetDependInformation()[*indx]->m_FullPath != "") + if((*d)->m_FullPath != "") { - i->GetDepends().push_back(md.GetDependInformation()[*indx]->m_FullPath); + i->GetDepends().push_back((*d)->m_FullPath); } } }