Browse Source

ENH: now target names can be used in add_custom_command() and
add_custom_target() as COMMAND, and cmake will recognize them and replace
them with the actual output path of these executables. Also the dependency
will be added automatically. Test included.
ENH: moved TraceVSDependencies() to the end of GlobalGenerator::Configure(),
so it is done now in one central place

Alex

Alexander Neundorf 18 years ago
parent
commit
7f11536704

+ 2 - 2
Source/cmCustomCommand.h

@@ -69,8 +69,8 @@ public:
   void SetEscapeAllowMakeVars(bool b);
 
   /** set get the used status of the command */ 
-  void SetUsed() { this->Used = true;}; 
-  bool IsUsed() { return this->Used;};
+  void SetUsed() { this->Used = true;}
+  bool IsUsed() const { return this->Used;}
  
 private:
   std::vector<std::string> Outputs;

+ 14 - 4
Source/cmGlobalGenerator.cxx

@@ -718,6 +718,13 @@ void cmGlobalGenerator::Configure()
   // at this point this->LocalGenerators has been filled,
   // so create the map from project name to vector of local generators
   this->FillProjectMap();
+  // now create project to target map 
+  // This will make sure that targets have all the 
+  // targets they depend on as part of the build.
+  this->FillProjectToTargetMap();
+  // now trace all dependencies
+  this->TraceDependencies();
+  
   if ( !this->CMakeInstance->GetScriptMode() )
     {
     this->CMakeInstance->UpdateProgress("Configuring done", -1);
@@ -1036,6 +1043,13 @@ const char* cmGlobalGenerator::GetLinkerPreference(const char* lang)
   return "None";
 }
 
+void cmGlobalGenerator::TraceDependencies()
+{ 
+  for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
+    {
+    this->LocalGenerators[i]->TraceDependencies();
+    }
+}
 
 void cmGlobalGenerator::FillProjectMap()
 { 
@@ -1057,10 +1071,6 @@ void cmGlobalGenerator::FillProjectMap()
       }
     while (lg);
     }
-  // now create project to target map 
-  // This will make sure that targets have all the 
-  // targets they depend on as part of the build.
-  this->FillProjectToTargetMap();
 }
 
 

+ 2 - 0
Source/cmGlobalGenerator.h

@@ -202,6 +202,8 @@ protected:
   void FillProjectMap();
   bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen);
   void FillProjectToTargetMap();
+  // Calls TraceVSDependencies() on all targets
+  void TraceDependencies();
   void CreateDefaultGlobalTargets(cmTargets* targets);
   cmTarget CreateGlobalTarget(const char* name, const char* message,
     const cmCustomCommandLines* commandLines,

+ 1 - 1
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -1056,7 +1056,7 @@ cmGlobalUnixMakefileGenerator3
 {
   cmTarget *result;
   cmLocalUnixMakefileGenerator3 *lg3;
- 
+
   // first check the same dir as the current target
   lg3 = static_cast<cmLocalUnixMakefileGenerator3 *>
     (target.GetMakefile()->GetLocalGenerator());

+ 2 - 3
Source/cmGlobalVisualStudio6Generator.cxx

@@ -208,9 +208,8 @@ void cmGlobalVisualStudio6Generator
       static_cast<cmLocalVisualStudio6Generator *>(generators[i])
       ->GetCreatedProjectNames();
     cmTargets &tgts = generators[i]->GetMakefile()->GetTargets();
-    cmTargets::iterator l = tgts.begin();
-    for(std::vector<std::string>::iterator si = dspnames.begin(); 
-        l != tgts.end(); ++l)
+    std::vector<std::string>::iterator si = dspnames.begin(); 
+    for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
       {
       // special handling for the current makefile
       if(mf == generators[0]->GetMakefile())

+ 1 - 2
Source/cmGlobalVisualStudio7Generator.cxx

@@ -294,8 +294,7 @@ void cmGlobalVisualStudio7Generator
     // than one dsp could have been created per input CMakeLists.txt file
     // for each target
     cmTargets &tgts = generators[i]->GetMakefile()->GetTargets();
-    cmTargets::iterator l = tgts.begin();
-    for(; l != tgts.end(); ++l)
+    for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
       {
       // special handling for the current makefile
       if(mf == generators[0]->GetMakefile())

+ 101 - 66
Source/cmGlobalXCodeGenerator.cxx

@@ -577,16 +577,17 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
       {
       continue;
       }
+
+    if(cmtarget.GetType() == cmTarget::UTILITY ||
+       cmtarget.GetType() == cmTarget::GLOBAL_TARGET)
+      {
+      targets.push_back(this->CreateUtilityTarget(cmtarget));
+      }
     if(cmtarget.GetType() == cmTarget::UTILITY ||
        cmtarget.GetType() == cmTarget::GLOBAL_TARGET ||
        cmtarget.GetType() == cmTarget::INSTALL_FILES ||
        cmtarget.GetType() == cmTarget::INSTALL_PROGRAMS)
       {
-      if(cmtarget.GetType() == cmTarget::UTILITY ||
-         cmtarget.GetType() == cmTarget::GLOBAL_TARGET)
-        {
-        targets.push_back(this->CreateUtilityTarget(cmtarget));
-        }
       continue;
       }
 
@@ -849,6 +850,7 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
     }
   return retFlag;
 }
+
 //----------------------------------------------------------------------------
 void 
 cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
@@ -872,8 +874,31 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
     return;
     }
 
+  // collect multiple outputs of custom commands into a set
+  // which will be used for every configuration
   std::map<cmStdString, cmStdString> multipleOutputPairs;
-  
+  for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
+      i != commands.end(); ++i)
+    {
+    cmCustomCommand const& cc = *i; 
+    if(!cc.GetCommandLines().empty())
+      {
+      const std::vector<std::string>& outputs = cc.GetOutputs();
+      if(!outputs.empty())
+        {
+        // If there are more than one outputs treat the
+        // first as the primary output and make the rest depend on it.
+        std::vector<std::string>::const_iterator o = outputs.begin();
+        std::string primaryOutput = this->ConvertToRelativeForMake(o->c_str());
+        for(++o; o != outputs.end(); ++o)
+          {
+          std::string currentOutput =this->ConvertToRelativeForMake(o->c_str());
+          multipleOutputPairs[currentOutput] = primaryOutput;
+          }
+        }
+      }
+    }
+    
   std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory();
   dir += "/CMakeScripts";
   cmSystemTools::MakeDirectory(dir.c_str());
