Kaynağa Gözat

ENH: add framework for unified handling of arguments to cmake commands,
example see cmExportCommand.cxx

Alex

Alexander Neundorf 18 yıl önce
ebeveyn
işleme
2e56fa4808

+ 1 - 0
Source/cmBootstrapCommands.cxx

@@ -29,6 +29,7 @@
 #include "cmAddTestCommand.cxx"
 #include "cmBuildCommand.cxx"
 #include "cmCMakeMinimumRequired.cxx"
+#include "cmCommandArgumentsHelper.cxx"
 #include "cmConfigureFileCommand.cxx"
 #include "cmCoreTryCompile.cxx"
 #include "cmCreateTestSourceList.cxx"

+ 2 - 0
Source/cmCommand.h

@@ -20,6 +20,7 @@
 #include "cmObject.h"
 #include "cmListFileCache.h"
 #include "cmMakefile.h"
+#include "cmCommandArgumentsHelper.h"
 
 /** \class cmCommand
  * \brief Superclass for all commands in CMake.
@@ -174,6 +175,7 @@ public:
 
 protected:
   cmMakefile* Makefile;
+  cmCommandArgumentsHelper Helper;
 
 private:
   bool Enabled;

+ 308 - 0
Source/cmCommandArgumentsHelper.cxx

@@ -0,0 +1,308 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#include "cmCommandArgumentsHelper.h"
+
+cmCommandArgument::cmCommandArgument(cmCommandArgumentsHelper* args, 
+                                     const char* key, 
+                                     cmCommandArgumentGroup* group)
+:Key(key)
+,Group(group)
+,WasActive(false)
+,CurrentIndex(0) 
+{
+  if (args!=0)
+    {
+    args->AddArgument(this);
+    }
+    
+  if (this->Group!=0)
+    {
+    this->Group->ContainedArguments.push_back(this);
+    }
+}
+
+void cmCommandArgument::Reset()
+{
+  this->WasActive =false;
+  this->CurrentIndex = 0;
+  this->DoReset();
+}
+
+void cmCommandArgument::Follows(const cmCommandArgument* arg)
+{
+  this->ArgumentsBefore.insert(arg);
+}
+
+void cmCommandArgument::FollowsGroup(const cmCommandArgumentGroup* group)
+{
+  if (group!=0)
+    {
+    for(std::vector<cmCommandArgument*>::const_iterator 
+        argIt= group->ContainedArguments.begin();
+        argIt != group->ContainedArguments.end();
+        ++argIt)
+      {
+      this->ArgumentsBefore.insert(*argIt);
+      }
+    }
+}
+
+bool cmCommandArgument::MayFollow(const cmCommandArgument* current) const
+{
+  if (this->ArgumentsBefore.empty())
+    {
+    return true;
+    }
+
+  std::set<const cmCommandArgument*>::const_iterator argIt 
+                                         = this->ArgumentsBefore.find(current);
+  if (argIt != this->ArgumentsBefore.end())
+    {
+    return true;
+    }
+
+  return false;
+}
+
+bool cmCommandArgument::KeyMatches(const std::string& key) const
+{
+  if ((this->Key==0) || (this->Key[0]=='\0'))
+    {
+    return true;
+    }
+  return (key==this->Key);
+}
+
+void cmCommandArgument::ApplyOwnGroup()
+{
+  if (this->Group!=0)
+    {
+    for (std::vector<cmCommandArgument*>::const_iterator 
+         it = this->Group->ContainedArguments.begin();
+         it != this->Group->ContainedArguments.end();
+         ++it)
+      {
+      if(*it != this)
+        {
+        this->ArgumentsBefore.insert(*it);
+        }
+      }
+    }
+}
+
+void cmCommandArgument::Activate()
+{
+  this->WasActive = true; 
+  this->CurrentIndex = 0;
+}
+
+bool cmCommandArgument::Consume(const std::string& arg)
+{
+  bool res=this->DoConsume(arg, this->CurrentIndex);
+  this->CurrentIndex++;
+  return res;
+}
+
+
+cmCAStringVector::cmCAStringVector(cmCommandArgumentsHelper* args, 
+                                   const char* key, 
+                                   cmCommandArgumentGroup* group)
+:cmCommandArgument(args, key, group)
+{
+  if ((key==0) || (*key==0))
+    {
+    this->DataStart = 0;
+    }
+  else
+    {
+    this->DataStart = 1;
+    }
+}
+
+bool cmCAStringVector::DoConsume(const std::string& arg,unsigned int index)
+{
+  if (index >= this->DataStart)
+    {
+    if ((this->Ignore==0) || (arg != this->Ignore))
+      {
+      this->Vector.push_back(arg);
+      }
+    }
+
+  return false;
+}
+
+void cmCAStringVector::DoReset()
+{
+  this->Vector.clear();
+}
+
+cmCAString::cmCAString(cmCommandArgumentsHelper* args, 
+                       const char* key, 
+                       cmCommandArgumentGroup* group)
+:cmCommandArgument(args, key, group)
+{
+  if ((key==0) || (*key==0))
+    {
+    this->DataStart = 0;
+    }
+  else
+    {
+    this->DataStart = 1;
+    }
+}
+
+bool cmCAString::DoConsume(const std::string& arg, unsigned int index)
+{
+  if (index == this->DataStart)
+    {
+    this->String = arg;
+    }
+
+  return index >= this->DataStart;
+}
+
+void cmCAString::DoReset()
+{
+  this->String = "";
+}
+
+cmCAEnabler::cmCAEnabler(cmCommandArgumentsHelper* args, 
+                         const char* key, 
+                         cmCommandArgumentGroup* group)
+:cmCommandArgument(args, key, group)
+,Enabled(false) 
+{}
+
+bool cmCAEnabler::DoConsume(const std::string& arg, unsigned int index)
+{
+  if (index==0)
+    {
+    this->Enabled = true;
+    }
+  return true;
+}
+
+void cmCAEnabler::DoReset()
+{
+  this->Enabled = false;
+}
+
+cmCADisabler::cmCADisabler(cmCommandArgumentsHelper* args, 
+                           const char* key, 
+                           cmCommandArgumentGroup* group)
+:cmCommandArgument(args, key, group)
+,Enabled(true) 
+{}
+
+bool cmCADisabler::DoConsume(const std::string& arg, unsigned int index)
+{
+  if (index==0)
+    {
+    this->Enabled = false;
+    }
+  return true;
+}
+
+void cmCADisabler::DoReset()
+{
+  this->Enabled = true;
+}
+
+void cmCommandArgumentGroup::Follows(const cmCommandArgument* arg)
+{
+  for(std::vector<cmCommandArgument*>::iterator 
+      it = this->ContainedArguments.begin();
+      it != this->ContainedArguments.end();
+      ++it)
+    {
+    (*it)->Follows(arg);
+    }
+}
+
+void cmCommandArgumentGroup::FollowsGroup(const cmCommandArgumentGroup* group)
+{
+  for(std::vector<cmCommandArgument*>::iterator 
+      it = this->ContainedArguments.begin();
+      it != this->ContainedArguments.end();
+      ++it)
+    {
+    (*it)->FollowsGroup(group);
+    }
+}
+
+void cmCommandArgumentsHelper::Parse(const std::vector<std::string>* args, 
+                                     std::vector<std::string>* unconsumedArgs)
+{
+  if(args==0)
+    {
+    return;
+    }
+
+  for(std::vector<cmCommandArgument*>::iterator 
+      argIt = this->Arguments.begin();
+      argIt != this->Arguments.end();
+      ++argIt)
+    {
+    (*argIt)->ApplyOwnGroup();
+    (*argIt)->Reset();
+    }
+
+  cmCommandArgument* activeArgument = 0;
+  const cmCommandArgument* previousArgument = 0;
+  for(std::vector<std::string>::const_iterator it = args->begin();
+      it != args->end();
+      ++it)
+    {
+    for(std::vector<cmCommandArgument*>::iterator 
+        argIt = this->Arguments.begin();
+        argIt != this->Arguments.end();
+        ++argIt)
+      {
+      if ((*argIt)->KeyMatches(*it) && ((*argIt)->MayFollow(previousArgument)))
+        {
+        activeArgument = *argIt;
+        activeArgument->Activate();
+        break;
+        }
+      }
+
+    if (activeArgument)
+      {
+      bool argDone = activeArgument->Consume(*it);
+      previousArgument = activeArgument;
+      if (argDone)
+        {
+        activeArgument = 0;
+        }
+      }
+    else
+      {
+      if (unconsumedArgs!=0)
+        {
+        unconsumedArgs->push_back(*it);
+        }
+      }
+    }
+}
+
+void cmCommandArgumentsHelper::AddArgument(cmCommandArgument* arg)
+{
+  this->Arguments.push_back(arg);
+}
+

+ 208 - 0
Source/cmCommandArgumentsHelper.h

@@ -0,0 +1,208 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmCommandArgumentsHelper_h
+#define cmCommandArgumentsHelper_h
+
+#include "cmStandardIncludes.h"
+
+class cmCommandArgumentsHelper;
+class cmCommandArgumentGroup;
+
+/* cmCommandArgumentsHelper, cmCommandArgumentGroup and cmCommandArgument (i.e.
+its derived classes cmCAXXX can be used to simplify the processing of 
+arguments to cmake commands. Maybe they can also be used to generate
+documentation.
+
+For every argument supported by a command one cmCommandArgument is created
+and added to cmCommandArgumentsHelper. cmCommand has a cmCommandArgumentsHelper
+as member variable so this should be used.
+
+The order of the arguments is defined using the Follows(arg) method. It says 
+that this argument follows immediateley the given argument. It can be used
+with multiple arguments if the argument can follow after different arguments.
+
+Arguments can be arranged in groups using cmCommandArgumentGroup. Every 
+member of a group can follow any other member of the group. These groups
+can also be used to define the order.
+
+Once all arguments and groups are set up, cmCommandArgumentsHelper::Parse()
+is called and afterwards the values of the arguments can be evaluated.
+
+For an example see cmExportCommand.cxx.
+*/
+class cmCommandArgument
+{
+  public:
+    cmCommandArgument(cmCommandArgumentsHelper* args, 
+                      const char* key, 
+                      cmCommandArgumentGroup* group=0);
+    virtual ~cmCommandArgument() {}
+
+    /// this argument may follow after arg. 0 means it comes first.
+    void Follows(const cmCommandArgument* arg);
+
+    /// this argument may follow after any of the arguments in the given group
+    void FollowsGroup(const cmCommandArgumentGroup* group);
+
+    /// Returns true if the argument was found in the argument list
+    bool WasFound() const                             {return this->WasActive;}
+
+    // The following methods are only called from 
+    // cmCommandArgumentsHelper::Parse(), but making this a friend would 
+    // give it access to everything
+
+    /// Make the current argument the currently active argument
+    void Activate();
+    /// Consume the current string
+    bool Consume(const std::string& arg);
+
+    /// Return true if this argument may follow after the given argument.
+    bool MayFollow(const cmCommandArgument* current) const;
+
+    /** Returns true if the given key matches the key for this argument.
+    If this argument has an empty key everything matches. */
+    bool KeyMatches(const std::string& key) const;
+
+    /// Make this argument follow all members of the own group
+    void ApplyOwnGroup();
+
+    /// Reset argument, so it's back to its initial state
+    void Reset();
+  private:
+    const char* Key;
+    std::set<const cmCommandArgument*> ArgumentsBefore;
+    cmCommandArgumentGroup* Group;
+    bool WasActive;
+    unsigned int CurrentIndex;
+
+    virtual bool DoConsume(const std::string& arg, unsigned int index) = 0;
+    virtual void DoReset() = 0;
+};
+
+/** cmCAStringVector is to be used for arguments which can consist of more 
+than one string, e.g. the FILES argument in INSTALL(FILES f1 f2 f3 ...). */
+class cmCAStringVector : public cmCommandArgument
+{
+  public:
+    cmCAStringVector(cmCommandArgumentsHelper* args, 
+                     const char* key, 
+                     cmCommandArgumentGroup* group=0);
+
+    /// Return the vector of strings
+    const std::vector<std::string>& GetVector() const    {return this->Vector;}
+
+    /** Is there a keyword which should be skipped in 
+    the arguments (e.g. ARGS for ADD_CUSTOM_COMMAND) ? */
+    void SetIgnore(const char* ignore)                   {this->Ignore=ignore;}
+  private:
+    std::vector<std::string> Vector;
+    unsigned int DataStart;
+    const char* Ignore;
+    cmCAStringVector();
+    virtual bool DoConsume(const std::string& arg, unsigned int index);
+    virtual void DoReset();
+};
+
+/** cmCAString is to be used for arguments which consist of one value,
+e.g. the executable name in ADD_EXECUTABLE(). */
+class cmCAString : public cmCommandArgument
+{
+  public:
+    cmCAString(cmCommandArgumentsHelper* args, 
+               const char* key, 
+               cmCommandArgumentGroup* group=0);
+
+    /// Return the string
+    const std::string& GetString() const                 {return this->String;}
+  private:
+    std::string String;
+    unsigned int DataStart;
+    virtual bool DoConsume(const std::string& arg, unsigned int index);
+    virtual void DoReset();
+    cmCAString();
+};
+
+/** cmCAEnabler is to be used for options which are off by default and can be
+enabled using a special argument, e.g. EXCLUDE_FROM_ALL in ADD_EXECUTABLE(). */
+class cmCAEnabler : public cmCommandArgument
+{
+  public:
+    cmCAEnabler(cmCommandArgumentsHelper* args, 
+                const char* key, 
+                cmCommandArgumentGroup* group=0);
+
+    /// Has it been enabled ?
+    bool IsEnabled() const                              {return this->Enabled;}
+  private:
+    bool Enabled;
+    virtual bool DoConsume(const std::string& arg, unsigned int index);
+    virtual void DoReset();
+    cmCAEnabler();
+};
+
+/** cmCADisable is to be used for options which are on by default and can be
+disabled using a special argument.*/
+class cmCADisabler : public cmCommandArgument
+{
+  public:
+    cmCADisabler(cmCommandArgumentsHelper* args, 
+                 const char* key, 
+                 cmCommandArgumentGroup* group=0);
+
+    /// Is it still enabled ?
+    bool IsEnabled() const                              {return this->Enabled;}
+  private:
+    bool Enabled;
+    virtual bool DoConsume(const std::string& arg, unsigned int index);
+    virtual void DoReset();
+    cmCADisabler();
+};
+
+
+/** Group of arguments, needed for ordering. E.g. WIN32, EXCLUDE_FROM_ALL and 
+MACSOX_BUNDLE from ADD_EXECUTABLE() are a group.
+*/
+class cmCommandArgumentGroup
+{
+  friend class cmCommandArgument;
+  public:
+    cmCommandArgumentGroup() {}
+
+    /// All members of this group may follow the given argument
+    void Follows(const cmCommandArgument* arg);
+
+    /// All members of this group may follow all members of the given group
+    void FollowsGroup(const cmCommandArgumentGroup* group);
+  private:
+    std::vector<cmCommandArgument*> ContainedArguments;
+};
+
+class cmCommandArgumentsHelper
+{
+  public:
+    /// Parse the argument list
+    void Parse(const std::vector<std::string>* args, 
+               std::vector<std::string>* unconsumedArgs);
+
+    /// Add an argument.
+    void AddArgument(cmCommandArgument* arg);
+  private:
+    std::vector<cmCommandArgument*> Arguments;
+};
+
+
+#endif

