| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmOutputRequiredFilesCommand.h"
 
- #include <cmsys/FStream.hxx>
 
- #include <cmsys/RegularExpression.hxx>
 
- #include <map>
 
- #include <utility>
 
- #include "cmAlgorithms.h"
 
- #include "cmGeneratorExpression.h"
 
- #include "cmMakefile.h"
 
- #include "cmPolicies.h"
 
- #include "cmSourceFile.h"
 
- #include "cmSystemTools.h"
 
- #include "cmTarget.h"
 
- #include "cm_unordered_map.hxx"
 
- class cmExecutionStatus;
 
- /** \class cmDependInformation
 
-  * \brief Store dependency information for a single source file.
 
-  *
 
-  * This structure stores the depend information for a single source file.
 
-  */
 
- class cmDependInformation
 
- {
 
- public:
 
-   /**
 
-    * Construct with dependency generation marked not done; instance
 
-    * not placed in cmMakefile's list.
 
-    */
 
-   cmDependInformation()
 
-     : DependDone(false)
 
-     , SourceFile(CM_NULLPTR)
 
-   {
 
-   }
 
-   /**
 
-    * The set of files on which this one depends.
 
-    */
 
-   typedef std::set<cmDependInformation*> DependencySetType;
 
-   DependencySetType DependencySet;
 
-   /**
 
-    * This flag indicates whether dependency checking has been
 
-    * performed for this file.
 
-    */
 
-   bool DependDone;
 
-   /**
 
-    * If this object corresponds to a cmSourceFile instance, this points
 
-    * to it.
 
-    */
 
-   const cmSourceFile* SourceFile;
 
-   /**
 
-    * Full path to this file.
 
-    */
 
-   std::string FullPath;
 
-   /**
 
-    * Full path not including file name.
 
-    */
 
-   std::string PathOnly;
 
-   /**
 
-    * Name used to #include this file.
 
-    */
 
-   std::string IncludeName;
 
-   /**
 
-    * This method adds the dependencies of another file to this one.
 
-    */
 
-   void AddDependencies(cmDependInformation* info)
 
-   {
 
-     if (this != info) {
 
-       this->DependencySet.insert(info);
 
-     }
 
-   }
 
- };
 
- class cmLBDepend
 
