Pārlūkot izejas kodu

Implement simple CMake script comment markup language.

The language is very simple. It use ##<keyword> special comment
which opens a structured documentation block and ##end closes it.
This may be used to extract documentation for macro as 'command'
and 'variables' such that cpack --help-command and --help-variable
does parse builtin modules files (CPack.cmake, CPackComponent.cmake,
...) in order to extract the corresponding doc.
Eric NOULARD 14 gadi atpakaļ
vecāks
revīzija
83e34dd9e6

+ 12 - 0
Modules/CPack.cmake

@@ -49,21 +49,33 @@
 # there are a variety of variables that can be set to customize
 # the resulting installers. The most commonly-used variables are:
 #
+##variable
 #   CPACK_PACKAGE_NAME - The name of the package (or application). If
 #   not specified, defaults to the project name.
+##end
 #
+##variable
 #   CPACK_PACKAGE_VENDOR - The name of the package vendor (e.g.,
 #   "Kitware").
+##end
 #
+##variable
 #   CPACK_PACKAGE_VERSION_MAJOR - Package major Version
+##end
 #
+##variable
 #   CPACK_PACKAGE_VERSION_MINOR - Package minor Version
+##end
 #
+##variable
 #   CPACK_PACKAGE_VERSION_PATCH - Package patch Version
+##end
 #
+##variable
 #   CPACK_PACKAGE_DESCRIPTION_FILE - A text file used to describe the
 #   project. Used, for example, the introduction screen of a
 #   CPack-generated Windows installer to describe the project.
+##end
 #
 #   CPACK_PACKAGE_DESCRIPTION_SUMMARY - Short description of the
 #   project (only a few words).

+ 8 - 0
Modules/CPackComponent.cmake

@@ -21,6 +21,7 @@
 # INSTALL commands, and should be further described by the following
 # CPack commands:
 #
+##macro
 #   cpack_add_component - Describes a CPack installation component
 #   named by the COMPONENT argument to a CMake INSTALL command.
 #
@@ -90,7 +91,9 @@
 #   create a file with some name based on CPACK_PACKAGE_FILE_NAME and
 #   the name of the component. See cpack_configure_downloads for more
 #   information.
+##end
 #
+##macro
 #   cpack_add_component_group - Describes a group of related CPack
 #   installation components.
 #
@@ -134,7 +137,9 @@
 #
 #   BOLD_TITLE indicates that the group title should appear in bold,
 #   to call the user's attention to the group.
+##end
 #
+##macro
 #   cpack_add_install_type - Add a new installation type containing a
 #   set of predefined component selections to the graphical installer.
 #
@@ -153,7 +158,9 @@
 #   DISPLAY_NAME is the displayed name of the install type, which will
 #   typically show up in a drop-down box within a graphical
 #   installer. This value can be any string.
+##end
 #
+##macro
 #   cpack_configure_downloads - Configure CPack to download selected
 #   components on-the-fly as part of the installation process.
 #
@@ -203,6 +210,7 @@
 #   that can be called from Windows' Add/Remove Programs dialog (via the
 #   "Modify" button) to change the set of installed components. NO_ADD_REMOVE
 #   turns off this behavior. This option is ignored on Mac OS X.
+##endmacro
 
 #=============================================================================
 # Copyright 2006-2009 Kitware, Inc.

+ 1 - 1
Source/CPack/cmCPackDocumentMacros.cxx

@@ -74,5 +74,5 @@ void cmCPackDocumentMacros::GetMacrosDocumentation(
           "information."
 );
 
-    v.push_back(e);
+   //v.push_back(e);
 }

+ 0 - 6
Source/CPack/cmCPackDocumentVariables.cxx

