diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index b9cf777a828d501bd52fefea5d78d1b485ae4f2e..a091cff464c3d133b93b99879cf214d64b9ce0c0 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -71,3 +71,27 @@ cmCustomCommandGenerator
       }
     }
 }
+
+//----------------------------------------------------------------------------
+const char* cmCustomCommandGenerator::GetComment() const
+{
+  return this->CC.GetComment();
+}
+
+//----------------------------------------------------------------------------
+std::string cmCustomCommandGenerator::GetWorkingDirectory() const
+{
+  return this->CC.GetWorkingDirectory();
+}
+
+//----------------------------------------------------------------------------
+std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
+{
+  return this->CC.GetOutputs();
+}
+
+//----------------------------------------------------------------------------
+std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const
+{
+  return this->CC.GetDepends();
+}
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 17d644af3a567b55493cf1b2eebf2413cc813e41..cbcdb413f8c453d1fbcf2fd80f0693067efeabd0 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -33,9 +33,14 @@ public:
                            const std::string& config,
                            cmMakefile* mf);
   ~cmCustomCommandGenerator();
+  cmCustomCommand const& GetCC() const { return this->CC; }
   unsigned int GetNumberOfCommands() const;
   std::string GetCommand(unsigned int c) const;
   void AppendArguments(unsigned int c, std::string& cmd) const;
