Browse Source

ENH: add new help option --help-custom-modules, which generates
documentation for all modules found in CMAKE_MODULE_PATH, which currently
has to be specified via -D, this can later on be improved e.g. by reading a
special (to-be-created) file like CMakeFiles/ModulePath.cmake in the build
tree so that running cmake help in the build tree of a project will always
give you the current module path. (This could actually also help IDEs which
would like to support cmake for projects...)

Alex

Alexander Neundorf 18 years ago
parent
commit
31881265c7
4 changed files with 208 additions and 24 deletions
  1. 168 22
      Source/cmDocumentation.cxx
  2. 18 1
      Source/cmDocumentation.h
  3. 1 1
      Source/cmDocumentationFormatter.h
  4. 21 0
      Source/cmakemain.cxx

+ 168 - 22
Source/cmDocumentation.cxx

@@ -61,6 +61,20 @@ static const cmDocumentationEntry cmModulesDocumentationDescription[] =
   {0,0,0}
 };
 
+//----------------------------------------------------------------------------
+static const cmDocumentationEntry cmCustomModulesDocumentationDescription[] =
+{
+  {0,
+  "  Custom CMake Modules - Additional Modules for CMake.", 0},
+//  CMAKE_DOCUMENTATION_OVERVIEW,
+  {0,
+  "This is the documentation for additional modules and scripts for CMake. "
+  "Using these modules you can check the computer system for "
+  "installed software packages, features of the compiler and the "
+  "existance of headers to name just a few.", 0},
+  {0,0,0}
+};
+
 //----------------------------------------------------------------------------
 static const cmDocumentationEntry cmPropertiesDocumentationDescription[] =
 {
@@ -166,6 +180,15 @@ static const cmDocumentationEntry cmDocumentationModulesHeader[] =
   {0,0,0}
 };
 
+//----------------------------------------------------------------------------
+static const cmDocumentationEntry cmDocumentationCustomModulesHeader[] =
+{
+  {0,
+   "The following modules are also available for CMake. "
+   "They can be used with INCLUDE(ModuleName).", 0},
+  {0,0,0}
+};
+
 //----------------------------------------------------------------------------
 static const cmDocumentationEntry cmDocumentationGeneratorsHeader[] =
 {
@@ -264,6 +287,7 @@ cmDocumentation::cmDocumentation()
 ,CompatCommandsSection("Compatibility Listfile Commands",
                        "COMPATIBILITY COMMANDS")
 ,ModulesSection       ("Standard CMake Modules",          "MODULES")
+,CustomModulesSection ("Custom CMake Modules",            "CUSTOM MODULES")
 ,GeneratorsSection    ("Generators",                      "GENERATORS")
 ,SeeAlsoSection       ("See Also",                        "SEE ALSO")
 ,CopyrightSection     ("Copyright",                       "COPYRIGHT")
@@ -389,6 +413,8 @@ bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os)
       return this->PrintDocumentationFull(os);
     case cmDocumentation::Modules: 
       return this->PrintDocumentationModules(os);
+    case cmDocumentation::CustomModules: 
+      return this->PrintDocumentationCustomModules(os);
     case cmDocumentation::Properties: 
       return this->PrintDocumentationProperties(os);
     case cmDocumentation::Commands: 
