diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index b2617aeab7059931e03a57937281f8aa512fbca1..09c0acfd18c06f962dc994f2b1119ed51708d922 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -386,6 +386,8 @@ set(SRCS
   cmake.cxx
   cmake.h
 
+  cmCommand.cxx
+  cmCommand.h
   cmCommands.cxx
   cmCommands.h
   cmAddCompileOptionsCommand.cxx
diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3c839de859015bb59bab5f4b8b6f49409848e7d2
--- /dev/null
+++ b/Source/cmCommand.cxx
@@ -0,0 +1,48 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmCommand.h"
+
+bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
+                                  cmExecutionStatus& status)
+{
+  std::vector<std::string> expandedArguments;
+  if (!this->Makefile->ExpandArguments(args, expandedArguments)) {
+    // There was an error expanding arguments.  It was already
+    // reported, so we can skip this command without error.
+    return true;
+  }
+  return this->InitialPass(expandedArguments, status);
+}
+
+const char* cmCommand::GetError()
+{
+  if (this->Error.empty()) {
+    this->Error = this->GetName();
+    this->Error += " unknown error.";
+  }
+  return this->Error.c_str();
+}
+
+void cmCommand::SetError(const std::string& e)
+{
+  this->Error = this->GetName();
+  this->Error += " ";
+  this->Error += e;
+}
+
+bool cmCommand::Disallowed(cmPolicies::PolicyID pol, const char* e)
+{
+  switch (this->Makefile->GetPolicyStatus(pol)) {
+    case cmPolicies::WARN:
+      this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
+                                   cmPolicies::GetPolicyWarning(pol));
+    case cmPolicies::OLD:
+      return false;
+    case cmPolicies::REQUIRED_IF_USED:
+    case cmPolicies::REQUIRED_ALWAYS:
+    case cmPolicies::NEW:
+      this->Makefile->IssueMessage(cmake::FATAL_ERROR, e);
+      break;
+  }
+  return true;
+}
diff --git a/Source/cmCommand.h b/Source/cmCommand.h
index d8e337dd694b6094fe4d7040af9962a69d62c32a..9299c7128b928d1d360acf6f98d38966855fd66f 100644
--- a/Source/cmCommand.h
+++ b/Source/cmCommand.h
@@ -28,9 +28,9 @@ public:
    * Construct the command. By default it is enabled with no makefile.
    */
   cmCommand()
+    : Makefile(CM_NULLPTR)
+    , Enabled(true)
   {
-    this->Makefile = CM_NULLPTR;
-    this->Enabled = true;
   }
 
   /**
@@ -50,16 +50,7 @@ public:
    * arguments and then invokes the InitialPass.
    */
   virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                                 cmExecutionStatus& status)
-  {
-    std::vector<std::string> expandedArguments;
-    if (!this->Makefile->ExpandArguments(args, expandedArguments)) {
-      // There was an error expanding arguments.  It was already
-      // reported, so we can skip this command without error.
-      return true;
-    }
-    return this->InitialPass(expandedArguments, status);
-  }
+                                 cmExecutionStatus& status);
 
   /**
    * This is called when the command is first encountered in
@@ -127,42 +118,15 @@ public:
   /**
    * Return the last error string.
    */
-  const char* GetError()
-  {
-    if (this->Error.empty()) {
-      this->Error = this->GetName();
-      this->Error += " unknown error.";
-    }
-    return this->Error.c_str();
-  }
+  const char* GetError();
 
   /**
    * Set the error message
    */
-  void SetError(const std::string& e)
-  {
-    this->Error = this->GetName();
-    this->Error += " ";
-    this->Error += e;
-  }
+  void SetError(const std::string& e);
 
   /** Check if the command is disallowed by a policy.  */
-  bool Disallowed(cmPolicies::PolicyID pol, const char* e)
-  {
-    switch (this->Makefile->GetPolicyStatus(pol)) {
-      case cmPolicies::WARN:
-        this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
-                                     cmPolicies::GetPolicyWarning(pol));
-      case cmPolicies::OLD:
-        return false;
-      case cmPolicies::REQUIRED_IF_USED:
-      case cmPolicies::REQUIRED_ALWAYS:
-      case cmPolicies::NEW:
-        this->Makefile->IssueMessage(cmake::FATAL_ERROR, e);
-        break;
-    }
-    return true;
-  }
+  bool Disallowed(cmPolicies::PolicyID pol, const char* e);
 
 protected:
   cmMakefile* Makefile;
diff --git a/bootstrap b/bootstrap
index ab76526b225d2f4bb462c86ab3e237858918565d..4ce0dee423c560b05b6995b54a4576fd7f8006be 100755
--- a/bootstrap
+++ b/bootstrap
@@ -254,6 +254,7 @@ CMAKE_CXX_SOURCES="\
   cmCMakePolicyCommand \
   cmCPackPropertiesGenerator \
   cmCacheManager \
+  cmCommand \
   cmCommandArgumentLexer \
   cmCommandArgumentParser \
   cmCommandArgumentParserHelper \