@@ -5,12 +5,6 @@ void cmCPackDocumentVariables::DefineVariables(cmake* cm)
 {
   // Subsection: variables defined/used by cpack,
   // which are common to all CPack generators
-  cm->DefineProperty
-    ("CPACK_PACKAGE_NAME", cmProperty::VARIABLE,
-     "The name of the package (or application).",
-     "If not specified, defaults to the project name."
-     "", false,
-     "Variables common to all CPack generators");
 
   cm->DefineProperty
       ("CPACK_PACKAGE_VENDOR", cmProperty::VARIABLE,

+ 32 - 2
Source/CPack/cpack.cxx

@@ -520,11 +520,41 @@ int main (int argc, char *argv[])
     doc.PrependSection("Options",cmDocumentationOptions);
 
     cmCPackDocumentVariables::DefineVariables(&cminst);
+
+    std::vector<cmDocumentationEntry> commands;
+
+    cminst.AddCMakePaths();
+    std::string systemFile =
+            globalMF->GetModulesFile("CMakeDetermineSystem.cmake");
+    if (!globalMF->ReadListFile(0, systemFile.c_str()))
+    {
+        cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+                "Error reading CMakeDetermineSystem.cmake" << std::endl);
+        return 1;
+    }
+
+    systemFile =
+            globalMF->GetModulesFile("CMakeSystemSpecificInformation.cmake");
+    if (!globalMF->ReadListFile(0, systemFile.c_str()))
+    {
+        cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+                "Error reading CMakeSystemSpecificInformation.cmake"
+                << std::endl);
+        return 1;
+    }
+    std::string cpFile = globalMF->GetModulesFile("CPack.cmake");
+    doc.getStructuredDocFromFile(cpFile.c_str(),
+            commands,&cminst,"Variables common to all CPack generators");
+    cpFile = globalMF->GetModulesFile("CPackComponent.cmake");
+    doc.getStructuredDocFromFile(cpFile.c_str(),
+                commands,&cminst,"Variables common to all CPack generators");
+    cpFile = globalMF->GetModulesFile("CPackRPM.cmake");
+        doc.getStructuredDocFromFile(cpFile.c_str(),
+                    commands,&cminst,"Variables specific to a CPack generator");
+
     std::map<std::string,cmDocumentationSection *> propDocs;
     cminst.GetPropertiesDocumentation(propDocs);
     doc.SetSections(propDocs);
-
-    std::vector<cmDocumentationEntry> commands;
     cminst.GetCommandDocumentation(commands);
     cmCPackDocumentMacros::GetMacrosDocumentation(commands);
     doc.SetSection("Commands",commands);

+ 171 - 0
Source/cmDocumentation.cxx