+ 55 - 105
Source/cmExportCommand.cxx

@@ -22,6 +22,21 @@
 
 #include <cmsys/auto_ptr.hxx>
 
+cmExportCommand::cmExportCommand()
+:cmCommand()
+,ArgumentGroup()
+,Targets(&this->Helper, "TARGETS")
+,Append(&this->Helper, "APPEND", &ArgumentGroup)
+,Prefix(&this->Helper, "PREFIX", &ArgumentGroup)
+,Filename(&this->Helper, "FILE", &ArgumentGroup)
+{
+  // at first TARGETS
+  this->Targets.Follows(0);
+  // and after that the other options in any order
+  this->ArgumentGroup.Follows(&this->Targets);
+}
+
+
 // cmExportCommand
 bool cmExportCommand
 ::InitialPass(std::vector<std::string> const& args)
@@ -32,42 +47,50 @@ bool cmExportCommand
     return false;
     }
 
-  std::string filename;
-  std::string prefix;
-  std::string exportName;
-  std::vector<std::string> targets;
-  bool append = false;
-  if (!this->ParseArgs(args, filename, prefix, exportName, targets, append))
+  std::vector<std::string> unknownArgs;
+  this->Helper.Parse(&args, &unknownArgs);
+
+  if (!unknownArgs.empty())
+    {
+    this->SetError("Unknown arguments.");
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+    }
+
+  if (this->Targets.WasFound() == false)
     {
+    this->SetError("TARGETS option missing.");
+    cmSystemTools::SetFatalErrorOccured();
     return false;
     }
 