@@ -883,7 +908,48 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
   makefile += "_";
   makefile += name;
   makefile += ".make";
-  cmGeneratedFileStream makefileStream(makefile.c_str());
+  
+  for (std::vector<std::string>::const_iterator currentConfig= 
+            this->CurrentConfigurationTypes.begin();
+       currentConfig!=this->CurrentConfigurationTypes.end();
+       currentConfig++ )
+    {
+    this->CreateCustomRulesMakefile(makefile.c_str(), 
+                                    target, 
+                                    commands, 
+                                    currentConfig->c_str(),
+                                    multipleOutputPairs);
+    }
+  
+  std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory();
+  cdir = this->ConvertToRelativeForXCode(cdir.c_str());
+  std::string makecmd = "make -C ";
+  makecmd += cdir;
+  makecmd += " -f ";
+  makecmd += this->ConvertToRelativeForMake((makefile+"$CONFIGURATION").c_str());
+  if(!multipleOutputPairs.empty())
+    {
+    makecmd += " cmake_check_multiple_outputs";
+    }
+  makecmd += " all";
+  cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ ");
+  buildphase->AddAttribute("shellScript", 
+                           this->CreateString(makecmd.c_str()));
+}
+
+//----------------------------------------------------------------------------
+void  cmGlobalXCodeGenerator
+::CreateCustomRulesMakefile(const char* makefileBasename, 
+                            cmTarget& target, 
+                            std::vector<cmCustomCommand> 
+                            const & commands,
+                            const char* configName,
+                            const std::map<cmStdString, cmStdString>& multipleOutputPairs
+                           )
+{
+  std::string makefileName=makefileBasename;
+  makefileName+=configName;
+  cmGeneratedFileStream makefileStream(makefileName.c_str());
   if(!makefileStream)
     {
     return;
@@ -909,7 +975,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
             o != outputs.end(); ++o)
           {
           makefileStream
-            << "\\\n\t" << this->ConvertToRelativeForMake(o->c_str());
+              << "\\\n\t" << this->ConvertToRelativeForMake(o->c_str());
           }
         }
       else
@@ -939,21 +1005,9 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
       const std::vector<std::string>& outputs = cc.GetOutputs();
       if(!outputs.empty())
         {
-        // There is at least one output.  If there is more than one treat the
-        // first as the primary output and make the rest depend on it.
-        std::vector<std::string>::const_iterator o = outputs.begin();
+        // There is at least one output, start the rule for it
         std::string primary_output =
-          this->ConvertToRelativeForMake(o->c_str());
-        for(++o; o != outputs.end(); ++o)
-          {
-          std::string current_output =
-            this->ConvertToRelativeForMake(o->c_str());
-          makefileStream << current_output << ": "
-                         << primary_output << "\n";
-          multipleOutputPairs[current_output] = primary_output;
-          }
-
-        // Start the rule for the primary output.
+            this->ConvertToRelativeForMake(outputs.begin()->c_str());
         makefileStream << primary_output << ": ";
         }
       else
@@ -962,11 +1016,11 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
         makefileStream << tname[&cc] << ": ";
         }
       for(std::vector<std::string>::const_iterator d = 
-            cc.GetDepends().begin();
+          cc.GetDepends().begin();
           d != cc.GetDepends().end(); ++d)
         {
         if(!this->FindTarget(this->CurrentProject.c_str(),
-                             d->c_str()))
+            d->c_str()))
           {
           // if the depend is not a target but
           // is a full path then use it, if not then
@@ -974,7 +1028,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
           if(cmSystemTools::FileIsFullPath(d->c_str()))
             {
             makefileStream << "\\\n" << this
-              ->ConvertToRelativeForMake(d->c_str());
+                ->ConvertToRelativeForMake(d->c_str());
             }
           }
         else
@@ -989,12 +1043,14 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
 
       // Add each command line to the set of commands.
       for(cmCustomCommandLines::const_iterator cl = 
-            cc.GetCommandLines().begin();
+          cc.GetCommandLines().begin();
           cl != cc.GetCommandLines().end(); ++cl)
         {
         // Build the command line in a single string.
         const cmCustomCommandLine& commandLine = *cl;
-        std::string cmd2 = commandLine[0];
+        std::string cmd2 = this->CurrentLocalGenerator
+                         ->GetRealLocation(commandLine[0].c_str(), configName);
+        
         cmSystemTools::ReplaceString(cmd2, "/./", "/");
         cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
         std::string cmd;
@@ -1011,13 +1067,13 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
           if(escapeOldStyle)
             {
             cmd += (this->CurrentLocalGenerator
-                    ->EscapeForShellOldStyle(commandLine[j].c_str()));
+                ->EscapeForShellOldStyle(commandLine[j].c_str()));
             }
           else
             {
             cmd += (this->CurrentLocalGenerator->
-                    EscapeForShell(commandLine[j].c_str(),
-                                   escapeAllowMakeVars));
+                EscapeForShell(commandLine[j].c_str(),
+                               escapeAllowMakeVars));
             }
           }
         makefileStream << "\t" << cmd.c_str() << "\n";
@@ -1025,38 +1081,31 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
       }
     }
 
-  // Add a rule to deal with multiple outputs of custom commands.
+  // Add rules to deal with multiple outputs of custom commands.
   if(!multipleOutputPairs.empty())
     {
+    makefileStream << 
+        "\n# Dependencies of multiple outputs to their primary outputs \n";
+
+    for(std::map<cmStdString, cmStdString>::const_iterator o =
+        multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o)
+      {
+      makefileStream << o->first << ": " << o->second << "\n";
+      }
+
     makefileStream <<
-      "\n"
-      "cmake_check_multiple_outputs:\n";
+        "\n"
+        "cmake_check_multiple_outputs:\n";
     for(std::map<cmStdString, cmStdString>::const_iterator o =
-          multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o)
+        multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o)
       {
       makefileStream << "\t@if [ ! -f "
-                     << o->first << " ]; then rm -f "
-                     << o->second << "; fi\n";
+          << o->first << " ]; then rm -f "
+          << o->second << "; fi\n";
       }
     }