@@ -511,6 +511,8 @@ bool cmDocumentation::CreateSingleModule(const char* fname,
     {
     if(line.size() && line[0] == '#')
       {
+      /* line beginnings with ## are mark-up ignore them */
+      if (line[1] == '#') continue;
       // blank line
       if(line.size() <= 2)
         {
@@ -743,6 +745,175 @@ void cmDocumentation::addCPackStandardDocSections()
             "Variables specific to a CPack generator");
 }
 
+//----------------------------------------------------------------------------
+static void trim(std::string& s)
+{
+  std::string::size_type pos = s.find_last_not_of(' ');
+  if(pos != std::string::npos) {
+    s.erase(pos + 1);
+    pos = s.find_first_not_of(' ');
+    if(pos != std::string::npos) s.erase(0, pos);
+  }
+  else s.erase(s.begin(), s.end());
+}
+
+int cmDocumentation::getStructuredDocFromFile(
+        const char* fname,
+        std::vector<cmDocumentationEntry>& commands,
+        cmake* cm,
+        const char *docSection)
+{
+    typedef enum sdoce {
+        SDOC_NONE, SDOC_MACRO,
+        SDOC_PARAM, SDOC_VARIABLE,
+        SDOC_UNKNOWN} sdoc_t;
+    int nbDocItemFound = 0;
+    int docCtxIdx      = 0;
+    std::vector<int> docContextStack(60);
+    docContextStack[docCtxIdx]=SDOC_NONE;
+    cmDocumentationEntry e;
+    std::ifstream fin(fname);
+    if(!fin)
+      {
+      //std::cerr << "Internal error: can not open script file: <" << fname <<">."<< std::endl;
+      return nbDocItemFound;
+      }
+    std::string name;
+    std::string full;
+    std::string brief;
+    std::string line;
+    bool newCtx  = false;
+    bool inBrief = false;
+    brief = "";
+    full  = "";
+    bool newParagraph = true;
+    while ( fin && cmSystemTools::GetLineFromStream(fin, line) )
+      {
+      if(line.size() && line[0] == '#')
+        {
+        /* handle structured doc context */
+        if (line[1]=='#') {
+            std::string mkword = line.substr(2,std::string::npos);
+            if (mkword=="macro")
+            {
+               docCtxIdx++;
+               docContextStack[docCtxIdx]=SDOC_MACRO;
+               newCtx = true;
+            }
+            else if (mkword=="variable")
+            {
+               docCtxIdx++;
+               docContextStack[docCtxIdx]=SDOC_VARIABLE;
+               newCtx = true;
+            }
+            else if (mkword.substr(0,3)=="end")
+            {
+               ;
+               switch (docContextStack[docCtxIdx]) {
+               case SDOC_MACRO:
+                   commands.push_back(cmDocumentationEntry(name.c_str(),
+                           brief.c_str(),full.c_str()));
+                   break;
+               case SDOC_VARIABLE:
+                   cm->DefineProperty
+                       (name.c_str(), cmProperty::VARIABLE,
+                        brief.c_str(),
+                        full.c_str(),false,
+                        docSection);
+                   break;
+               }
+               docCtxIdx--;
+               newCtx = false;
+            }
+            else
+            {
+                // error out unhandled context
+                std::cerr << "Internal error: unknown markup context <"
+                          << mkword <<"> found in:" << fname << std::endl;
+                return nbDocItemFound;
+            }
+            /* context is set go to next doc line */
+            continue;
+        }
+
+        // Now parse the text attached to the context
+
+        // The first line after the context mark-up contains::
+        //  name - brief until. (brief is dot terminated or
+        //                       followed by a blank line)
+        if (newCtx)
+        {
+            name = line.substr(1,line.find("-")-1);
+            trim(name);
+            brief = "";
+            line = line.substr(line.find("- ")+1,std::string::npos);
+            inBrief = true;
+            full = "";
+        }
+        // blank line
+        if(line.size() <= 2)
+        {
+            inBrief = false;
+            full += "\n";
+            newParagraph = true;
+        }
+        // brief terminated by .
+        else if (inBrief && line[line.length()-1]=='.')
+        {
+            inBrief = false;
+            brief += line.c_str()+1;
+        }
+        // we handle full text or multi-line brief.
+        else
+          {
+          std::string* text;
+          if (inBrief) {
+              text = &brief;
+          } else {
+              text = &full;
+          }
+          // two spaces
+          if(line[1] == ' ' && line[2] == ' ')
+            {
+            if(!newParagraph)
+              {
+
+                *text += "\n";
+                newParagraph = true;
+              }
+            // Skip #, and leave space for preformatted
+            *text += line.c_str()+1;
+            *text += "\n";
+            }
+          else if(line[1] == ' ')
+            {
+            if(!newParagraph)
+              {
+              *text += " ";
+              }
+            newParagraph = false;
+            // skip # and space
+            *text += line.c_str()+2;
+            }
+          else
+            {
+            if(!newParagraph)
+              {
+              *text += " ";
+              }
+            newParagraph = false;
+            // skip #
+            *text += line.c_str()+1;
+            }
+          }
+        }
+      /* next line is not the first context line */
+      newCtx = false;
+      }
+
+    return nbDocItemFound;
+}
+
 //----------------------------------------------------------------------------
 bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
                                    const char* exitOpt)

+ 23 - 0
Source/cmDocumentation.h

@@ -21,6 +21,7 @@
 #include "cmDocumentationFormatterText.h"
 #include "cmDocumentationFormatterUsage.h"
 #include "cmDocumentationSection.h"
+#include "cmake.h"
 
 namespace cmsys
 {
@@ -131,6 +132,28 @@ public:
   /** Add the CPack standard documentation section(s) */
   void addCPackStandardDocSections();
 
+  /**
+   * Get the documentation of macros and variable documented
+   * with CMake structured documentation in a CMake script.
+   * Structured documentation begin with
+   * ## (double sharp) in column 1 & 2 immediately followed
+   * by a markup. Those ## are ignored by the legacy module
+   * documentation parser @see CreateSingleModule.
+   * Current markup are ##macro, ##param, ##variable and ##end
+   * which is closing either of the previous ones.
+   * @param[in] fname the script file name to be parsed for documentation
+   * @param[in,out] commands the vector of command/macros documentation
+   *                entry found in the script file.
+   * @param[in,out] the cmake object instance to which variable documentation
+   *                will be attached (using @see cmake::DefineProperty)
+   * @return the number of documented items (command and variable)
+   *         found in the file.
+   */
+  int getStructuredDocFromFile(const char* fname,
+                               std::vector<cmDocumentationEntry>& commands,
+                               cmake* cm,
+                               const char *docSection);
+  ;
 private:
   void SetForm(Form f);
   void SetDocName(const char* docname);