+  const char* GetComment() const;
+  std::string GetWorkingDirectory() const;
+  std::vector<std::string> const& GetOutputs() const;
+  std::vector<std::string> const& GetDepends() const;
 };
 
 #endif
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 2dd31f3acdcedae6c62666977c40f49fef94ac8a..36196a23a0e5c41c9f4dc68649f6a11178767470 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1546,10 +1546,10 @@ void  cmGlobalXCodeGenerator
   for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
       i != commands.end(); ++i)
     {
-    cmCustomCommand const& cc = *i;
-    if(!cc.GetCommandLines().empty())
+    cmCustomCommandGenerator ccg(*i, configName, this->CurrentMakefile);
+    if(ccg.GetNumberOfCommands() > 0)
       {
-      const std::vector<std::string>& outputs = cc.GetOutputs();
+      const std::vector<std::string>& outputs = ccg.GetOutputs();
       if(!outputs.empty())
         {
         for(std::vector<std::string>::const_iterator o = outputs.begin();
@@ -1573,8 +1573,8 @@ void  cmGlobalXCodeGenerator
         {
         cmOStringStream str;
         str << "_buildpart_" << count++ ;
-        tname[&cc] = std::string(target.GetName()) + str.str();
-        makefileStream << "\\\n\t" << tname[&cc];
+        tname[&ccg.GetCC()] = std::string(target.GetName()) + str.str();
+        makefileStream << "\\\n\t" << tname[&ccg.GetCC()];
         }
       }
     }
@@ -1582,12 +1582,11 @@ void  cmGlobalXCodeGenerator
   for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
       i != commands.end(); ++i)
     {
-    cmCustomCommand const& cc = *i;
-    if(!cc.GetCommandLines().empty())
+    cmCustomCommandGenerator ccg(*i, configName, this->CurrentMakefile);
+    if(ccg.GetNumberOfCommands() > 0)
       {
-      cmCustomCommandGenerator ccg(cc, configName, this->CurrentMakefile);
       makefileStream << "\n";
-      const std::vector<std::string>& outputs = cc.GetOutputs();
+      const std::vector<std::string>& outputs = ccg.GetOutputs();
       if(!outputs.empty())
         {
         // There is at least one output, start the rule for it
@@ -1598,11 +1597,11 @@ void  cmGlobalXCodeGenerator
       else
         {
         // There are no outputs.  Use the generated force rule name.
-        makefileStream << tname[&cc] << ": ";
+        makefileStream << tname[&ccg.GetCC()] << ": ";
         }
       for(std::vector<std::string>::const_iterator d =
-          cc.GetDepends().begin();
-          d != cc.GetDepends().end(); ++d)
+          ccg.GetDepends().begin();
+          d != ccg.GetDepends().end(); ++d)
         {
         std::string dep;
         if(this->CurrentLocalGenerator
@@ -1614,11 +1613,11 @@ void  cmGlobalXCodeGenerator
         }
       makefileStream << "\n";
 
-      if(const char* comment = cc.GetComment())
+      if(const char* comment = ccg.GetComment())
         {
         std::string echo_cmd = "echo ";
         echo_cmd += (this->CurrentLocalGenerator->
-                     EscapeForShell(comment, cc.GetEscapeAllowMakeVars()));
+          EscapeForShell(comment, ccg.GetCC().GetEscapeAllowMakeVars()));
         makefileStream << "\t" << echo_cmd.c_str() << "\n";
         }
 
@@ -1630,7 +1629,7 @@ void  cmGlobalXCodeGenerator
         cmSystemTools::ReplaceString(cmd2, "/./", "/");
         cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
         std::string cmd;
-        std::string wd = cc.GetWorkingDirectory();
+        std::string wd = ccg.GetWorkingDirectory();
         if(!wd.empty())
           {
           cmd += "cd ";
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index de8dd514cbd694708c8cda24b89a8899a7d309d0..ebcfa08c592bde6f2bb414e7c2176e6d48229d33 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -22,6 +22,7 @@
 #include "cmSourceFile.h"
 #include "cmTest.h"
 #include "cmTestGenerator.h"
+#include "cmCustomCommandGenerator.h"
 #include "cmVersion.h"
 #include "cmake.h"
 
@@ -2482,23 +2483,23 @@ void cmLocalGenerator::AppendFeatureOptions(
 
 //----------------------------------------------------------------------------
 std::string
-cmLocalGenerator::ConstructComment(const cmCustomCommand& cc,
+cmLocalGenerator::ConstructComment(cmCustomCommandGenerator const& ccg,
                                    const char* default_comment)
 {
   // Check for a comment provided with the command.
-  if(cc.GetComment())
+  if(ccg.GetComment())
     {
-    return cc.GetComment();
+    return ccg.GetComment();
     }
 
   // Construct a reasonable default comment if possible.
-  if(!cc.GetOutputs().empty())
+  if(!ccg.GetOutputs().empty())
     {
     std::string comment;
     comment = "Generating ";
     const char* sep = "";
-    for(std::vector<std::string>::const_iterator o = cc.GetOutputs().begin();
-        o != cc.GetOutputs().end(); ++o)
+    for(std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
+        o != ccg.GetOutputs().end(); ++o)
       {
       comment += sep;
       comment += this->Convert(*o, cmLocalGenerator::START_OUTPUT);
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 4d62833d9f9924014d757d719b4a8104df65cfba..afcaee9b568b5fb1025116c3ab6fcbc2acc89a3b 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -21,6 +21,7 @@ class cmTarget;
 class cmTargetManifest;
 class cmSourceFile;
 class cmCustomCommand;
+class cmCustomCommandGenerator;
 
 /** \class cmLocalGenerator
  * \brief Create required build files for a directory.
@@ -350,7 +351,7 @@ public:
                                   const std::string& targetName,
                                   const char* fname);
   /** Construct a comment for a custom command.  */
-  std::string ConstructComment(const cmCustomCommand& cc,
+  std::string ConstructComment(cmCustomCommandGenerator const& ccg,
                                const char* default_comment = "");
   // Compute object file names.
   std::string GetObjectFileNameWithoutTarget(const cmSourceFile& source,
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index d68a07bc053cd46f41a1459da2a9cc0b6524badb..7c4aab87c8e745d2c1ca70fbeb662184cbe0a041 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -303,10 +303,11 @@ cmLocalNinjaGenerator
   this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs);
 }
 
-void cmLocalNinjaGenerator::AppendCustomCommandDeps(const cmCustomCommand *cc,
-                                                    cmNinjaDeps &ninjaDeps)
+void cmLocalNinjaGenerator::AppendCustomCommandDeps(
+  cmCustomCommandGenerator const& ccg,
+  cmNinjaDeps &ninjaDeps)
 {
-  const std::vector<std::string> &deps = cc->GetDepends();
+  const std::vector<std::string> &deps = ccg.GetDepends();
   for (std::vector<std::string>::const_iterator i = deps.begin();
        i != deps.end(); ++i) {
     std::string dep;
@@ -359,12 +360,12 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
   return cmd.str();
 }
 
-void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc,
-                                            std::vector<std::string> &cmdLines)
+void cmLocalNinjaGenerator::AppendCustomCommandLines(
+  cmCustomCommandGenerator const& ccg,
+  std::vector<std::string> &cmdLines)
 {
-  cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->Makefile);
   if (ccg.GetNumberOfCommands() > 0) {
-    std::string wd = cc->GetWorkingDirectory();
+    std::string wd = ccg.GetWorkingDirectory();
     if (wd.empty())
       wd = this->GetMakefile()->GetStartOutputDirectory();
 
@@ -378,7 +379,7 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc,
     cmdLines.push_back(cdCmd.str());
   }
 
-  std::string launcher = this->MakeCustomLauncher(*cc);
+  std::string launcher = this->MakeCustomLauncher(ccg);
 
   for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
     cmdLines.push_back(launcher +
@@ -396,19 +397,21 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
   if (this->GetGlobalNinjaGenerator()->SeenCustomCommand(cc))
     return;
 
-  const std::vector<std::string> &outputs = cc->GetOutputs();
+  cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->Makefile);
+
+  const std::vector<std::string> &outputs = ccg.GetOutputs();
   cmNinjaDeps ninjaOutputs(outputs.size()), ninjaDeps;
 
   std::transform(outputs.begin(), outputs.end(),
                  ninjaOutputs.begin(), MapToNinjaPath());
-  this->AppendCustomCommandDeps(cc, ninjaDeps);
+  this->AppendCustomCommandDeps(ccg, ninjaDeps);
 
   for (cmNinjaDeps::iterator i = ninjaOutputs.begin(); i != ninjaOutputs.end();
        ++i)
     this->GetGlobalNinjaGenerator()->SeenCustomCommandOutput(*i);
 
   std::vector<std::string> cmdLines;
-  this->AppendCustomCommandLines(cc, cmdLines);
+  this->AppendCustomCommandLines(ccg, cmdLines);
 
   if (cmdLines.empty()) {
     this->GetGlobalNinjaGenerator()->WritePhonyBuild(
@@ -423,7 +426,7 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
   } else {
     this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
       this->BuildCommandLine(cmdLines),
-      this->ConstructComment(*cc),
+      this->ConstructComment(ccg),
       "Custom command for " + ninjaOutputs[0],
       ninjaOutputs,
       ninjaDeps,
@@ -472,7 +475,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
 }
 
 std::string cmLocalNinjaGenerator::MakeCustomLauncher(
-  const cmCustomCommand& cc)
+  cmCustomCommandGenerator const& ccg)
 {
   const char* property = "RULE_LAUNCH_CUSTOM";
   const char* property_value = this->Makefile->GetProperty(property);
@@ -487,11 +490,11 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
   RuleVariables vars;
   vars.RuleLauncher = property;
   std::string output;
-  const std::vector<std::string>& outputs = cc.GetOutputs();
+  const std::vector<std::string>& outputs = ccg.GetOutputs();
   if(!outputs.empty())
   {
     RelativeRoot relative_root =
-      cc.GetWorkingDirectory().empty() ? START_OUTPUT : NONE;
+      ccg.GetWorkingDirectory().empty() ? START_OUTPUT : NONE;
 
     output = this->Convert(outputs[0], relative_root, SHELL);
   }
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 2d870fb77636efcfe17da26a11e8734f315572f9..9d0b7b5bc31019ed9b0123db080f1f5c06bbb360 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -16,6 +16,7 @@
 #  include "cmLocalGenerator.h"
 #  include "cmNinjaTypes.h"
 
+class cmCustomCommandGenerator;
 class cmGlobalNinjaGenerator;
 class cmGeneratedFileStream;
 class cmake;
@@ -92,9 +93,9 @@ public:
   void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
 
   void AddCustomCommandTarget(cmCustomCommand const* cc, cmTarget* target);
-  void AppendCustomCommandLines(const cmCustomCommand *cc,
+  void AppendCustomCommandLines(cmCustomCommandGenerator const& ccg,
                                 std::vector<std::string> &cmdLines);
-  void AppendCustomCommandDeps(const cmCustomCommand *cc,
+  void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg,
                                cmNinjaDeps &ninjaDeps);
 
   virtual std::string ConvertToLinkReference(std::string const& lib,
@@ -124,7 +125,7 @@ private:
 
   void WriteCustomCommandBuildStatements();
 
-  std::string MakeCustomLauncher(const cmCustomCommand& cc);
+  std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
 
   std::string ConfigName;
   std::string HomeRelativeOutputPath;
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index d3f63f51d04e2e7ded07b6da6424ce2ee8300056..9f12ffef7a7b2c00c64f0044209375a7e1c179a4 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -960,7 +960,9 @@ cmLocalUnixMakefileGenerator3
   for(std::vector<cmCustomCommand>::const_iterator i = ccs.begin();
       i != ccs.end(); ++i)
     {
-    this->AppendCustomDepend(depends, *i);
+    cmCustomCommandGenerator ccg(*i, this->ConfigurationName,
+                                 this->Makefile);
+    this->AppendCustomDepend(depends, ccg);
     }
 }
 
@@ -968,10 +970,10 @@ cmLocalUnixMakefileGenerator3
 void
 cmLocalUnixMakefileGenerator3
 ::AppendCustomDepend(std::vector<std::string>& depends,
-                     const cmCustomCommand& cc)
+                     cmCustomCommandGenerator const& ccg)
 {
-  for(std::vector<std::string>::const_iterator d = cc.GetDepends().begin();
-      d != cc.GetDepends().end(); ++d)
+  for(std::vector<std::string>::const_iterator d = ccg.GetDepends().begin();
+      d != ccg.GetDepends().end(); ++d)
     {
     // Lookup the real name of the dependency in case it is a CMake target.
     std::string dep;
@@ -994,7 +996,9 @@ cmLocalUnixMakefileGenerator3
   for(std::vector<cmCustomCommand>::const_iterator i = ccs.begin();
       i != ccs.end(); ++i)
     {
-    this->AppendCustomCommand(commands, *i, target, true, relative);
+    cmCustomCommandGenerator ccg(*i, this->ConfigurationName,
+                                 this->Makefile);
+    this->AppendCustomCommand(commands, ccg, target, true, relative);
     }
 }
 
@@ -1002,7 +1006,7 @@ cmLocalUnixMakefileGenerator3
 void
 cmLocalUnixMakefileGenerator3
 ::AppendCustomCommand(std::vector<std::string>& commands,
-                      const cmCustomCommand& cc,
+                      cmCustomCommandGenerator const& ccg,
                       cmTarget* target,
                       bool echo_comment,
                       cmLocalGenerator::RelativeRoot relative,
@@ -1014,8 +1018,8 @@ cmLocalUnixMakefileGenerator3
   // their comments generated elsewhere.
   if(echo_comment)
     {
-    const char* comment = cc.GetComment();
-    if(comment && *comment)
+    const char* comment = ccg.GetComment();
+    if(comment && !*comment)
       {
       this->AppendEcho(commands, comment,
                        cmLocalUnixMakefileGenerator3::EchoGenerate);
@@ -1024,7 +1028,7 @@ cmLocalUnixMakefileGenerator3
 
   // if the command specified a working directory use it.
   std::string dir  = this->Makefile->GetStartOutputDirectory();
-  std::string workingDir = cc.GetWorkingDirectory();
+  std::string workingDir = ccg.GetWorkingDirectory();
   if(!workingDir.empty())
     {
     dir = workingDir;
@@ -1033,8 +1037,6 @@ cmLocalUnixMakefileGenerator3
     {
     *content << dir;
     }
-  cmCustomCommandGenerator ccg(cc, this->ConfigurationName,
-                               this->Makefile);
 
   // Add each command line to the set of commands.
   std::vector<std::string> commands1;
@@ -1079,7 +1081,7 @@ cmLocalUnixMakefileGenerator3
         cmd = "./" + cmd;
         }
       std::string launcher =
-        this->MakeLauncher(cc, target,
+        this->MakeLauncher(ccg, target,
                            workingDir.empty()? START_OUTPUT : NONE);
       cmd = launcher + this->ConvertShellCommand(cmd, NONE);
 
@@ -1134,9 +1136,9 @@ cmLocalUnixMakefileGenerator3
 
 //----------------------------------------------------------------------------
 std::string
-cmLocalUnixMakefileGenerator3::MakeLauncher(const cmCustomCommand& cc,
-                                            cmTarget* target,
-                                            RelativeRoot relative)
+cmLocalUnixMakefileGenerator3::MakeLauncher(
+  cmCustomCommandGenerator const& ccg,
+  cmTarget* target, RelativeRoot relative)
 {
   // Short-circuit if there is no launcher.
   const char* prop = "RULE_LAUNCH_CUSTOM";
@@ -1152,7 +1154,7 @@ cmLocalUnixMakefileGenerator3::MakeLauncher(const cmCustomCommand& cc,
   vars.RuleLauncher = prop;
   vars.CMTarget = target;
   std::string output;
-  const std::vector<std::string>& outputs = cc.GetOutputs();
+  const std::vector<std::string>& outputs = ccg.GetOutputs();
   if(!outputs.empty())
     {
     output = this->Convert(outputs[0], relative, SHELL);
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 7987c961f158d96e912baccd2e4b0c47c539f863..d5042472d9a6ebe08df273858e04cfe59eb80e56 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -18,6 +18,7 @@
 #include "cmDepends.h"
 
 class cmCustomCommand;
+class cmCustomCommandGenerator;
 class cmDependInformation;
 class cmDepends;
 class cmMakefileTargetGenerator;
@@ -289,14 +290,14 @@ protected:
   void AppendCustomDepends(std::vector<std::string>& depends,
                            const std::vector<cmCustomCommand>& ccs);
   void AppendCustomDepend(std::vector<std::string>& depends,
-                          const cmCustomCommand& cc);
+                          cmCustomCommandGenerator const& cc);
   void AppendCustomCommands(std::vector<std::string>& commands,
                             const std::vector<cmCustomCommand>& ccs,
                             cmTarget* target,
                             cmLocalGenerator::RelativeRoot relative =
                             cmLocalGenerator::HOME_OUTPUT);
   void AppendCustomCommand(std::vector<std::string>& commands,
-                           const cmCustomCommand& cc,
+                           cmCustomCommandGenerator const& ccg,
                            cmTarget* target,
                            bool echo_comment=false,
                            cmLocalGenerator::RelativeRoot relative =
@@ -313,8 +314,8 @@ protected:
 
 private:
   std::string ConvertShellCommand(std::string const& cmd, RelativeRoot root);
-  std::string MakeLauncher(const cmCustomCommand& cc, cmTarget* target,
-                           RelativeRoot relative);
+  std::string MakeLauncher(cmCustomCommandGenerator const& ccg,
+                           cmTarget* target, RelativeRoot relative);
 
   friend class cmMakefileTargetGenerator;
   friend class cmMakefileExecutableTargetGenerator;
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index d7130248b060a225a3b36fc5e09e7f01452e3933..2ab25cc52caf1409e2b6ffa6847489dd1ab125ef 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -16,6 +16,7 @@
 #include "cmSourceFile.h"
 #include "cmCacheManager.h"
 #include "cmGeneratorTarget.h"
+#include "cmCustomCommandGenerator.h"
 #include "cmake.h"
 
 #include "cmComputeLinkInformation.h"
@@ -59,6 +60,7 @@ public:
     }
   void Write(cmCustomCommand const& cc)
     {
+    cmCustomCommandGenerator ccg(cc, this->Config, this->LG->GetMakefile());
     if(this->First)
       {
       this->Code += this->Event + "_Cmds=";
@@ -68,7 +70,7 @@ public:
       {
       this->Code += "\\\n\t";
       }
-    this->Code += this->LG->ConstructScript(cc, this->Config, "\\\n\t");
+    this->Code += this->LG->ConstructScript(ccg, "\\\n\t");
     }
 private:
   cmLocalVisualStudio6Generator* LG;
@@ -575,14 +577,18 @@ cmLocalVisualStudio6Generator
                            target.GetName().size() + 30)];
   sprintf(output,"%s/%s_force_%i", this->Makefile->GetStartOutputDirectory(),
           target.GetName().c_str(), count);
-  std::string comment = this->ConstructComment(origCommand, "<hack>");
+  const char* comment = origCommand.GetComment();
+  if(!comment && origCommand.GetOutputs().empty())
+    {
+    comment = "<hack>";
+    }
 
   // Add the rule with the given dependencies and commands.
   std::string no_main_dependency = "";
   if(cmSourceFile* outsf =
      this->Makefile->AddCustomCommandToOutput(
        output, depends, no_main_dependency,
-       origCommand.GetCommandLines(), comment.c_str(),
+       origCommand.GetCommandLines(), comment,
        origCommand.GetWorkingDirectory().c_str()))
     {
     target.AddSourceFile(outsf);
@@ -604,20 +610,21 @@ cmLocalVisualStudio6Generator
                   const cmCustomCommand& command,
                   const char* flags)
 {
-  std::string comment =
-    this->ConstructComment(command, "Building Custom Rule $(InputPath)");
-  if(comment == "<hack>")
-    {
-    comment = "";
-    }
-
   // Write the rule for each configuration.
   std::vector<std::string>::iterator i;
   for(i = this->Configurations.begin(); i != this->Configurations.end(); ++i)
     {
     std::string config = this->GetConfigName(*i);
+    cmCustomCommandGenerator ccg(command, config, this->Makefile);
+    std::string comment =
+      this->ConstructComment(ccg, "Building Custom Rule $(InputPath)");
+    if(comment == "<hack>")
+      {
+      comment = "";
+      }
+
     std::string script =
-      this->ConstructScript(command, config.c_str(), "\\\n\t");
+      this->ConstructScript(ccg, "\\\n\t");
 
     if (i == this->Configurations.begin())
       {
@@ -634,8 +641,8 @@ cmLocalVisualStudio6Generator
     // Write out the dependencies for the rule.
     fout << "USERDEP__HACK=";
     for(std::vector<std::string>::const_iterator d =
-          command.GetDepends().begin();
-        d != command.GetDepends().end();
+          ccg.GetDepends().begin();
+        d != ccg.GetDepends().end();
         ++d)
       {
       // Lookup the real name of the dependency in case it is a CMake target.
@@ -655,7 +662,7 @@ cmLocalVisualStudio6Generator
       fout << " " << comment.c_str();
       }
     fout << "\n\n";
-    if(command.GetOutputs().empty())
+    if(ccg.GetOutputs().empty())
       {
       fout << source
            << "_force :  \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
@@ -664,8 +671,8 @@ cmLocalVisualStudio6Generator
     else
       {
       for(std::vector<std::string>::const_iterator o =
-          command.GetOutputs().begin();
-          o != command.GetOutputs().end();
+          ccg.GetOutputs().begin();
+          o != ccg.GetOutputs().end();
           ++o)
         {
         // Write a rule for every output generated by this command.
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 4491140150680fa6a71546ec82dc624df5cfc08c..14ad56778732cb32a01779592da7ccaa7e077196 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -18,6 +18,7 @@
 #include "cmSourceFile.h"
 #include "cmCacheManager.h"
 #include "cmGeneratorTarget.h"
+#include "cmCustomCommandGenerator.h"
 #include "cmake.h"
 
 #include "cmComputeLinkInformation.h"
@@ -609,9 +610,10 @@ public:
     }
   void Write(cmCustomCommand const& cc)
     {
+    cmCustomCommandGenerator ccg(cc, this->Config, this->LG->GetMakefile());
     if(this->First)
       {
-      const char* comment = cc.GetComment();
+      const char* comment = ccg.GetComment();
       if(comment && *comment)
         {
         this->Stream << "\nDescription=\""
@@ -624,7 +626,7 @@ public:
       {
       this->Stream << this->LG->EscapeForXML("\n");
       }
-    std::string script = this->LG->ConstructScript(cc, this->Config);
+    std::string script = this->LG->ConstructScript(ccg);
     this->Stream << this->LG->EscapeForXML(script.c_str());
     }
 private:
@@ -1791,8 +1793,6 @@ WriteCustomRule(std::ostream& fout,
                 const cmCustomCommand& command,
                 FCInfo& fcinfo)
 {
-  std::string comment = this->ConstructComment(command);
-
   // Write the rule for each configuration.
   std::vector<std::string>::iterator i;
   std::vector<std::string> *configs =
@@ -1810,6 +1810,7 @@ WriteCustomRule(std::ostream& fout,
     }
   for(i = configs->begin(); i != configs->end(); ++i)
     {
+    cmCustomCommandGenerator ccg(command, *i, this->Makefile);
     cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[*i];
     fout << "\t\t\t\t<FileConfiguration\n";
     fout << "\t\t\t\t\tName=\"" << *i << "|" << this->PlatformName << "\">\n";
@@ -1821,7 +1822,8 @@ WriteCustomRule(std::ostream& fout,
            << this->EscapeForXML(fc.CompileFlags.c_str()) << "\"/>\n";
       }
 
-    std::string script = this->ConstructScript(command, i->c_str());
+    std::string comment = this->ConstructComment(ccg);
+    std::string script = this->ConstructScript(ccg);
     if(this->FortranProject)
       {
       cmSystemTools::ReplaceString(script, "$(Configuration)", i->c_str());
@@ -1833,7 +1835,7 @@ WriteCustomRule(std::ostream& fout,
          << "\t\t\t\t\tCommandLine=\""
          << this->EscapeForXML(script.c_str()) << "\"\n"
          << "\t\t\t\t\tAdditionalDependencies=\"";
-    if(command.GetDepends().empty())
+    if(ccg.GetDepends().empty())
       {
       // There are no real dependencies.  Produce an artificial one to
       // make sure the rule runs reliably.
@@ -1848,8 +1850,8 @@ WriteCustomRule(std::ostream& fout,
       {
       // Write out the dependencies for the rule.
       for(std::vector<std::string>::const_iterator d =
-          command.GetDepends().begin();
-          d != command.GetDepends().end();
+          ccg.GetDepends().begin();
+          d != ccg.GetDepends().end();
           ++d)
         {
         // Get the real name of the dependency in case it is a CMake target.
@@ -1863,7 +1865,7 @@ WriteCustomRule(std::ostream& fout,
       }
     fout << "\"\n";
     fout << "\t\t\t\t\tOutputs=\"";
-    if(command.GetOutputs().empty())
+    if(ccg.GetOutputs().empty())
       {
       fout << source << "_force";
       }
@@ -1872,8 +1874,8 @@ WriteCustomRule(std::ostream& fout,
       // Write a rule for the output generated by this command.
       const char* sep = "";
       for(std::vector<std::string>::const_iterator o =
-          command.GetOutputs().begin();
-          o != command.GetOutputs().end();
+          ccg.GetOutputs().begin();
+          o != ccg.GetOutputs().end();
           ++o)
         {
         fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str());
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 3075c15672d08eeb407c063e786d6a35000e79ad..613ee975cec24b58a386a2e54f16cb8d2a661e01 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -79,13 +79,11 @@ const char* cmLocalVisualStudioGenerator::GetReportErrorLabel() const
 //----------------------------------------------------------------------------
 std::string
 cmLocalVisualStudioGenerator
-::ConstructScript(cmCustomCommand const& cc,
-                  const std::string& configName,
+::ConstructScript(cmCustomCommandGenerator const& ccg,
                   const std::string& newline_text)
 {
   bool useLocal = this->CustomCommandUseLocal();
-  std::string workingDirectory = cc.GetWorkingDirectory();
-  cmCustomCommandGenerator ccg(cc, configName, this->Makefile);
+  std::string workingDirectory = ccg.GetWorkingDirectory();
   RelativeRoot relativeRoot = workingDirectory.empty()? START_OUTPUT : NONE;
 
   // Avoid leading or trailing newlines.
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index 94a6293b658ac91e618f2fc1198976ef0482c20e..a89e21930de8e093b81fa20704c02bf9380ed80d 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -19,6 +19,7 @@
 class cmSourceFile;
 class cmSourceGroup;
 class cmCustomCommand;
+class cmCustomCommandGenerator;
 
 /** \class cmLocalVisualStudioGenerator
  * \brief Base class for Visual Studio generators.
@@ -46,8 +47,7 @@ public:
   virtual ~cmLocalVisualStudioGenerator();
 
   /** Construct a script from the given list of command lines.  */
-  std::string ConstructScript(cmCustomCommand const& cc,
-                              const std::string& configName,
+  std::string ConstructScript(cmCustomCommandGenerator const& ccg,
                               const std::string& newline = "\n");
 
   /** Label to which to jump in a batch file after a failed step in a
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 983fd997f8cd523c9e87a715b2444c28e67078a2..3161abaf5c5cb908c9f541450e208b0126ded506 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -21,6 +21,7 @@
 #include "cmTarget.h"
 #include "cmake.h"
 #include "cmComputeLinkInformation.h"
+#include "cmCustomCommandGenerator.h"
 #include "cmGeneratorExpression.h"
 
 #include "cmMakefileExecutableTargetGenerator.h"
@@ -158,11 +159,13 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
         si = customCommands.begin();
       si != customCommands.end(); ++si)
     {
-    cmCustomCommand const* cc = (*si)->GetCustomCommand();
-    this->GenerateCustomRuleFile(*cc);
+    cmCustomCommandGenerator ccg(*(*si)->GetCustomCommand(),
+                                 this->ConfigName,
+                                 this->Makefile);
+    this->GenerateCustomRuleFile(ccg);
     if (clean)
       {
-      const std::vector<std::string>& outputs = cc->GetOutputs();
+      const std::vector<std::string>& outputs = ccg.GetOutputs();
       for(std::vector<std::string>::const_iterator o = outputs.begin();
           o != outputs.end(); ++o)
         {
@@ -1178,7 +1181,8 @@ cmMakefileTargetGenerator
     {
     if(cmCustomCommand* cc = (*source)->GetCustomCommand())
       {
-      const std::vector<std::string>& outputs = cc->GetOutputs();
+      cmCustomCommandGenerator ccg(*cc, this->ConfigName, this->Makefile);
+      const std::vector<std::string>& outputs = ccg.GetOutputs();
       for(std::vector<std::string>::const_iterator o = outputs.begin();
           o != outputs.end(); ++o)
         {
@@ -1210,11 +1214,11 @@ void cmMakefileTargetGenerator
 
 //----------------------------------------------------------------------------
 void cmMakefileTargetGenerator
-::GenerateCustomRuleFile(const cmCustomCommand& cc)
+::GenerateCustomRuleFile(cmCustomCommandGenerator const& ccg)
 {
   // Collect the commands.
   std::vector<std::string> commands;
-  std::string comment = this->LocalGenerator->ConstructComment(cc);
+  std::string comment = this->LocalGenerator->ConstructComment(ccg);
   if(!comment.empty())
     {
     // add in a progress call if needed
@@ -1229,19 +1233,19 @@ void cmMakefileTargetGenerator
 
   // Now append the actual user-specified commands.
   cmOStringStream content;
-  this->LocalGenerator->AppendCustomCommand(commands, cc, this->Target, false,
+  this->LocalGenerator->AppendCustomCommand(commands, ccg, this->Target, false,
                                             cmLocalGenerator::HOME_OUTPUT,
                                             &content);
 
   // Collect the dependencies.
   std::vector<std::string> depends;
-  this->LocalGenerator->AppendCustomDepend(depends, cc);
+  this->LocalGenerator->AppendCustomDepend(depends, ccg);
 
   // Check whether we need to bother checking for a symbolic output.
   bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
 
   // Write the rule.
-  const std::vector<std::string>& outputs = cc.GetOutputs();
+  const std::vector<std::string>& outputs = ccg.GetOutputs();
   std::vector<std::string>::const_iterator o = outputs.begin();
   {
   bool symbolic = false;
@@ -1259,7 +1263,7 @@ void cmMakefileTargetGenerator
   // If the rule has changed make sure the output is rebuilt.
   if(!symbolic)
     {
-    this->GlobalGenerator->AddRuleHash(cc.GetOutputs(), content.str());
+    this->GlobalGenerator->AddRuleHash(ccg.GetOutputs(), content.str());
     }
   }
 
@@ -1280,8 +1284,8 @@ void cmMakefileTargetGenerator
 
   // Setup implicit dependency scanning.
   for(cmCustomCommand::ImplicitDependsList::const_iterator
-        idi = cc.GetImplicitDepends().begin();
-      idi != cc.GetImplicitDepends().end(); ++idi)
+        idi = ccg.GetCC().GetImplicitDepends().begin();
+      idi != ccg.GetCC().GetImplicitDepends().end(); ++idi)
     {
     std::string objFullPath =
       this->Convert(outputs[0], cmLocalGenerator::FULL);
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index bed945bb5bf7538fc638008532631bc622adfa7b..97c58b9824e2ec88b662ab90e273c8db196a9ce1 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -15,7 +15,7 @@
 #include "cmLocalUnixMakefileGenerator3.h"
 #include "cmOSXBundleGenerator.h"
 
-class cmCustomCommand;
+class cmCustomCommandGenerator;
 class cmDependInformation;
 class cmDepends;
 class cmGeneratorTarget;
@@ -102,7 +102,7 @@ protected:
                               std::vector<std::string>& depends);
 
   // write the build rule for a custom command
-  void GenerateCustomRuleFile(const cmCustomCommand& cc);
+  void GenerateCustomRuleFile(cmCustomCommandGenerator const& ccg);
 
   // write a rule to drive building of more than one output from
   // another rule
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 34b2e63191a3c3662c3acdc15730ca3d5508e2e2..2d1bc76df621da9c794c4703abb5ecf285e7b2bb 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -18,6 +18,7 @@
 #include "cmMakefile.h"
 #include "cmOSXBundleGenerator.h"
 #include "cmGeneratorTarget.h"
+#include "cmCustomCommandGenerator.h"
 
 #include <assert.h>
 #include <algorithm>
@@ -555,7 +556,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     for (std::vector<cmCustomCommand>::const_iterator
          ci = cmdLists[i]->begin();
          ci != cmdLists[i]->end(); ++ci) {
-      this->GetLocalGenerator()->AppendCustomCommandLines(&*ci,
+      cmCustomCommandGenerator ccg(*ci, this->GetConfigName(),
+                                   this->GetMakefile());
+      this->GetLocalGenerator()->AppendCustomCommandLines(ccg,
                                                           *cmdLineLists[i]);
     }
   }
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index d6520184a64c3f6b99068e54fe5c6765420a3ef8..ed3782c2ab84578f4172d495a77c61c9852edaf4 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -577,7 +577,9 @@ cmNinjaTargetGenerator
       si != customCommands.end(); ++si)
     {
     cmCustomCommand const* cc = (*si)->GetCustomCommand();
-    const std::vector<std::string>& ccoutputs = cc->GetOutputs();
+    cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
+                                 this->GetMakefile());
+    const std::vector<std::string>& ccoutputs = ccg.GetOutputs();
     std::transform(ccoutputs.begin(), ccoutputs.end(),
                    std::back_inserter(orderOnlyDeps), MapToNinjaPath());
     }
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 1a7b445bb172b9b1458184b4e8365d26ea396a7c..0fb40c04332e08a40f955f5bf2a5fbedc563dba1 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -17,6 +17,7 @@
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmTarget.h"
+#include "cmCustomCommandGenerator.h"
 
 cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
     cmGeneratorTarget *target)
@@ -37,8 +38,10 @@ void cmNinjaUtilityTargetGenerator::Generate()
   for (unsigned i = 0; i != 2; ++i) {
     for (std::vector<cmCustomCommand>::const_iterator
          ci = cmdLists[i]->begin(); ci != cmdLists[i]->end(); ++ci) {
-      this->GetLocalGenerator()->AppendCustomCommandDeps(&*ci, deps);
-      this->GetLocalGenerator()->AppendCustomCommandLines(&*ci, commands);
+      cmCustomCommandGenerator ccg(*ci, this->GetConfigName(),
+                                   this->GetMakefile());
+      this->GetLocalGenerator()->AppendCustomCommandDeps(ccg, deps);
+      this->GetLocalGenerator()->AppendCustomCommandLines(ccg, commands);
     }
   }
 
@@ -49,10 +52,12 @@ void cmNinjaUtilityTargetGenerator::Generate()
     {
     if(cmCustomCommand* cc = (*source)->GetCustomCommand())
       {
+      cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
+                                   this->GetMakefile());
       this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
 
       // Depend on all custom command outputs.
-      const std::vector<std::string>& ccOutputs = cc->GetOutputs();
+      const std::vector<std::string>& ccOutputs = ccg.GetOutputs();
       std::transform(ccOutputs.begin(), ccOutputs.end(),
                      std::back_inserter(deps), MapToNinjaPath());
       }
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 90155b4132d4b7c1defe9dc1d0d4a63e6a3ea21b..7c55f645e4db6da56b857845ee65b51cbe2b1a8d 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -19,6 +19,7 @@
 #include "cmSourceFile.h"
 #include "cmVisualStudioGeneratorOptions.h"
 #include "cmLocalVisualStudio7Generator.h"
+#include "cmCustomCommandGenerator.h"
 #include "cmVS10CLFlagTable.h"
 #include "cmVS10LinkFlagTable.h"
 #include "cmVS10LibFlagTable.h"
@@ -616,8 +617,6 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
       }
     }
   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
-  std::string comment = lg->ConstructComment(command);
-  comment = cmVS10EscapeComment(comment);
   std::vector<std::string> *configs =
     static_cast<cmGlobalVisualStudio7Generator *>
     (this->GlobalGenerator)->GetConfigurations();
@@ -627,8 +626,11 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
   for(std::vector<std::string>::iterator i = configs->begin();
       i != configs->end(); ++i)
     {
+    cmCustomCommandGenerator ccg(command, *i, this->Makefile);
+    std::string comment = lg->ConstructComment(ccg);
+    comment = cmVS10EscapeComment(comment);
     std::string script =
-      cmVS10EscapeXML(lg->ConstructScript(command, i->c_str()));
+      cmVS10EscapeXML(lg->ConstructScript(ccg));
     this->WritePlatformConfigTag("Message",i->c_str(), 3);
     (*this->BuildFileStream ) << cmVS10EscapeXML(comment) << "</Message>\n";
     this->WritePlatformConfigTag("Command", i->c_str(), 3);
@@ -637,8 +639,8 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
 
     (*this->BuildFileStream ) << source->GetFullPath();
     for(std::vector<std::string>::const_iterator d =
-          command.GetDepends().begin();
-        d != command.GetDepends().end();
+          ccg.GetDepends().begin();
+        d != ccg.GetDepends().end();
         ++d)
       {
       std::string dep;
@@ -652,8 +654,8 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
     this->WritePlatformConfigTag("Outputs", i->c_str(), 3);
     const char* sep = "";
     for(std::vector<std::string>::const_iterator o =
-          command.GetOutputs().begin();
-        o != command.GetOutputs().end();
+          ccg.GetOutputs().begin();
+        o != ccg.GetOutputs().end();
         ++o)
       {
       std::string out = *o;
@@ -1835,13 +1837,12 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
   for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
       i != commands.end(); ++i)
     {
-    const cmCustomCommand& command = *i;
+    cmCustomCommandGenerator ccg(*i, configName, this->Makefile);
     comment += pre;
-    comment += lg->ConstructComment(command);
+    comment += lg->ConstructComment(ccg);
     script += pre;
     pre = "\n";
-    script +=
-      cmVS10EscapeXML(lg->ConstructScript(command, configName.c_str()));
+    script += cmVS10EscapeXML(lg->ConstructScript(ccg));
     }
   comment = cmVS10EscapeComment(comment);
   this->WriteString("<Message>",3);