-  if ( !this->Makefile->CanIWriteThisFile(filename.c_str()) )
+
+  if ( !this->Makefile->CanIWriteThisFile(this->Filename.GetString().c_str()) )
     {
-    std::string e = "attempted to write a file: " + filename
+    std::string e = "attempted to write a file: " + this->Filename.GetString()
       + " into a source directory.";
     this->SetError(e.c_str());
     cmSystemTools::SetFatalErrorOccured();
     return false;
     }
 
-  if ((targets.empty()) || (filename.empty()))
+  if((this->Targets.GetVector().empty())||(this->Filename.GetString().empty()))
     {
     return true;
     }
 
   // Use copy-if-different if not appending.
   cmsys::auto_ptr<std::ofstream> foutPtr;
-  if(append)
+  if(this->Append.IsEnabled())
     {
     cmsys::auto_ptr<std::ofstream> ap(
-      new std::ofstream(filename.c_str(), std::ios::app));
+      new std::ofstream(this->Filename.GetString().c_str(), std::ios::app));
     foutPtr = ap;
     }
   else
     {
     cmsys::auto_ptr<cmGeneratedFileStream> ap(
-      new cmGeneratedFileStream(filename.c_str(), true));
+      new cmGeneratedFileStream(this->Filename.GetString().c_str(), true));
     ap->SetCopyIfDifferent(true);
     foutPtr = ap;
     }