@@ -414,30 +440,75 @@ bool cmDocumentation::CreateModulesSection()
   if (dir.GetNumberOfFiles() > 0)
     {
     this->ModulesSection.Append(cmDocumentationModulesHeader[0]);
-    for(unsigned int i = 0; i < dir.GetNumberOfFiles(); ++i)
+    this->CreateModuleDocsForDir(dir, this->ModulesSection);
+    cmDocumentationEntry e = { 0, 0, 0 };
+    this->ModulesSection.Append(e);
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmDocumentation::CreateCustomModulesSection()
+{
+  bool sectionHasHeader = false;
+
+  std::vector<std::string> dirs;
+  cmSystemTools::ExpandListArgument(this->CMakeModulePath, dirs);
+
+  for(std::vector<std::string>::const_iterator dirIt = dirs.begin();
+      dirIt != dirs.end();
+      ++dirIt)
+    {
+    cmsys::Directory dir;
+    dir.Load(dirIt->c_str());
+    if (dir.GetNumberOfFiles() > 0)
       {
-      std::string fname = dir.GetFile(i);
-      if(fname.length() > 6)
+      if (!sectionHasHeader)
         {
-        if(fname.substr(fname.length()-6, 6) == ".cmake")
+        this->CustomModulesSection.Append(cmDocumentationCustomModulesHeader[0]);
+        sectionHasHeader =  true;
+        }
+      this->CreateModuleDocsForDir(dir, this->CustomModulesSection);
+      }
+    }
+
+  if(sectionHasHeader)
+    {
+    cmDocumentationEntry e = { 0, 0, 0 };
+    this->CustomModulesSection.Append(e);
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+void cmDocumentation::CreateModuleDocsForDir(cmsys::Directory& dir, 
+                                             cmSection &moduleSection)
+{
+  for(unsigned int i = 0; i < dir.GetNumberOfFiles(); ++i)
+    {
+    std::string fname = dir.GetFile(i);
+    if(fname.length() > 6)
+      {
+      if(fname.substr(fname.length()-6, 6) == ".cmake")
+        {
+        std::string moduleName = fname.substr(0, fname.length()-6);
+        if (this->ModulesFound.find(moduleName) == this->ModulesFound.end())
           {
-          std::string moduleName = fname.substr(0, fname.length()-6);
-          std::string path = cmakeModules;
+          this->ModulesFound.insert(moduleName);
+          std::string path = dir.GetPath();
           path += "/";
           path += fname;
-          this->CreateSingleModule(path.c_str(), moduleName.c_str());
+          this->CreateSingleModule(path.c_str(), moduleName.c_str(), moduleSection);
           }
         }
-      } 
-    cmDocumentationEntry e = { 0, 0, 0 };
-    this->ModulesSection.Append(e);
+      }
     }
-  return true;
 }
 
 //----------------------------------------------------------------------------
 bool cmDocumentation::CreateSingleModule(const char* fname, 
-                                         const char* moduleName)
+                                         const char* moduleName,
+                                         cmSection &moduleSection)
 {
   std::ifstream fin(fname);
   if(!fin)
@@ -513,7 +584,7 @@ bool cmDocumentation::CreateSingleModule(const char* fname,
       char* pbrief = strcpy(new char[brief.length()+1], brief.c_str());
       this->ModuleStrings.push_back(pbrief);
       cmDocumentationEntry e = { pname, pbrief, ptext };
-      this->ModulesSection.Append(e);
+      moduleSection.Append(e);
       return true;
       }
     }
@@ -642,6 +713,12 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv)
       GET_OPT_ARGUMENT(help.Filename);
       help.HelpForm = this->GetFormFromFilename(help.Filename);
       }
+    else if(strcmp(argv[i], "--help-custom-modules") == 0)
+      {
+      help.HelpType = cmDocumentation::CustomModules;
+      GET_OPT_ARGUMENT(help.Filename);
+      help.HelpForm = this->GetFormFromFilename(help.Filename);
+      }
     else if(strcmp(argv[i], "--help-commands") == 0)
       {
       help.HelpType = cmDocumentation::Commands;
@@ -914,22 +991,51 @@ bool cmDocumentation::PrintDocumentationSingleModule(std::ostream& os)
     os << "Argument --help-module needs a module name.\n";
     return false;
     }
-  std::string cmakeModules = this->CMakeRoot;
-  cmakeModules += "/Modules/";
-  cmakeModules += this->CurrentArgument;
-  cmakeModules += ".cmake";
-  if(cmSystemTools::FileExists(cmakeModules.c_str())
-     && this->CreateSingleModule(cmakeModules.c_str(), 
-                                 this->CurrentArgument.c_str()))
+    
+  std::string moduleName;
+  // find the module
+  std::vector<std::string> dirs;
+  cmSystemTools::ExpandListArgument(this->CMakeModulePath, dirs);
+  for(std::vector<std::string>::const_iterator dirIt = dirs.begin();
+      dirIt != dirs.end();
+      ++dirIt)
+    {
+    moduleName = *dirIt;
+    moduleName += "/";
+    moduleName += this->CurrentArgument;
+    moduleName += ".cmake";
+    if(cmSystemTools::FileExists(moduleName.c_str()))
+      {
+      break;
+      }
+    moduleName = "";
+    }
+
+  if (moduleName.empty())
+    {
+    moduleName = this->CMakeRoot;
+    moduleName += "/Modules/";
+    moduleName += this->CurrentArgument;
+    moduleName += ".cmake";
+    if(!cmSystemTools::FileExists(moduleName.c_str()))
+      {
+      moduleName = "";
+      }
+    }
+
+  if(!moduleName.empty()
+     && this->CreateSingleModule(moduleName.c_str(), 
+                                 this->CurrentArgument.c_str(),
+                                 this->ModulesSection))
     {
     this->PrintDocumentationCommand(os, this->ModulesSection.GetEntries());
     os <<  "\n       Defined in: ";
-    os << cmakeModules << "\n";
+    os << moduleName << "\n";
     return true;
     }
   // Argument was not a module.  Complain.
   os << "Argument \"" << this->CurrentArgument.c_str()