-
-  std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory();
-  cdir = this->ConvertToRelativeForXCode(cdir.c_str());
-  std::string makecmd = "make -C ";
-  makecmd += cdir;
-  makecmd += " -f ";
-  makecmd += this->ConvertToRelativeForMake(makefile.c_str());
-  if(!multipleOutputPairs.empty())
-    {
-    makecmd += " cmake_check_multiple_outputs";
-    }
-  makecmd += " all";
-  cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ ");
-  buildphase->AddAttribute("shellScript", 
-                           this->CreateString(makecmd.c_str()));
 }
 
-
 //----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
                                                  cmXCodeObject* buildSettings,
@@ -2406,20 +2455,6 @@ cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator* root,
     cmMakefile* mf = (*g)->GetMakefile();
     std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups();
     cmTargets &tgts = mf->GetTargets();
-  // Call TraceVSDependencies on all targets
-  for(cmTargets::iterator l = tgts.begin(); 
-      l != tgts.end(); l++)
-    {
-    // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
-    // so don't build a projectfile for it
-    if ((l->second.GetType() != cmTarget::INSTALL_FILES)
-        && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
-        && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
-      {
-      cmTarget& target = l->second;
-      target.TraceVSDependencies(target.GetName(), mf);
-      }
-    }
   // now for all custom commands that are not used directly in a 
   // target, add them to all targets in the current directory or
   // makefile

+ 9 - 0
Source/cmGlobalXCodeGenerator.h

@@ -106,6 +106,15 @@ private:
                                std::vector<cmCustomCommand> 
                                const & commands,
                                const char* commandFileName);
+  
+  void CreateCustomRulesMakefile(const char* makefileBasename, 
+                                 cmTarget& target,
+                                 std::vector<cmCustomCommand> const & commands, 
+                                 const char* configName,
+                                 const std::map<cmStdString, cmStdString>& 
+                                     multipleOutputPairs
+                                );
+  
   cmXCodeObject* FindXCodeTarget(cmTarget*);
   // create cmXCodeObject from these functions so that memory can be managed
   // correctly.  All objects created are stored in this->XCodeObjects.

+ 39 - 0
Source/cmLocalGenerator.cxx

@@ -52,6 +52,7 @@ cmLocalGenerator::cmLocalGenerator()
   this->UseRelativePaths = false;
   this->Configured = false;
   this->EmitUniversalBinaryFlags = true;
+  this->IsMakefileGenerator = false;
   this->RelativePathsConfigured = false;
   this->PathConversionsSetup = false;
 }
@@ -135,6 +136,30 @@ void cmLocalGenerator::ConfigureFinalPass()
   this->Makefile->ConfigureFinalPass();
 }
 