- {
 
- public:
 
-   /**
 
-    * Construct the object with verbose turned off.
 
-    */
 
-   cmLBDepend()
 
-   {
 
-     this->Verbose = false;
 
-     this->IncludeFileRegularExpression.compile("^.*$");
 
-     this->ComplainFileRegularExpression.compile("^$");
 
-   }
 
-   /**
 
-    * Destructor.
 
-    */
 
-   ~cmLBDepend() { cmDeleteAll(this->DependInformationMap); }
 
-   /**
 
-    * Set the makefile that is used as a source of classes.
 
-    */
 
-   void SetMakefile(cmMakefile* makefile)
 
-   {
 
-     this->Makefile = makefile;
 
-     // Now extract the include file regular expression from the makefile.
 
-     this->IncludeFileRegularExpression.compile(
 
-       this->Makefile->GetIncludeRegularExpression());
 
-     this->ComplainFileRegularExpression.compile(
 
-       this->Makefile->GetComplainRegularExpression());
 
-     // Now extract any include paths from the targets
 
-     std::set<std::string> uniqueIncludes;
 
-     std::vector<std::string> orderedAndUniqueIncludes;
 
-     cmTargets& targets = this->Makefile->GetTargets();
 
-     for (cmTargets::iterator l = targets.begin(); l != targets.end(); ++l) {
 
-       const char* incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES");
 
-       if (!incDirProp) {
 
-         continue;
 
-       }
 
-       std::string incDirs = cmGeneratorExpression::Preprocess(
 
-         incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
 
-       std::vector<std::string> includes;
 
-       cmSystemTools::ExpandListArgument(incDirs, includes);
 
-       for (std::vector<std::string>::const_iterator j = includes.begin();
 
-            j != includes.end(); ++j) {
 
-         std::string path = *j;
 
-         this->Makefile->ExpandVariablesInString(path);
 
-         if (uniqueIncludes.insert(path).second) {
 
-           orderedAndUniqueIncludes.push_back(path);
 
-         }
 
-       }
 
-     }
 
-     for (std::vector<std::string>::const_iterator it =
 
-            orderedAndUniqueIncludes.begin();
 
-          it != orderedAndUniqueIncludes.end(); ++it) {
 
-       this->AddSearchPath(*it);
 
-     }
 
-   }
 
-   /**
 
-    * Add a directory to the search path for include files.
 
-    */
 
-   void AddSearchPath(const std::string& path)
 
-   {
 
-     this->IncludeDirectories.push_back(path);
 
-   }
 
-   /**
 
-    * Generate dependencies for the file given.  Returns a pointer to
 
-    * the cmDependInformation object for the file.
 
-    */
 
-   const cmDependInformation* FindDependencies(const char* file)
 
-   {
 
-     cmDependInformation* info = this->GetDependInformation(file, CM_NULLPTR);
 
-     this->GenerateDependInformation(info);
 
-     return info;
 
-   }
 
- protected:
 
-   /**
 
-    * Compute the depend information for this class.
 
-    */
 
-   void DependWalk(cmDependInformation* info)
 
-   {
 
-     cmsys::ifstream fin(info->FullPath.c_str());
 
-     if (!fin) {
 
-       cmSystemTools::Error("error can not open ", info->FullPath.c_str());
 
-       return;
 
-     }
 
-     std::string line;
 
-     while (cmSystemTools::GetLineFromStream(fin, line)) {
 
-       if (cmHasLiteralPrefix(line.c_str(), "#include")) {
 
-         // if it is an include line then create a string class
 
-         std::string currentline = line;
 
-         size_t qstart = currentline.find('\"', 8);
 
-         size_t qend;
 
-         // if a quote is not found look for a <
 
-         if (qstart == std::string::npos) {
 
-           qstart = currentline.find('<', 8);
 
-           // if a < is not found then move on
 
-           if (qstart == std::string::npos) {
 
-             cmSystemTools::Error("unknown include directive ",
 
-                                  currentline.c_str());
 
-             continue;
 
-           } else {
 
-             qend = currentline.find('>', qstart + 1);
 
-           }
 
-         } else {
 
-           qend = currentline.find('\"', qstart + 1);
 
-         }
 
-         // extract the file being included
 
-         std::string includeFile =
 
-           currentline.substr(qstart + 1, qend - qstart - 1);
 
-         // see if the include matches the regular expression
 
-         if (!this->IncludeFileRegularExpression.find(includeFile)) {
 
-           if (this->Verbose) {
 
-             std::string message = "Skipping ";
 
-             message += includeFile;
 
-             message += " for file ";
 
-             message += info->FullPath;
 
-             cmSystemTools::Error(message.c_str(), CM_NULLPTR);
 
-           }
 
-           continue;
 
-         }
 
-         // Add this file and all its dependencies.
 
-         this->AddDependency(info, includeFile.c_str());
 
-         /// add the cxx file if it exists
 
-         std::string cxxFile = includeFile;
 
-         std::string::size_type pos = cxxFile.rfind('.');
 
-         if (pos != std::string::npos) {
 
-           std::string root = cxxFile.substr(0, pos);
 
-           cxxFile = root + ".cxx";
 
-           bool found = false;
 
-           // try jumping to .cxx .cpp and .c in order
 
-           if (cmSystemTools::FileExists(cxxFile.c_str())) {
 
-             found = true;
 
-           }
 
-           for (std::vector<std::string>::iterator i =
 
-                  this->IncludeDirectories.begin();
 
-                i != this->IncludeDirectories.end(); ++i) {
 
-             std::string path = *i;
 
-             path = path + "/";
 
-             path = path + cxxFile;
 
-             if (cmSystemTools::FileExists(path.c_str())) {
 
-               found = true;
 
-             }
 
-           }
 
-           if (!found) {
 
-             cxxFile = root + ".cpp";
 
-             if (cmSystemTools::FileExists(cxxFile.c_str())) {
 
-               found = true;
 
-             }
 
-             for (std::vector<std::string>::iterator i =
 
-                    this->IncludeDirectories.begin();
 
-                  i != this->IncludeDirectories.end(); ++i) {
 
-               std::string path = *i;
 
-               path = path + "/";
 
-               path = path + cxxFile;
 
-               if (cmSystemTools::FileExists(path.c_str())) {
 
-                 found = true;
 
-               }
 
-             }
 
-           }
 
-           if (!found) {
 
-             cxxFile = root + ".c";
 
-             if (cmSystemTools::FileExists(cxxFile.c_str())) {
 
-               found = true;
 
-             }
 
-             for (std::vector<std::string>::iterator i =
 
-                    this->IncludeDirectories.begin();
 
-                  i != this->IncludeDirectories.end(); ++i) {
 
-               std::string path = *i;
 
-               path = path + "/";
 
-               path = path + cxxFile;
 
-               if (cmSystemTools::FileExists(path.c_str())) {
 
-                 found = true;
 
-               }
 
-             }
 
-           }
 
-           if (!found) {
 
-             cxxFile = root + ".txx";
 
-             if (cmSystemTools::FileExists(cxxFile.c_str())) {
 
-               found = true;
 
-             }
 
-             for (std::vector<std::string>::iterator i =
 
-                    this->IncludeDirectories.begin();
 
-                  i != this->IncludeDirectories.end(); ++i) {
 
-               std::string path = *i;
 
-               path = path + "/";
 
-               path = path + cxxFile;
 
-               if (cmSystemTools::FileExists(path.c_str())) {
 
-                 found = true;
 
-               }
 
-             }
 
-           }
 
-           if (found) {
 
-             this->AddDependency(info, cxxFile.c_str());
 
-           }
 
-         }
 
-       }
 
-     }
 
-   }
 
-   /**
 
-    * Add a dependency.  Possibly walk it for more dependencies.
 
-    */
 
-   void AddDependency(cmDependInformation* info, const char* file)
 
-   {
 
-     cmDependInformation* dependInfo =
 
-       this->GetDependInformation(file, info->PathOnly.c_str());
 
-     this->GenerateDependInformation(dependInfo);
 
-     info->AddDependencies(dependInfo);
 
-   }
 
-   /**
 
-    * Fill in the given object with dependency information.  If the
 
-    * information is already complete, nothing is done.
 
-    */
 
-   void GenerateDependInformation(cmDependInformation* info)
 
-   {
 
-     // If dependencies are already done, stop now.
 
-     if (info->DependDone) {
 
-       return;
 
-     }
 
-     // Make sure we don't visit the same file more than once.
 
-     info->DependDone = true;
 
-     const char* path = info->FullPath.c_str();
 
-     if (!path) {
 
-       cmSystemTools::Error(
 
-         "Attempt to find dependencies for file without path!");
 
-       return;
 
-     }
 
-     bool found = false;
 
-     // If the file exists, use it to find dependency information.
 
-     if (cmSystemTools::FileExists(path, true)) {
 
-       // Use the real file to find its dependencies.
 
-       this->DependWalk(info);
 
-       found = true;
 
-     }
 
-     // See if the cmSourceFile for it has any files specified as
 
-     // dependency hints.
 
-     if (info->SourceFile != CM_NULLPTR) {
 
-       // Get the cmSourceFile corresponding to this.
 
-       const cmSourceFile& cFile = *(info->SourceFile);
 
-       // See if there are any hints for finding dependencies for the missing
 
-       // file.
 
-       if (!cFile.GetDepends().empty()) {
 
-         // Dependency hints have been given.  Use them to begin the
 
-         // recursion.
 
-         for (std::vector<std::string>::const_iterator file =
 
-                cFile.GetDepends().begin();
 
-              file != cFile.GetDepends().end(); ++file) {
 
-           this->AddDependency(info, file->c_str());
 
-         }
 
-         // Found dependency information.  We are done.
 
-         found = true;
 
-       }
 
-     }
 
-     if (!found) {
 
-       // Try to find the file amongst the sources
 
-       cmSourceFile* srcFile = this->Makefile->GetSource(
 
-         cmSystemTools::GetFilenameWithoutExtension(path));
 
-       if (srcFile) {
 
-         if (srcFile->GetFullPath() == path) {
 
-           found = true;
 
-         } else {
 
-           // try to guess which include path to use
 
-           for (std::vector<std::string>::iterator t =
 
-                  this->IncludeDirectories.begin();
 
-                t != this->IncludeDirectories.end(); ++t) {
 
-             std::string incpath = *t;
 
-             if (!incpath.empty() && incpath[incpath.size() - 1] != '/') {
 
-               incpath = incpath + "/";
 
-             }
 
-             incpath = incpath + path;
 
-             if (srcFile->GetFullPath() == incpath) {
 
-               // set the path to the guessed path
 
-               info->FullPath = incpath;
 
-               found = true;
 
-             }
 
-           }
 
-         }
 
-       }
 
-     }
 
-     if (!found) {
 
-       // Couldn't find any dependency information.
 
-       if (this->ComplainFileRegularExpression.find(
 
-             info->IncludeName.c_str())) {
 
-         cmSystemTools::Error("error cannot find dependencies for ", path);
 
-       } else {
 
-         // Destroy the name of the file so that it won't be output as a
 
-         // dependency.
 
-         info->FullPath = "";
 
-       }
 
-     }
 
-   }
 
-   /**
 
-    * Get an instance of cmDependInformation corresponding to the given file
 
-    * name.
 
-    */
 
-   cmDependInformation* GetDependInformation(const char* file,
 
-                                             const char* extraPath)
 
-   {
 
-     // Get the full path for the file so that lookup is unambiguous.
 
-     std::string fullPath = this->FullPath(file, extraPath);
 
-     // Try to find the file's instance of cmDependInformation.
 
-     DependInformationMapType::const_iterator result =
 
-       this->DependInformationMap.find(fullPath);
 
-     if (result != this->DependInformationMap.end()) {
 
-       // Found an instance, return it.
 
-       return result->second;
 
-     }
 
-     // Didn't find an instance.  Create a new one and save it.
 
-     cmDependInformation* info = new cmDependInformation;
 
-     info->FullPath = fullPath;
 
-     info->PathOnly = cmSystemTools::GetFilenamePath(fullPath);
 
-     info->IncludeName = file;
 
-     this->DependInformationMap[fullPath] = info;
 
-     return info;
 
-   }
 
-   /**
 
-    * 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* fname, const char* extraPath)
 
-   {
 
-     DirectoryToFileToPathMapType::iterator m;
 
-     if (extraPath) {
 
-       m = this->DirectoryToFileToPathMap.find(extraPath);
 
-     } else {
 
-       m = this->DirectoryToFileToPathMap.find("");
 
-     }
 
-     if (m != this->DirectoryToFileToPathMap.end()) {
 
-       FileToPathMapType& map = m->second;
 
-       FileToPathMapType::iterator p = map.find(fname);
 
-       if (p != map.end()) {
 
-         return p->second;
 
-       }
 
-     }
 
-     if (cmSystemTools::FileExists(fname, true)) {
 
-       std::string fp = cmSystemTools::CollapseFullPath(fname);
 
-       this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp;
 
-       return fp;
 
-     }
 
-     for (std::vector<std::string>::iterator i =
 
-            this->IncludeDirectories.begin();
 
-          i != this->IncludeDirectories.end(); ++i) {
 
-       std::string path = *i;
 
-       if (!path.empty() && path[path.size() - 1] != '/') {
 
-         path = path + "/";
 
-       }
 
-       path = path + fname;
 
-       if (cmSystemTools::FileExists(path.c_str(), true) &&
 
-           !cmSystemTools::FileIsDirectory(path)) {
 
-         std::string fp = cmSystemTools::CollapseFullPath(path);
 
-         this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp;
 
-         return fp;
 
-       }
 
-     }
 
-     if (extraPath) {
 
-       std::string path = extraPath;
 
-       if (!path.empty() && path[path.size() - 1] != '/') {
 
-         path = path + "/";
 
-       }
 
-       path = path + fname;
 
-       if (cmSystemTools::FileExists(path.c_str(), true) &&
 
-           !cmSystemTools::FileIsDirectory(path)) {
 
-         std::string fp = cmSystemTools::CollapseFullPath(path);
 
-         this->DirectoryToFileToPathMap[extraPath][fname] = fp;
 
-         return fp;
 
-       }
 
-     }
 
-     // Couldn't find the file.
 
-     return std::string(fname);
 
-   }
 
-   cmMakefile* Makefile;
 
-   bool Verbose;
 
-   cmsys::RegularExpression IncludeFileRegularExpression;
 
-   cmsys::RegularExpression ComplainFileRegularExpression;
 
-   std::vector<std::string> IncludeDirectories;
 
-   typedef std::map<std::string, std::string> FileToPathMapType;
 
-   typedef std::map<std::string, FileToPathMapType>
 
-     DirectoryToFileToPathMapType;
 
-   typedef std::map<std::string, cmDependInformation*> DependInformationMapType;
 
-   DependInformationMapType DependInformationMap;
 
-   DirectoryToFileToPathMapType DirectoryToFileToPathMap;
 
- };
 
- // cmOutputRequiredFilesCommand
 
- bool cmOutputRequiredFilesCommand::InitialPass(
 
-   std::vector<std::string> const& args, cmExecutionStatus&)
 
- {
 
-   if (this->Disallowed(cmPolicies::CMP0032, "The output_required_files "
 
-                                             "command should not be called; "
 
-                                             "see CMP0032.")) {
 
-     return true;
 
-   }
 
-   if (args.size() != 2) {
 
-     this->SetError("called with incorrect number of arguments");
 
-     return false;
 
-   }
 
-   // store the arg for final pass
 
-   this->File = args[0];
 
-   this->OutputFile = args[1];
 
-   // compute the list of files
 
-   cmLBDepend md;
 
-   md.SetMakefile(this->Makefile);
 
-   md.AddSearchPath(this->Makefile->GetCurrentSourceDirectory());
 
-   // find the depends for a file
 
-   const cmDependInformation* info = md.FindDependencies(this->File.c_str());
 
-   if (info) {
 
-     // write them out
 
-     FILE* fout = cmsys::SystemTools::Fopen(this->OutputFile, "w");
 
-     if (!fout) {
 
-       std::string err = "Can not open output file: ";
 
-       err += this->OutputFile;
 
-       this->SetError(err);
 
-       return false;
 
-     }
 
-     std::set<cmDependInformation const*> visited;
 
-     this->ListDependencies(info, fout, &visited);
 
-     fclose(fout);
 
-   }
 
-   return true;
 
- }
 
- void cmOutputRequiredFilesCommand::ListDependencies(
 
-   cmDependInformation const* info, FILE* fout,
 
-   std::set<cmDependInformation const*>* visited)
 
- {
 
-   // add info to the visited set
 
-   visited->insert(info);
 
-   // now recurse with info's dependencies
 
-   for (cmDependInformation::DependencySetType::const_iterator d =
 
-          info->DependencySet.begin();
 
-        d != info->DependencySet.end(); ++d) {
 
-     if (visited->find(*d) == visited->end()) {
 
-       if (info->FullPath != "") {
 
-         std::string tmp = (*d)->FullPath;
 
-         std::string::size_type pos = tmp.rfind('.');
 
-         if (pos != std::string::npos && (tmp.substr(pos) != ".h")) {
 
-           tmp = tmp.substr(0, pos);
 
-           fprintf(fout, "%s\n", (*d)->FullPath.c_str());
 
-         }
 
-       }
 
-       this->ListDependencies(*d, fout, visited);
 
-     }
 
-   }
 
- }
 
 
  |