-     << "\" to --help-module is not a CMake module.";
+     << "\" to --help-module is not a CMake module.\n";
   return false;
 }
 
@@ -1039,6 +1145,7 @@ bool cmDocumentation::PrintPropertyList(std::ostream& os)
 //----------------------------------------------------------------------------
 bool cmDocumentation::PrintModuleList(std::ostream& os)
 {
+  this->CreateCustomModulesSection();
   this->CreateModulesSection();
   if(this->ModulesSection.IsEmpty())
     {
@@ -1053,6 +1160,19 @@ bool cmDocumentation::PrintModuleList(std::ostream& os)
       os << entry->name << std::endl;
       }
     }
+
+  if(!this->CustomModulesSection.IsEmpty())
+    {
+    os << "\nCUSTOM MODULES\n" << std::endl;
+    for(const cmDocumentationEntry* 
+        entry = this->CustomModulesSection.GetEntries(); entry->brief; ++entry)
+      {
+      if(entry->name)
+        {
+        os << entry->name << std::endl;
+        }
+      }
+    }
   return true;
 }
 
@@ -1084,6 +1204,16 @@ bool cmDocumentation::PrintDocumentationModules(std::ostream& os)
   return true;
 }
 
+//----------------------------------------------------------------------------
+bool cmDocumentation::PrintDocumentationCustomModules(std::ostream& os)
+{
+  this->CreateCustomModulesDocumentation();
+  this->CurrentFormatter->PrintHeader(GetNameString(), os);
+  this->Print(os);
+  this->CurrentFormatter->PrintFooter(os);
+  return true;
+}
+
 //----------------------------------------------------------------------------
 bool cmDocumentation::PrintDocumentationProperties(std::ostream& os)
 {
@@ -1141,6 +1271,7 @@ void cmDocumentation::CreateUsageDocumentation()
 void cmDocumentation::CreateFullDocumentation()
 {
   this->ClearSections();
+  this->CreateCustomModulesSection();
   this->CreateModulesSection();
   this->AddSection(this->NameSection);
   this->AddSection(this->UsageSection);
@@ -1211,6 +1342,21 @@ void cmDocumentation::CreateModulesDocumentation()
         this->CurrentFormatter->GetForm()), cmDocumentationStandardSeeAlso);
 }
 