+void cmLocalGenerator::TraceDependencies()
+{
+  // Generate the rule files for each target.
+  cmTargets& targets = this->Makefile->GetTargets();
+  for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
+    {
+    // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
+    // so don't build a projectfile for it
+    if ((t->second.GetType() != cmTarget::INSTALL_FILES)
+        && (t->second.GetType() != cmTarget::INSTALL_PROGRAMS)
+        && (t->second.GetType() != cmTarget::INSTALL_DIRECTORY)
+        && (strncmp(t->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)
+        && (t->second.GetPropertyAsBool("IMPORTED") == false))
+      {
+      std::string projectFilename;
+      if (this->IsMakefileGenerator == false)  // only use of this variable
+        {
+        projectFilename=t->second.GetName();
+        }
+      t->second.TraceVSDependencies(projectFilename, this->Makefile);
+      }
+    }
+}
+
 void cmLocalGenerator::GenerateTestFiles()
 {
   if ( !this->Makefile->IsOn("CMAKE_TESTING_ENABLED") )
@@ -1986,6 +2011,20 @@ std::string cmLocalGenerator::GetRealDependency(const char* inName,
   return name;
 }
 
+//----------------------------------------------------------------------------
+std::string cmLocalGenerator::GetRealLocation(const char* inName,
+                                              const char* config)
+{
+  std::string outName=inName;
+  // Look for a CMake target with the given name.
+  cmTarget* target = this->GlobalGenerator->FindTarget(0, inName);
+  if ((target!=0) && (target->GetType()==cmTarget::EXECUTABLE))
+    {
+    outName = target->GetLocation( config );
+    }
+  return outName;
+}
+
 //----------------------------------------------------------------------------
 void cmLocalGenerator::AddSharedFlags(std::string& flags,
                                       const char* lang,

+ 13 - 1
Source/cmLocalGenerator.h

@@ -42,7 +42,7 @@ public:
   /**
    * Generate the makefile for this directory. 
    */
-  virtual void Generate() {};
+  virtual void Generate() {}
 
   /**
    * Process the CMakeLists files for this directory to fill in the
@@ -50,6 +50,11 @@ public:
    */
   virtual void Configure();
 
+  /** 
+   * Calls TraceVSDependencies() on all targets of this generator.
+   */
+  virtual void TraceDependencies();
+  
   /**
    * Perform any final calculations prior to generation
    */
@@ -137,6 +142,11 @@ public:
       the source directory of this generator.  This should only be
       used for dependencies of custom commands.  */
   std::string GetRealDependency(const char* name, const char* config);
+  
+  /** Translate a command as given in CMake code to the location of the 
+      executable if the command is the name of a CMake executable target.
+      If that's not the case, just return the original name. */
+  std::string GetRealLocation(const char* inName, const char* config);
 
   ///! for existing files convert to output path and short path if spaces
   std::string ConvertToOutputForExisting(const char* p);
@@ -298,6 +308,8 @@ protected:
   bool IgnoreLibPrefix;
   bool Configured;
   bool EmitUniversalBinaryFlags;
+  // A type flag is not nice. It's used only in TraceDependencies().
+  bool IsMakefileGenerator;
   // Hack for ExpandRuleVariable until object-oriented version is
   // committed.
   std::string TargetImplib;

+ 4 - 2
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -54,6 +54,7 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3()
   this->NativeEchoCommand = "@echo ";
   this->NativeEchoWindows = true;
   this->MakeCommandEscapeTargetTwice = false;
+  this->IsMakefileGenerator = true;
 }
 
 //----------------------------------------------------------------------------
@@ -112,7 +113,7 @@ void cmLocalUnixMakefileGenerator3::Generate()
     if (tg)
       {
       this->TargetGenerators.push_back(tg);
-      t->second.TraceVSDependencies(empty, this->Makefile);
+//      t->second.TraceVSDependencies(empty, this->Makefile);
       tg->WriteRuleFiles();
       }
     }
@@ -885,7 +886,8 @@ cmLocalUnixMakefileGenerator3
     {
     // Build the command line in a single string.
     const cmCustomCommandLine& commandLine = *cl;
-    std::string cmd = commandLine[0];
+    std::string cmd = GetRealLocation(commandLine[0].c_str(), 
+                                      this->ConfigurationName.c_str());
     if (cmd.size())
       {
       cmSystemTools::ReplaceString(cmd, "/./", "/");

+ 54 - 42
Source/cmLocalVisualStudio6Generator.cxx

@@ -116,16 +116,6 @@ void cmLocalVisualStudio6Generator::OutputDSPFile()
       {
       this->AddDSPBuildRule(l->second);
       }
-
-    // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
-    // so don't build a projectfile for it
-    if ((l->second.GetType() != cmTarget::INSTALL_FILES)
-        && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
-        && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
-      {
-      cmTarget& target = l->second;
-      target.TraceVSDependencies(target.GetName(), this->Makefile);
-      }
     }
 
   // build any targets
@@ -490,23 +480,8 @@ void cmLocalVisualStudio6Generator
         }
       if (command)
         {
-        std::string script =
-          this->ConstructScript(command->GetCommandLines(), 
-                                command->GetWorkingDirectory(),
-                                command->GetEscapeOldStyle(),
-                                command->GetEscapeAllowMakeVars(),
-                                "\\\n\t");
-        std::string comment =
-          this->ConstructComment(*command,
-                                 "Building Custom Rule $(InputPath)");
-        if(comment == "<hack>")
-          {
-          comment = "";
-          }
         const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
-        this->WriteCustomRule(fout, source.c_str(), script.c_str(),
-                              comment.c_str(), command->GetDepends(),
-                              command->GetOutputs(), flags);
+        this->WriteCustomRule(fout, source.c_str(), *command, flags);
         }
       else if(!compileFlags.empty() || !objectNameDir.empty())
         {
@@ -603,16 +578,29 @@ void
 cmLocalVisualStudio6Generator
 ::WriteCustomRule(std::ostream& fout,
                   const char* source,
-                  const char* command,
-                  const char* comment,
-                  const std::vector<std::string>& depends,
-                  const std::vector<std::string>& outputs,
+                  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 script =
+      this->ConstructScript(command.GetCommandLines(), 
+                            command.GetWorkingDirectory(),
+                            i->c_str(),
+                            command.GetEscapeOldStyle(),
+                            command.GetEscapeAllowMakeVars(),
+                            "\\\n\t");
+      
     if (i == this->Configurations.begin())
       {
       fout << "!IF  \"$(CFG)\" == " << i->c_str() << std::endl;
@@ -627,8 +615,9 @@ cmLocalVisualStudio6Generator
       }
     // Write out the dependencies for the rule.
     fout << "USERDEP__HACK=";
-    for(std::vector<std::string>::const_iterator d = depends.begin();
-        d != depends.end(); ++d)
+    for(std::vector<std::string>::const_iterator d=command.GetDepends().begin();
+        d != command.GetDepends().end(); 
+        ++d)
       {
       // Lookup the real name of the dependency in case it is a CMake target.
       std::string dep = this->GetRealDependency(d->c_str(), i->c_str());
@@ -639,26 +628,28 @@ cmLocalVisualStudio6Generator
 
     fout << "# PROP Ignore_Default_Tool 1\n";
     fout << "# Begin Custom Build -";
-    if(comment && *comment)
+    if(!comment.empty())
       {
-      fout << " " << comment;
+      fout << " " << comment.c_str();
       }
     fout << "\n\n";
-    if(outputs.empty())
+    if(command.GetOutputs().empty())
       {
       fout << source 
            << "_force :  \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
-      fout << command << "\n\n";
+      fout << script.c_str() << "\n\n";
       }
     else
       {
-      for(std::vector<std::string>::const_iterator o = outputs.begin();
-          o != outputs.end(); ++o)
+      for(std::vector<std::string>::const_iterator o = 
+          command.GetOutputs().begin();
+          o != command.GetOutputs().end(); 
+          ++o)
         {
         // Write a rule for every output generated by this command.
         fout << this->ConvertToOptionallyRelativeOutputPath(o->c_str())
              << " :  \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
-        fout << command << "\n\n";
+        fout << script.c_str() << "\n\n";
         }
       }
     fout << "# End Custom Build\n\n";
@@ -768,6 +759,7 @@ void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
 // look for custom rules on a target and collect them together
 std::string 
 cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target, 
+                                                 const char* configName, 
                                                  const char * /* libName */)
 {
   std::string customRuleCode = "";
@@ -808,6 +800,7 @@ cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
       }
     customRuleCode += this->ConstructScript(cr->GetCommandLines(),
                                             cr->GetWorkingDirectory(),
+                                            configName, 
                                             cr->GetEscapeOldStyle(),
                                             cr->GetEscapeAllowMakeVars(),
                                             "\\\n\t");
@@ -822,6 +815,7 @@ cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
       }
     customRuleCode += this->ConstructScript(cr->GetCommandLines(),
                                             cr->GetWorkingDirectory(),
+                                            configName,
                                             cr->GetEscapeOldStyle(),
                                             cr->GetEscapeAllowMakeVars(),
                                             "\\\n\t");
@@ -850,6 +844,7 @@ cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
       }
     customRuleCode += this->ConstructScript(cr->GetCommandLines(),
                                             cr->GetWorkingDirectory(),
+                                            configName,
                                             cr->GetEscapeOldStyle(),
                                             cr->GetEscapeAllowMakeVars(),
                                             "\\\n\t");
@@ -1274,7 +1269,14 @@ void cmLocalVisualStudio6Generator
 
   // are there any custom rules on the target itself
   // only if the target is a lib or exe
-  std::string customRuleCode = this->CreateTargetRules(target, libName);
+  std::string customRuleCodeRelease        
+      = this->CreateTargetRules(target, "RELEASE",        libName);
+  std::string customRuleCodeDebug          
+      = this->CreateTargetRules(target, "DEBUG",          libName);
+  std::string customRuleCodeMinSizeRel     
+      = this->CreateTargetRules(target, "MINSIZEREL",     libName);
+  std::string customRuleCodeRelWithDebInfo 
+      = this->CreateTargetRules(target, "RELWITHDEBINFO", libName);
 
   std::ifstream fin(this->DSPHeaderTemplate.c_str());
   if(!fin)
@@ -1307,8 +1309,6 @@ void cmLocalVisualStudio6Generator
       }
     cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
                                  exportSymbol.c_str());