@@ -75,7 +98,7 @@ bool cmExportCommand
 
   if (!fout)
     {
-    cmSystemTools::Error("Error Writing ", filename.c_str());
+    cmSystemTools::Error("Error Writing ", this->Filename.GetString().c_str());
     cmSystemTools::ReportLastSystemError("");
     return true;
     }
@@ -97,8 +120,9 @@ bool cmExportCommand
       }
     }
 
-  for(std::vector<std::string>::const_iterator currentTarget = targets.begin();
-      currentTarget != targets.end();
+  for(std::vector<std::string>::const_iterator 
+      currentTarget = this->Targets.GetVector().begin();
+      currentTarget != this->Targets.GetVector().end();
       ++currentTarget)
     {
     cmTarget* target = this->Makefile->GetLocalGenerator()->
@@ -112,8 +136,9 @@ bool cmExportCommand
       }
     }
 
-  for(std::vector<std::string>::const_iterator currentTarget = targets.begin();
-      currentTarget != targets.end();
+  for(std::vector<std::string>::const_iterator 
+      currentTarget = this->Targets.GetVector().begin();
+      currentTarget != this->Targets.GetVector().end();
       ++currentTarget)
     {
     // Look for a CMake target with the given name, which is an executable
@@ -129,26 +154,30 @@ bool cmExportCommand
       switch (target->GetType())
         {
         case cmTarget::EXECUTABLE:
-          fout << "ADD_EXECUTABLE(" << prefix.c_str() << currentTarget->c_str()
-                                                              << " IMPORT )\n";
+          fout << "ADD_EXECUTABLE(" 
+               << this->Prefix.GetString().c_str() << currentTarget->c_str()
+               << " IMPORT )\n";
           break;
         case cmTarget::STATIC_LIBRARY:
-          fout << "ADD_LIBRARY(" << prefix.c_str() << currentTarget->c_str()
-                                                       << " STATIC IMPORT )\n";
+          fout << "ADD_LIBRARY(" 
+               << this->Prefix.GetString().c_str() << currentTarget->c_str()
+               << " STATIC IMPORT )\n";
           break;
         case cmTarget::SHARED_LIBRARY:
-          fout << "ADD_LIBRARY(" << prefix.c_str() << currentTarget->c_str()
-                                                       << " SHARED IMPORT )\n";
+          fout << "ADD_LIBRARY(" 
+               << this->Prefix.GetString().c_str() << currentTarget->c_str()
+               << " SHARED IMPORT )\n";
           break;
         case cmTarget::MODULE_LIBRARY:
-          fout << "ADD_LIBRARY(" << prefix.c_str() << currentTarget->c_str()
-                                                       << " MODULE IMPORT )\n";
+          fout << "ADD_LIBRARY(" 
+               << this->Prefix.GetString().c_str() << currentTarget->c_str()
+               << " MODULE IMPORT )\n";
           break;
         default:  // should never happen
           break;
         }
 
-      fout << "SET_TARGET_PROPERTIES(" << prefix.c_str()
+      fout << "SET_TARGET_PROPERTIES(" << this->Prefix.GetString().c_str()
                                  << currentTarget->c_str() << " PROPERTIES \n"
         << "                      LOCATION " << target->GetLocation(0) << "\n";
       for(std::vector<std::string>::const_iterator
@@ -172,82 +201,3 @@ bool cmExportCommand
 
   return true;
 }
-
-bool cmExportCommand::ParseArgs(const std::vector<std::string>& args,
-                                std::string& filename,
-                                std::string& prefix,
-                                std::string& exportName,
-                                std::vector<std::string>& targets,
-                                bool& append) const
-{
-  bool doingFile = false;
-  bool doingPrefix = false;
-  bool doingTargets = false;
-  bool doingName = true;
-  for(std::vector<std::string>::const_iterator it = args.begin();
-      it != args.end();
-      ++it)
-    {
-    if (*it == "FILE")
-      {
-      doingFile = true;
-      doingPrefix = false;
-      doingName = false;
-      doingTargets = false;
-      }
-    else if (*it == "PREFIX")
-      {
-      doingFile = false;
-      doingPrefix = true;
-      doingName = false;
-      doingTargets = false;
-      }
-    else if (*it == "TARGETS")
-      {
-      doingFile = false;
-      doingPrefix = false;
-      doingName = false;
-      doingTargets = true;
-      }
-    else if (*it == "APPEND")
-      {
-      append = true;
-      doingFile = false;
-      doingPrefix = false;
-      doingName = false;
-      doingTargets = false;
-      }
-    else if (doingFile)
-      {
-      filename = *it;
-      doingFile = false;
-      doingPrefix = false;
-      doingName = false;
-      doingTargets = false;
-      }
-    else if (doingPrefix)
-      {
-      prefix = *it;
-      doingFile = false;
-      doingPrefix = false;
-      doingName = false;
-      doingTargets = false;
-      }
-    else if (doingTargets)
-      {
-      targets.push_back(*it);
-      }
-    else if (doingName)
-      {
-      exportName = *it;
-      doingFile = false;
-      doingPrefix = false;
-      doingName = false;
-      doingTargets = false;
-      }
-    else
-      {
-      }
-    }
-  return true;
-}

+ 6 - 4
Source/cmExportCommand.h

@@ -28,6 +28,7 @@
 class cmExportCommand : public cmCommand
 {
 public:
+  cmExportCommand();
   /**
    * This is a virtual constructor for the command.
    */
@@ -75,10 +76,11 @@ public:
   cmTypeMacro(cmExportCommand, cmCommand);
 
 private:
-  bool ParseArgs(const std::vector<std::string>& args, std::string& filename,
-                 std::string& prefix, std::string& exportName,
-                 std::vector<std::string>& targets, bool& append ) const;
-
+  cmCommandArgumentGroup ArgumentGroup;
+  cmCAStringVector Targets;
+  cmCAEnabler Append;
+  cmCAString Prefix;
+  cmCAString Filename;
 };