+//----------------------------------------------------------------------------
+void cmDocumentation::CreateCustomModulesDocumentation()
+{
+  this->ClearSections();
+  this->CreateCustomModulesSection();
+  this->AddSection(this->DescriptionSection.GetName(
+        this->CurrentFormatter->GetForm()), 
+        cmCustomModulesDocumentationDescription);
+  this->AddSection(this->CustomModulesSection);
+  this->AddSection(this->CopyrightSection.GetName(
+        this->CurrentFormatter->GetForm()), cmDocumentationCopyright);
+  this->AddSection(this->SeeAlsoSection.GetName(
+        this->CurrentFormatter->GetForm()), cmDocumentationStandardSeeAlso);
+}
+
 //----------------------------------------------------------------------------
 void cmDocumentation::CreatePropertiesDocumentation()
 {

+ 18 - 1
Source/cmDocumentation.h

@@ -26,6 +26,11 @@
 #include "cmDocumentationFormatterUsage.h"
 
 
+namespace cmsys
+{
+  class Directory;
+}
+
 /** Class to generate documentation.  */
 class cmDocumentation: public cmDocumentationEnums
 {
@@ -157,14 +162,21 @@ public:
   
   /** Set cmake root so we can find installed files */
   void SetCMakeRoot(const char* root)  { this->CMakeRoot = root;}
+
+  /** Set CMAKE_MODULE_PATH so we can find additional cmake modules */
+  void SetCMakeModulePath(const char* path)  { this->CMakeModulePath = path;}
   
   static Form GetFormFromFilename(const std::string& filename);
 
 private:
   void SetForm(Form f);
 
-  bool CreateSingleModule(const char* fname, const char* moduleName);
+  bool CreateSingleModule(const char* fname, 
+                          const char* moduleName, 
+                          cmSection &moduleSection);
+  void CreateModuleDocsForDir(cmsys::Directory& dir, cmSection &moduleSection);
   bool CreateModulesSection();
+  bool CreateCustomModulesSection();
   bool PrintCopyright(std::ostream& os);
   bool PrintVersion(std::ostream& os);
   bool PrintDocumentationList(std::ostream& os);
@@ -176,6 +188,7 @@ private:
   bool PrintDocumentationUsage(std::ostream& os);
   bool PrintDocumentationFull(std::ostream& os);
   bool PrintDocumentationModules(std::ostream& os);
+  bool PrintDocumentationCustomModules(std::ostream& os);
   bool PrintDocumentationProperties(std::ostream& os);
   bool PrintDocumentationCurrentCommands(std::ostream& os);
   bool PrintDocumentationCompatCommands(std::ostream& os);
@@ -187,6 +200,7 @@ private:
   void CreateCurrentCommandsDocumentation();
   void CreateCompatCommandsDocumentation();
   void CreateModulesDocumentation();
+  void CreateCustomModulesDocumentation();
   void CreatePropertiesDocumentation();
 
   void SetSection(const cmDocumentationEntry* header,
@@ -204,6 +218,7 @@ private:
   cmSection CommandsSection;
   cmSection CompatCommandsSection;
   cmSection ModulesSection;
+  cmSection CustomModulesSection;
   cmSection GeneratorsSection;
   cmSection SeeAlsoSection;
   cmSection CopyrightSection;
@@ -219,6 +234,8 @@ private:
   
   std::string SeeAlsoString;
   std::string CMakeRoot;
+  std::string CMakeModulePath;
+  std::set<std::string> ModulesFound;
   std::vector< char* > ModuleStrings;
   std::vector< const char* > Names;
   std::vector< const cmDocumentationEntry* > Sections;

+ 1 - 1
Source/cmDocumentationFormatter.h

@@ -32,7 +32,7 @@ public:
   enum Type 
      { None, Usage, Single, SingleModule, SingleProperty,
        List, ModuleList, PropertyList,
-       Full, Properties, Modules, Commands, CompatCommands,
+       Full, Properties, Modules, CustomModules, Commands, CompatCommands,
        Copyright, Version };
 
   /** Forms of documentation output.  */

+ 21 - 0
Source/cmakemain.cxx

@@ -138,6 +138,12 @@ static const cmDocumentationEntry cmDocumentationOptions[] =
    "If a file is specified, the documentation is written into and the output "
    "format is determined depending on the filename suffix. Supported are man "
    "page, HTML and plain text."},
+  {"--help-custom-modules [file]" , "Print help for all custom modules and "
+   "exit.",
+   "Full documentation for all custom modules is displayed. "
+   "If a file is specified, the documentation is written into and the output "
+   "format is determined depending on the filename suffix. Supported are man "
+   "page, HTML and plain text."},
   {"--help-property prop [file]", 
    "Print help for a single property and exit.",
    "Full documentation specific to the given module is displayed."
@@ -277,6 +283,21 @@ int do_cmake(int ac, char** av)
     cmake hcm;
     hcm.AddCMakePaths(av[0]);
     doc.SetCMakeRoot(hcm.GetCacheDefinition("CMAKE_ROOT"));
+
+    // the command line args are processed here so that you can do 
+    // -DCMAKE_MODULE_PATH=/some/path and have this value accessible here
+    std::vector<std::string> args;
+    for(int i =0; i < ac; ++i)
+      {
+      args.push_back(av[i]);
+      }
+    hcm.SetCacheArgs(args);
+    const char* modulePath = hcm.GetCacheDefinition("CMAKE_MODULE_PATH");
+    if (modulePath)
+      {
+      doc.SetCMakeModulePath(modulePath);
+      }
+
     std::vector<cmDocumentationEntry> commands;
     std::vector<cmDocumentationEntry> compatCommands;
     std::vector<cmDocumentationEntry> globalProperties;