-    cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE",
-                                 customRuleCode.c_str());
     cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
                                  mfcFlag);
     if(target.GetType() == cmTarget::STATIC_LIBRARY )
@@ -1337,6 +1337,18 @@ void cmLocalVisualStudio6Generator
     cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
                                  libMultiLineOptimizedOptions.c_str());
 #endif
+    
+    // Substitute the rules for custom command. When specifying just the 
+    // target name for the command the command can be different for
+    // different configs
+    cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELEASE",
+                                 customRuleCodeRelease.c_str());
+    cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_DEBUG",
+                                 customRuleCodeDebug.c_str());
+    cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_MINSIZEREL",
+                                 customRuleCodeMinSizeRel.c_str());
+    cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO",
+                                 customRuleCodeRelWithDebInfo.c_str());
 
     // Substitute the real output name into the template.
     cmSystemTools::ReplaceString(line, "OUTPUT_NAME_DEBUG", 

+ 2 - 4
Source/cmLocalVisualStudio6Generator.h

@@ -84,10 +84,7 @@ private:
   void AddDSPBuildRule(cmTarget& tgt);
   void WriteCustomRule(std::ostream& fout,
                        const char* source,
-                       const char* command,
-                       const char* comment,
-                       const std::vector<std::string>& depends,
-                       const std::vector<std::string>& outputs,
+                       const cmCustomCommand& command,
                        const char* flags);
   void AddUtilityCommandHack(cmTarget& target, int count,
                              std::vector<std::string>& depends,
@@ -95,6 +92,7 @@ private:
   void WriteGroup(const cmSourceGroup *sg, cmTarget target,
                   std::ostream &fout, const char *libName);
   std::string CreateTargetRules(cmTarget &target, 
+                                const char* configName, 
                                 const char *libName);
   void ComputeLinkOptions(cmTarget& target, const char* configName,
                           const std::string extraOptions,

+ 27 - 33
Source/cmLocalVisualStudio7Generator.cxx

@@ -124,16 +124,6 @@ void cmLocalVisualStudio7Generator::OutputVCProjFile()
       {
       this->AddVCProjBuildRule(l->second);
       }
-
-    // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
-    // so don't build a projectfile for it
-    if ((l->second.GetType() != cmTarget::INSTALL_FILES)
-        && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
-        && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
-      {
-      cmTarget& target = l->second;
-      target.TraceVSDependencies(target.GetName(), this->Makefile);
-      }
     }
 
   for(cmTargets::iterator l = tgts.begin();
@@ -623,7 +613,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
          << "\t\t\t/>\n";
     }
 
-  this->OutputTargetRules(fout, target, libName);
+  this->OutputTargetRules(fout, configName, target, libName);
   this->OutputBuildTool(fout, configName, target);
   fout << "\t\t</Configuration>\n";
 }
@@ -1141,17 +1131,8 @@ void cmLocalVisualStudio7Generator
       fout << "\t\t\t\tRelativePath=\"" << d << "\">\n";
       if (command)
         {
-        // Construct the entire set of commands in one string.
-        std::string script = 
-          this->ConstructScript(command->GetCommandLines(),
-                                command->GetWorkingDirectory(),
-                                command->GetEscapeOldStyle(),
-                                command->GetEscapeAllowMakeVars());
-        std::string comment = this->ConstructComment(*command);
         const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
-        this->WriteCustomRule(fout, source.c_str(), script.c_str(),
-                              comment.c_str(), command->GetDepends(),
-                              command->GetOutputs(), flags);
+        this->WriteCustomRule(fout, source.c_str(), *command, flags);
         }
       else if(compileFlags.size() || additionalDeps.length() 
               || objectName.size() || excludedFromBuild)
@@ -1228,12 +1209,11 @@ void cmLocalVisualStudio7Generator
 void cmLocalVisualStudio7Generator::
 WriteCustomRule(std::ostream& fout,
                 const char* source,
-                const char* command,
-                const char* comment,
-                const std::vector<std::string>& depends,
-                const std::vector<std::string>& outputs,
+                const cmCustomCommand& command,
                 const char* compileFlags)
 {
+  std::string comment = this->ConstructComment(command);
+  
   // Write the rule for each configuration.
   std::vector<std::string>::iterator i;
   std::vector<std::string> *configs =
@@ -1251,14 +1231,21 @@ WriteCustomRule(std::ostream& fout,
            << "\t\t\t\t\tAdditionalOptions=\""
            << this->EscapeForXML(compileFlags) << "\"/>\n";
       }
+
+    std::string script = 
+      this->ConstructScript(command.GetCommandLines(),
+                            command.GetWorkingDirectory(),
+                            i->c_str(),
+                            command.GetEscapeOldStyle(),
+                            command.GetEscapeAllowMakeVars());
     fout << "\t\t\t\t\t<Tool\n"
          << "\t\t\t\t\tName=\"VCCustomBuildTool\"\n"
          << "\t\t\t\t\tDescription=\"" 
-         << this->EscapeForXML(comment) << "\"\n"
+         << this->EscapeForXML(comment.c_str()) << "\"\n"
          << "\t\t\t\t\tCommandLine=\"" 
-         << this->EscapeForXML(command) << "\"\n"
+         << this->EscapeForXML(script.c_str()) << "\"\n"
          << "\t\t\t\t\tAdditionalDependencies=\"";
-    if(depends.empty())
+    if(command.GetDepends().empty())
       {
       // There are no real dependencies.  Produce an artificial one to
       // make sure the rule runs reliably.
@@ -1272,8 +1259,10 @@ WriteCustomRule(std::ostream& fout,
     else
       {
       // Write out the dependencies for the rule.
-      for(std::vector<std::string>::const_iterator d = depends.begin();
-          d != depends.end(); ++d)
+      for(std::vector<std::string>::const_iterator d = 
+          command.GetDepends().begin();
+          d != command.GetDepends().end(); 
+          ++d)
         {
         // Get the real name of the dependency in case it is a CMake target.
         std::string dep = this->GetRealDependency(d->c_str(), i->c_str());
@@ -1283,7 +1272,7 @@ WriteCustomRule(std::ostream& fout,
       }
     fout << "\"\n";
     fout << "\t\t\t\t\tOutputs=\"";
-    if(outputs.empty())
+    if(command.GetOutputs().empty())
       {
       fout << source << "_force";
       }
@@ -1291,8 +1280,9 @@ 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 = outputs.begin();
-          o != outputs.end(); ++o)
+      for(std::vector<std::string>::const_iterator o = command.GetOutputs().begin();
+          o != command.GetOutputs().end(); 
+          ++o)
         {
         fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str());
         sep = ";";
@@ -1323,6 +1313,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjEndGroup(std::ostream& fout)
 // look for custom rules on a target and collect them together
 void cmLocalVisualStudio7Generator
 ::OutputTargetRules(std::ostream& fout,
+                    const char* configName,
                     cmTarget &target,
                     const char * /*libName*/)
 {
@@ -1350,6 +1341,7 @@ void cmLocalVisualStudio7Generator
     std::string script =
       this->ConstructScript(cr->GetCommandLines(),
                             cr->GetWorkingDirectory(),
+                            configName,
                             cr->GetEscapeOldStyle(),
                             cr->GetEscapeAllowMakeVars());
     fout << this->EscapeForXML(script.c_str()).c_str();
@@ -1379,6 +1371,7 @@ void cmLocalVisualStudio7Generator
     std::string script =
       this->ConstructScript(cr->GetCommandLines(),
                             cr->GetWorkingDirectory(),
+                            configName,
                             cr->GetEscapeOldStyle(),
                             cr->GetEscapeAllowMakeVars());
     fout << this->EscapeForXML(script.c_str()).c_str();
@@ -1408,6 +1401,7 @@ void cmLocalVisualStudio7Generator
     std::string script =
       this->ConstructScript(cr->GetCommandLines(),
                             cr->GetWorkingDirectory(),
+                            configName,
                             cr->GetEscapeOldStyle(),
                             cr->GetEscapeAllowMakeVars());
     fout << this->EscapeForXML(script.c_str()).c_str();

+ 4 - 6
Source/cmLocalVisualStudio7Generator.h

@@ -89,8 +89,8 @@ private:
   std::string EscapeForXML(const char* s);
   std::string ConvertToXMLOutputPath(const char* path);
   std::string ConvertToXMLOutputPathSingle(const char* path);
-  void OutputTargetRules(std::ostream& fout, cmTarget &target, 
-                         const char *libName);
+  void OutputTargetRules(std::ostream& fout, const char* configName, 
+                         cmTarget &target, const char *libName);
   void OutputBuildTool(std::ostream& fout, const char* configName,
                        cmTarget& t);
   void OutputLibraries(std::ostream& fout,
@@ -104,12 +104,10 @@ private:
                           const char* group,
                           const char* filter);
   void WriteVCProjEndGroup(std::ostream& fout);
+  
   void WriteCustomRule(std::ostream& fout,
                        const char* source,
-                       const char* command,
-                       const char* comment,
-                       const std::vector<std::string>& depends,
-                       const std::vector<std::string>& outputs,
+                       const cmCustomCommand& command,
                        const char* extraFlags);
   void WriteTargetVersionAttribute(std::ostream& fout, cmTarget& target);
 

+ 5 - 2
Source/cmLocalVisualStudioGenerator.cxx

@@ -111,6 +111,7 @@ std::string
 cmLocalVisualStudioGenerator
 ::ConstructScript(const cmCustomCommandLines& commandLines,
                   const char* workingDirectory,
+                  const char* configName,
                   bool escapeOldStyle,
                   bool escapeAllowMakeVars,
                   const char* newline_text)
@@ -152,13 +153,15 @@ cmLocalVisualStudioGenerator
 
     // Start with the command name.
     const cmCustomCommandLine& commandLine = *cl;
+    std::string commandName = this->GetRealLocation(commandLine[0].c_str(), 
+                                                    configName);
     if(!workingDirectory)
       {
-      script += this->Convert(commandLine[0].c_str(),START_OUTPUT,SHELL);
+      script += this->Convert(commandName.c_str(),START_OUTPUT,SHELL);
       }
     else
       {
-      script += this->Convert(commandLine[0].c_str(),NONE,SHELL);
+      script += this->Convert(commandName.c_str(),NONE,SHELL);
       }
 
     // Add the arguments.

+ 1 - 0
Source/cmLocalVisualStudioGenerator.h

@@ -41,6 +41,7 @@ protected:
   /** Construct a script from the given list of command lines.  */
   std::string ConstructScript(const cmCustomCommandLines& commandLines,
                               const char* workingDirectory,
+                              const char* configName,
                               bool escapeOldStyle,
                               bool escapeAllowMakeVars,
                               const char* newline = "\n");

+ 0 - 12
Source/cmMakefile.cxx

@@ -578,18 +578,6 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
         ti->second.GetPostBuildCommands().push_back(cc);
         break;
       }
-
-    // Add dependencies on commands CMake knows how to build.
-    for(cmCustomCommandLines::const_iterator cli = commandLines.begin();
-        cli != commandLines.end(); ++cli)
-      {
-      std::string cacheCommand = *cli->begin();
-      if(const char* knownTarget =
-         this->GetCacheManager()->GetCacheValue(cacheCommand.c_str()))
-        {
-        ti->second.AddUtility(knownTarget);
-        }
-      }
     }
 }
 

+ 52 - 2
Source/cmTarget.cxx

@@ -408,6 +408,31 @@ void cmTarget::SetMakefile(cmMakefile* mf)
     }
 }
 
+
+void 
+cmTarget::checkForTargetsAsCommand(const std::vector<cmCustomCommand>& commands)
+{
+  for ( std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
+        cli != commands.end();
+        ++cli )
+    {
+    for ( cmCustomCommandLines::const_iterator cit=cli->GetCommandLines().begin();
+          cit!=cli->GetCommandLines().end();
+          ++cit )
+      {
+      std::string command = *cit->begin();
+      // see if we can find a target with this name
+      cmTarget* t =  this->Makefile->GetLocalGenerator()->
+                     GetGlobalGenerator()->FindTarget ( 0, command.c_str() );
+      if ( ( t ) && ( t->GetType() ==cmTarget::EXECUTABLE ) )
+        {
+        this->AddUtility ( command.c_str() );
+        }
+      }
+    }
+}
+
+
 void cmTarget::TraceVSDependencies(std::string projFile, 
                                    cmMakefile *makefile)
 { 
@@ -504,6 +529,11 @@ void cmTarget::TraceVSDependencies(std::string projFile,
         }
       }
     }
+    
+  checkForTargetsAsCommand(this->GetPreBuildCommands());
+  checkForTargetsAsCommand(this->GetPreLinkCommands());
+  checkForTargetsAsCommand(this->GetPostBuildCommands());
+
   while (!srcFilesToProcess.empty())
     {
     // is this source the output of a custom command
@@ -533,9 +563,28 @@ void cmTarget::TraceVSDependencies(std::string projFile,
           srcFilesQueued.insert(temp);
           }
         }
+
+      // check if commands for this custom commands are names of targets and
+      // if that's the case add these targets as dependencies
+      std::vector<std::string> automaticTargetDepends;
+      for(cmCustomCommandLines::const_iterator it=
+          outsf->GetCustomCommand()->GetCommandLines().begin();
+          it!=outsf->GetCustomCommand()->GetCommandLines().end();
+          ++it)
+        {
+        const std::string& currentCommand = (*it)[0];
+        // see if we can find a target with this name
+        cmTarget* t =  this->Makefile->GetLocalGenerator()->
+            GetGlobalGenerator()->FindTarget(0, currentCommand.c_str());
+        if (( t) && (t->GetType()==cmTarget::EXECUTABLE))
+          {
+          automaticTargetDepends.push_back(currentCommand);
+          }
+        }
+        outsf->GetCustomCommand()->AppendDepends(automaticTargetDepends);
+
       // add its dependencies to the list to check
-      unsigned int i;
-      for (i = 0; i < outsf->GetCustomCommand()->GetDepends().size(); ++i)
+      for (unsigned int i = 0; i < outsf->GetCustomCommand()->GetDepends().size(); ++i)
         {
         const std::string& fullName 
           = outsf->GetCustomCommand()->GetDepends()[i];
@@ -590,6 +639,7 @@ void cmTarget::TraceVSDependencies(std::string projFile,
             }
           }
         }
