Ver código fonte

VS10: Fix working directory of consecutive custom commands (#11938)

The VS 10 msbuild tool uses a single command shell to invoke all the
custom command scripts in a project.  Isolate the environment and
working directory of custom commands using setlocal/endlocal.  The
form of each command is

  set errlev=
  setlocal
  cd c:\work\dir
  if %errorlevel% neq 0 goto :cmEnd
  c:
  if %errorlevel% neq 0 goto :cmEnd
  command1 ...
  if %errorlevel% neq 0 goto :cmEnd
  ...
  commandN ...
  if %errorlevel% neq 0 goto :cmEnd
  :cmEnd
  endlocal & set errlev=%errorlevel%
  if %errlev% neq 0 goto :VCEnd

so that all changes to the environment and working directory are
isolated within the script and the return code is preserved.
Brad King 14 anos atrás
pai
commit
06fcbc4757

+ 2 - 2
Source/cmLocalVisualStudio10Generator.cxx

@@ -119,7 +119,7 @@ void cmLocalVisualStudio10Generator
 }
 
 //----------------------------------------------------------------------------
-std::string cmLocalVisualStudio10Generator::CheckForErrorLine()
+const char* cmLocalVisualStudio10Generator::ReportErrorLabel() const
 {
-  return "if errorlevel 1 goto :VCEnd";
+  return ":VCEnd";
 }

+ 1 - 1
Source/cmLocalVisualStudio10Generator.h

@@ -38,7 +38,7 @@ public:
                                         const char* path);
 
 protected:
-  virtual std::string CheckForErrorLine();
+  virtual const char* ReportErrorLabel() const;
 
 private:
 };

+ 28 - 14
Source/cmLocalVisualStudioGenerator.cxx

@@ -154,15 +154,15 @@ void cmLocalVisualStudioGenerator::ComputeObjectNameRequirements
 }
 
 //----------------------------------------------------------------------------
-std::string cmLocalVisualStudioGenerator::CheckForErrorLine()
+const char* cmLocalVisualStudioGenerator::ReportErrorLabel() const
 {
-  return "if errorlevel 1 goto :VCReportError";
+  return ":VCReportError";
 }
 
 //----------------------------------------------------------------------------
-std::string cmLocalVisualStudioGenerator::GetCheckForErrorLine()
+const char* cmLocalVisualStudioGenerator::GetReportErrorLabel() const
 {
-  return this->CheckForErrorLine();
+  return this->ReportErrorLabel();
 }
 
 //----------------------------------------------------------------------------
@@ -170,35 +170,43 @@ std::string
 cmLocalVisualStudioGenerator
 ::ConstructScript(cmCustomCommand const& cc,
                   const char* configName,
-                  const char* newline_text)
+                  const char* newline)
 {
   const cmCustomCommandLines& commandLines = cc.GetCommandLines();
   const char* workingDirectory = cc.GetWorkingDirectory();
   cmCustomCommandGenerator ccg(cc, configName, this->Makefile);
   RelativeRoot relativeRoot = workingDirectory? NONE : START_OUTPUT;
 
-  // Avoid leading or trailing newlines.
-  const char* newline = "";
+  // Line to check for error between commands.
+  std::string check_error = newline;
+  check_error += "if %errorlevel% neq 0 goto :cmEnd";
 
   // Store the script in a string.
   std::string script;
+
+  // Open a local context.
+  script += "set errlev=";
+  script += newline;
+  script += "setlocal";
+
   if(workingDirectory)
     {
     // Change the working directory.
     script += newline;
-    newline = newline_text;
     script += "cd ";
     script += this->Convert(workingDirectory, FULL, SHELL);
+    script += check_error;
 
     // Change the working drive.
     if(workingDirectory[0] && workingDirectory[1] == ':')
       {
       script += newline;
-      newline = newline_text;
       script += workingDirectory[0];
       script += workingDirectory[1];
+      script += check_error;
       }
     }
+
   // for visual studio IDE add extra stuff to the PATH
   // if CMAKE_MSVCIDE_RUN_PATH is set.
   if(this->Makefile->GetDefinition("MSVC_IDE"))
@@ -208,18 +216,17 @@ cmLocalVisualStudioGenerator
     if(extraPath)
       {
       script += newline;
-      newline = newline_text;
       script += "set PATH=";
       script += extraPath;
       script += ";%PATH%";
       }
     }
+
   // Write each command on a single line.
   for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
     {
     // Start a new line.
     script += newline;
-    newline = newline_text;
 
     // Add this command line.
     std::string cmd = ccg.GetCommand(c);
@@ -230,10 +237,17 @@ cmLocalVisualStudioGenerator
     // If there was an error, jump to the VCReportError label,
     // skipping the run of any subsequent commands in this
     // sequence.
-    //
-    script += newline_text;
-    script += this->GetCheckForErrorLine();
+    script += check_error;
     }
 
+  // Close the local context.
+  script += newline;
+  script += ":cmEnd";
+  script += newline;
+  script += "endlocal & set errlev=%errorlevel%";
+  script += newline;
+  script += "if %errlev% neq 0 goto ";
+  script += this->GetReportErrorLabel();
+
   return script;
 }

+ 4 - 5
Source/cmLocalVisualStudioGenerator.h

@@ -37,13 +37,12 @@ public:
                               const char* configName,
                               const char* newline = "\n");
 
-  /** Line of batch file text that skips to the end after
-    * a failed step in a sequence of custom commands.
-    */
-  std::string GetCheckForErrorLine();
+  /** Label to which to jump in a batch file after a failed step in a
+      sequence of custom commands. */
+  const char* GetReportErrorLabel() const;
 
 protected:
-  virtual std::string CheckForErrorLine();
+  virtual const char* ReportErrorLabel() const;
 
   /** Construct a custom command to make exe import lib dir.  */
   cmsys::auto_ptr<cmCustomCommand>