+
       }
     // finished with this SF move to the next
     srcFilesToProcess.pop();

+ 9 - 2
Source/cmTarget.h

@@ -55,7 +55,7 @@ public:
   void SetType(TargetType f, const char* name);
 
   ///! Set/Get the name of the target
-  const char* GetName() {return this->Name.c_str();}
+  const char* GetName() const {return this->Name.c_str();}
 
   ///! Set the cmMakefile that owns this target
   void SetMakefile(cmMakefile *mf);
@@ -180,7 +180,7 @@ public:
 
   /**
    * Trace through the source files in this target and add al source files
-   * that they depend on, used by the visual studio generators
+   * that they depend on, used by all generators
    */
   void TraceVSDependencies(std::string projName, cmMakefile *mf);  
 
@@ -291,6 +291,13 @@ private:
                          const LibraryID& lib,
                          const LibraryID& dep);
 
+  /*
+   * Checks the prebuild, prelink and postbuild custom commands for known
+   * targets and adds them to the dependencies.
+   */
+  void checkForTargetsAsCommand(const std::vector<cmCustomCommand>& commands);
+  
+  
   /**
    * Emits the library \a lib and all its dependencies into link_line.
    * \a emitted keeps track of the libraries that have been emitted to

+ 4 - 4
Templates/DLLHeader.dsptemplate

@@ -74,7 +74,7 @@ LINK32=link.exe
 # ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /machine:I386 /out:"OUTPUT_DIRECTORY\Release/OUTPUT_NAME_RELEASE" TARGET_IMPLIB_FLAG_RELEASE
 CM_MULTILINE_OPTIONS_RELEASE
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELEASE
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
 
@@ -106,7 +106,7 @@ LINK32=link.exe
 # ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /debug /machine:I386 /out:"OUTPUT_DIRECTORY\Debug/OUTPUT_NAME_DEBUG" /pdbtype:sept TARGET_IMPLIB_FLAG_DEBUG
 CM_MULTILINE_OPTIONS_DEBUG
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_DEBUG
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
 
@@ -140,7 +140,7 @@ LINK32=link.exe
 # ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /machine:I386 /out:"OUTPUT_DIRECTORY\MinSizeRel/OUTPUT_NAME_MINSIZEREL" TARGET_IMPLIB_FLAG_MINSIZEREL
 CM_MULTILINE_OPTIONS_MINSIZEREL
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
 
@@ -172,7 +172,7 @@ LINK32=link.exe
 # ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /debug /machine:I386 /pdbtype:sept /out:"OUTPUT_DIRECTORY\RelWithDebInfo/OUTPUT_NAME_RELWITHDEBINFO" TARGET_IMPLIB_FLAG_RELWITHDEBINFO
 CM_MULTILINE_OPTIONS_RELWITHDEBINFO
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
 
 !ENDIF 
 

+ 4 - 4
Templates/EXEHeader.dsptemplate

@@ -72,7 +72,7 @@ LINK32=link.exe
 # ADD LINK32 /out:"OUTPUT_DIRECTORY\Release\OUTPUT_NAME_RELEASE" TARGET_IMPLIB_FLAG_RELEASE
 CM_MULTILINE_OPTIONS_RELEASE
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELEASE
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
 
@@ -104,7 +104,7 @@ LINK32=link.exe
 # ADD LINK32 /out:"OUTPUT_DIRECTORY\Debug\OUTPUT_NAME_DEBUG" TARGET_IMPLIB_FLAG_DEBUG
 CM_MULTILINE_OPTIONS_DEBUG
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_DEBUG
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
 # PROP BASE Use_MFC CMAKE_MFC_FLAG
@@ -133,7 +133,7 @@ LINK32=link.exe
 # ADD LINK32 /out:"OUTPUT_DIRECTORY\MinSizeRel\OUTPUT_NAME_MINSIZEREL" TARGET_IMPLIB_FLAG_MINSIZEREL
 CM_MULTILINE_OPTIONS_MINSIZEREL
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
 
@@ -163,7 +163,7 @@ LINK32=link.exe
 # ADD LINK32 /out:"OUTPUT_DIRECTORY\RelWithDebInfo\OUTPUT_NAME_RELWITHDEBINFO" TARGET_IMPLIB_FLAG_RELWITHDEBINFO
 CM_MULTILINE_OPTIONS_RELWITHDEBINFO
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
 
 !ENDIF 
 

+ 4 - 4
Templates/EXEWinHeader.dsptemplate

@@ -74,7 +74,7 @@ LINK32=link.exe
 # ADD LINK32 /out:"OUTPUT_DIRECTORY\Release\OUTPUT_NAME_RELEASE"
 CM_MULTILINE_OPTIONS_RELEASE
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELEASE
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
 
@@ -106,7 +106,7 @@ LINK32=link.exe
 # ADD LINK32 /out:"OUTPUT_DIRECTORY\Debug\OUTPUT_NAME_DEBUG"
 CM_MULTILINE_OPTIONS_DEBUG
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_DEBUG
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
 # PROP BASE Use_MFC CMAKE_MFC_FLAG
@@ -135,7 +135,7 @@ LINK32=link.exe
 # ADD LINK32 /out:"OUTPUT_DIRECTORY\MinSizeRel\OUTPUT_NAME_MINSIZEREL"
 CM_MULTILINE_OPTIONS_MINSIZEREL
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
 
@@ -167,7 +167,7 @@ LINK32=link.exe
 # ADD LINK32 /out:"OUTPUT_DIRECTORY\RelWithDebInfo\OUTPUT_NAME_RELWITHDEBINFO"
 CM_MULTILINE_OPTIONS_RELWITHDEBINFO
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
 
 !ENDIF 
 

+ 4 - 4
Templates/UtilityHeader.dsptemplate

@@ -42,7 +42,7 @@ MTL=midl.exe
 # PROP Intermediate_Dir "Release"
 # PROP Target_Dir ""
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELEASE
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
 
@@ -57,7 +57,7 @@ CMAKE_CUSTOM_RULE_CODE
 # PROP Intermediate_Dir "Debug"
 # PROP Target_Dir ""
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_DEBUG
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
 
@@ -72,7 +72,7 @@ CMAKE_CUSTOM_RULE_CODE
 # PROP Intermediate_Dir "MinSizeRel"
 # PROP Target_Dir ""
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
 
@@ -87,7 +87,7 @@ CMAKE_CUSTOM_RULE_CODE
 # PROP Intermediate_Dir "RelWithDebInfo"
 # PROP Target_Dir ""
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
 
 !ENDIF 
 

+ 4 - 4
Templates/staticLibHeader.dsptemplate

@@ -67,7 +67,7 @@ LIB32=link.exe -lib
 # ADD BASE LIB32 /nologo
 # ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\Release/OUTPUT_NAME_RELEASE" CM_STATIC_LIB_ARGS
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELEASE
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
 
@@ -95,7 +95,7 @@ LIB32=link.exe -lib
 # ADD BASE LIB32 /nologo
 # ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\Debug/OUTPUT_NAME_DEBUG" CM_STATIC_LIB_ARGS
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_DEBUG
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
 
@@ -124,7 +124,7 @@ LIB32=link.exe -lib
 # ADD BASE LIB32 /nologo
 # ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\MinSizeRel/OUTPUT_NAME_MINSIZEREL" CM_STATIC_LIB_ARGS
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
 
 !ELSEIF  "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
 
@@ -152,7 +152,7 @@ LIB32=link.exe -lib
 # ADD BASE LIB32 /nologo
 # ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\RelWithDebInfo/OUTPUT_NAME_RELWITHDEBINFO" CM_STATIC_LIB_ARGS
 
-CMAKE_CUSTOM_RULE_CODE
+CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
 
 !ENDIF 
 

+ 25 - 0
Tests/CustomCommand/CMakeLists.txt

@@ -167,6 +167,31 @@ TARGET_LINK_LIBRARIES(CustomCommand GeneratedHeader)
 # the CustomCommand executable really needs doc1.h
 ADD_DEPENDENCIES(CustomCommand TDocument)
 
+##############################################################################
+# Test for using just the target name as executable in the COMMAND
+# section. Has to be recognized and replaced by CMake with the output
+# actual location of the executable.
+# Additionally the generator is created in an extra subdir after the 
+# ADD_CUSTOM_COMMAND() is used.
+#
+# Test the same for ADD_CUSTOM_TARGET()
+
+ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated_extern.cxx
+  COMMAND generator_extern ${CMAKE_CURRENT_BINARY_DIR}/generated_extern.cxx
+  )
+
+ADD_EXECUTABLE(CustomCommandUsingTargetTest main.cxx ${CMAKE_CURRENT_BINARY_DIR}/generated_extern.cxx )
+
+ADD_CUSTOM_TARGET(RunTarget 
+  COMMAND generator_extern ${CMAKE_CURRENT_BINARY_DIR}/run_target.cxx
+  )
+
+ADD_CUSTOM_COMMAND(TARGET CustomCommandUsingTargetTest POST_BUILD 
+                   COMMAND dummy_generator ${CMAKE_CURRENT_BINARY_DIR}/generated_dummy.cxx)
+
+ADD_SUBDIRECTORY(GeneratorInExtraDir)
+
+
 ##############################################################################
 # Test non-trivial command line arguments in custom commands.
 SET(EXPECTED_ARGUMENTS)

+ 6 - 0
Tests/CustomCommand/GeneratorInExtraDir/CMakeLists.txt

@@ -0,0 +1,6 @@
+# add the executable which will be used for generating files
+ADD_EXECUTABLE(generator_extern ../generator.cxx)
+SET_TARGET_PROPERTIES(generator_extern PROPERTIES OUTPUT_NAME the_external_generator)
+
+# add an executable which will be called from ADD_CUSTOM_COMMAND( ... POST_BUILD)
+ADD_EXECUTABLE(dummy_generator ../generator.cxx)

+ 6 - 0
Tests/CustomCommand/main.cxx

@@ -0,0 +1,6 @@
+extern int generated();
+
+int main()
+{
+  return generated();
+}