Просмотр исходного кода

Add support to indicate UTF-8 custom command pipe output encoding

Adds a flag to indicate that pipe output from a custom command should be
interpreted as UTF-8 encoded. This change does not introduce a public
way to set the flag, but generators that create internally-generated
commands know if they are calling cmake, which uses UTF-8 pipes.

MSBuild added support for interpreting output of PreBuildEvent,
PreLinkEvent, PostBuildEvent, and CustomBuildStep as UTF-8. This change
will appear in Visual Studio 16.6 Preview 3. It is opt-in, and you need
to add the StdOutEncoding tag. MSBuild treats these as property bags so
if we emit the tag for earlier versions of Visual Studio it would be
safely ignored. This change emits the StdOutEncoding tag and sets it to
UTF-8 whenever the custom command UTF-8 pipe flag is set. This fixes
globalization issues when the output from cmake contained characters
that required MSBuild to interpret as UTF-8 before displaying them.
Justin Goshi 5 лет назад
Родитель
Сommit
bc877a7e94

+ 3 - 1
Source/cmCustomCommand.cxx

@@ -11,7 +11,8 @@ cmCustomCommand::cmCustomCommand(std::vector<std::string> outputs,
                                  std::vector<std::string> depends,
                                  std::vector<std::string> depends,
                                  cmCustomCommandLines commandLines,
                                  cmCustomCommandLines commandLines,
                                  cmListFileBacktrace lfbt, const char* comment,
                                  cmListFileBacktrace lfbt, const char* comment,
-                                 const char* workingDirectory)
+                                 const char* workingDirectory,
+                                 bool stdPipesUTF8)
   : Outputs(std::move(outputs))
   : Outputs(std::move(outputs))
   , Byproducts(std::move(byproducts))
   , Byproducts(std::move(byproducts))
   , Depends(std::move(depends))
   , Depends(std::move(depends))
@@ -20,6 +21,7 @@ cmCustomCommand::cmCustomCommand(std::vector<std::string> outputs,
   , Comment(comment ? comment : "")
   , Comment(comment ? comment : "")
   , WorkingDirectory(workingDirectory ? workingDirectory : "")
   , WorkingDirectory(workingDirectory ? workingDirectory : "")
   , HaveComment(comment != nullptr)
   , HaveComment(comment != nullptr)
+  , StdPipesUTF8(stdPipesUTF8)
 {
 {
 }
 }
 
 

+ 6 - 1
Source/cmCustomCommand.h

@@ -30,7 +30,8 @@ public:
                   std::vector<std::string> byproducts,
                   std::vector<std::string> byproducts,
                   std::vector<std::string> depends,
                   std::vector<std::string> depends,
                   cmCustomCommandLines commandLines, cmListFileBacktrace lfbt,
                   cmCustomCommandLines commandLines, cmListFileBacktrace lfbt,
-                  const char* comment, const char* workingDirectory);
+                  const char* comment, const char* workingDirectory,
+                  bool stdPipesUTF8);
 
 
   /** Get the output file produced by the command.  */
   /** Get the output file produced by the command.  */
   const std::vector<std::string>& GetOutputs() const;
   const std::vector<std::string>& GetOutputs() const;
@@ -53,6 +54,9 @@ public:
   /** Get the comment string for the command.  */
   /** Get the comment string for the command.  */
   const char* GetComment() const;
   const char* GetComment() const;
 
 
+  /** Get a value indicating if the command uses UTF-8 output pipes. */
+  bool GetStdPipesUTF8() const { return this->StdPipesUTF8; }
+
   /** Append to the list of command lines.  */
   /** Append to the list of command lines.  */
   void AppendCommands(const cmCustomCommandLines& commandLines);
   void AppendCommands(const cmCustomCommandLines& commandLines);
 
 
@@ -108,6 +112,7 @@ private:
   bool EscapeOldStyle = true;
   bool EscapeOldStyle = true;
   bool UsesTerminal = false;
   bool UsesTerminal = false;
   bool CommandExpandLists = false;
   bool CommandExpandLists = false;
+  bool StdPipesUTF8 = false;
 };
 };
 
 
 #endif
 #endif

+ 5 - 1
Source/cmGlobalGenerator.cxx

@@ -2543,6 +2543,7 @@ void cmGlobalGenerator::AddGlobalTarget_EditCache(
     singleLine.push_back("No interactive CMake dialog available.");
     singleLine.push_back("No interactive CMake dialog available.");
     gti.Message = "No interactive CMake dialog available...";
     gti.Message = "No interactive CMake dialog available...";
     gti.UsesTerminal = false;
     gti.UsesTerminal = false;
+    gti.StdPipesUTF8 = true;
   }
   }
   gti.CommandLines.push_back(std::move(singleLine));
   gti.CommandLines.push_back(std::move(singleLine));
 
 
@@ -2567,6 +2568,7 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache(
   singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
   singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
   singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
   singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
   gti.CommandLines.push_back(std::move(singleLine));
   gti.CommandLines.push_back(std::move(singleLine));
+  gti.StdPipesUTF8 = true;
   targets.push_back(std::move(gti));
   targets.push_back(std::move(gti));
 }
 }
 
 
@@ -2603,6 +2605,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
     gti.Name = this->GetInstallTargetName();
     gti.Name = this->GetInstallTargetName();
     gti.Message = "Install the project...";
     gti.Message = "Install the project...";
     gti.UsesTerminal = true;
     gti.UsesTerminal = true;
+    gti.StdPipesUTF8 = true;
     cmCustomCommandLine singleLine;
     cmCustomCommandLine singleLine;
     if (this->GetPreinstallTargetName()) {
     if (this->GetPreinstallTargetName()) {
       gti.Depends.emplace_back(this->GetPreinstallTargetName());
       gti.Depends.emplace_back(this->GetPreinstallTargetName());
@@ -2714,7 +2717,8 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
   std::vector<std::string> no_depends;
   std::vector<std::string> no_depends;
   // Store the custom command in the target.
   // Store the custom command in the target.
   cmCustomCommand cc(no_outputs, no_byproducts, no_depends, gti.CommandLines,
   cmCustomCommand cc(no_outputs, no_byproducts, no_depends, gti.CommandLines,
-                     cmListFileBacktrace(), nullptr, gti.WorkingDir.c_str());
+                     cmListFileBacktrace(), nullptr, gti.WorkingDir.c_str(),
+                     gti.StdPipesUTF8);
   cc.SetUsesTerminal(gti.UsesTerminal);
   cc.SetUsesTerminal(gti.UsesTerminal);
   target.AddPostBuildCommand(std::move(cc));
   target.AddPostBuildCommand(std::move(cc));
   if (!gti.Message.empty()) {
   if (!gti.Message.empty()) {

+ 1 - 0
Source/cmGlobalGenerator.h

@@ -554,6 +554,7 @@ protected:
     std::string WorkingDir;
     std::string WorkingDir;
     bool UsesTerminal = false;
     bool UsesTerminal = false;
     bool PerConfig = true;
     bool PerConfig = true;
+    bool StdPipesUTF8 = false;
   };
   };
 
 
   void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets);
   void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets);

+ 6 - 2
Source/cmGlobalVisualStudio8Generator.cxx

@@ -142,6 +142,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
 
 
   // Add a custom rule to re-run CMake if any input files changed.
   // Add a custom rule to re-run CMake if any input files changed.
   {
   {
+    // The custom rule runs cmake so set UTF-8 pipes.
+    bool stdPipesUTF8 = true;
+
     // Collect the input files used to generate all targets in this
     // Collect the input files used to generate all targets in this
     // project.
     // project.
     std::vector<std::string> listFiles;
     std::vector<std::string> listFiles;
@@ -160,7 +163,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
       lg.AddCustomCommandToTarget(
       lg.AddCustomCommandToTarget(
         CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts, no_depends,
         CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts, no_depends,
         verifyCommandLines, cmCustomCommandType::PRE_BUILD,
         verifyCommandLines, cmCustomCommandType::PRE_BUILD,
-        "Checking File Globs", no_working_directory, false);
+        "Checking File Globs", no_working_directory, stdPipesUTF8);
 
 
       // Ensure ZERO_CHECK always runs in Visual Studio using MSBuild,
       // Ensure ZERO_CHECK always runs in Visual Studio using MSBuild,
       // otherwise the prebuild command will not be run.
       // otherwise the prebuild command will not be run.
@@ -192,7 +195,8 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
     if (cmSourceFile* file = lg.AddCustomCommandToOutput(
     if (cmSourceFile* file = lg.AddCustomCommandToOutput(
           stamps, no_byproducts, listFiles, no_main_dependency,
           stamps, no_byproducts, listFiles, no_main_dependency,
           no_implicit_depends, commandLines, "Checking Build System",
           no_implicit_depends, commandLines, "Checking Build System",
-          no_working_directory, true, false)) {
+          no_working_directory, true, false, false, false, "", "",
+          stdPipesUTF8)) {
       gt->AddSource(file->ResolveFullPath());
       gt->AddSource(file->ResolveFullPath());
     } else {
     } else {
       cmSystemTools::Error("Error adding rule for " + stamps[0]);
       cmSystemTools::Error("Error adding rule for " + stamps[0]);

+ 1 - 1
Source/cmGlobalVisualStudioGenerator.cxx

@@ -932,7 +932,7 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
     { cmakeCommand, "-E", "__create_def", mdi->DefFile, objs_file });
     { cmakeCommand, "-E", "__create_def", mdi->DefFile, objs_file });
   cmCustomCommand command(outputs, empty, empty, commandLines,
   cmCustomCommand command(outputs, empty, empty, commandLines,
                           gt->Target->GetMakefile()->GetBacktrace(),
                           gt->Target->GetMakefile()->GetBacktrace(),
-                          "Auto build dll exports", ".");
+                          "Auto build dll exports", ".", true);
   commands.push_back(std::move(command));
   commands.push_back(std::move(command));
 }
 }
 
 

+ 2 - 1
Source/cmGlobalXCodeGenerator.cxx

@@ -1464,6 +1464,7 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
       cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>');
       cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>');
     std::string str_link_file =
     std::string str_link_file =
       cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>');
       cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>');
+    bool stdPipesUTF8 = true;
     cmCustomCommandLines cmd = cmMakeSingleCommandLine(
     cmCustomCommandLines cmd = cmMakeSingleCommandLine(
       { cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library",
       { cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library",
         str_file, str_so_file, str_link_file });
         str_file, str_so_file, str_link_file });
@@ -1471,7 +1472,7 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
     cmCustomCommand command(
     cmCustomCommand command(
       std::vector<std::string>(), std::vector<std::string>(),
       std::vector<std::string>(), std::vector<std::string>(),
       std::vector<std::string>(), cmd, this->CurrentMakefile->GetBacktrace(),
       std::vector<std::string>(), cmd, this->CurrentMakefile->GetBacktrace(),
-      "Creating symlinks", "");
+      "Creating symlinks", "", stdPipesUTF8);
 
 
     postbuild.push_back(std::move(command));
     postbuild.push_back(std::move(command));
   }
   }

+ 24 - 19
Source/cmLocalGenerator.cxx

@@ -1067,7 +1067,8 @@ cmTarget* cmLocalGenerator::AddCustomCommandToTarget(
   const cmCustomCommandLines& commandLines, cmCustomCommandType type,
   const cmCustomCommandLines& commandLines, cmCustomCommandType type,
   const char* comment, const char* workingDir, bool escapeOldStyle,
   const char* comment, const char* workingDir, bool escapeOldStyle,
   bool uses_terminal, const std::string& depfile, const std::string& job_pool,
   bool uses_terminal, const std::string& depfile, const std::string& job_pool,
-  bool command_expand_lists, cmObjectLibraryCommands objLibCommands)
+  bool command_expand_lists, cmObjectLibraryCommands objLibCommands,
+  bool stdPipesUTF8)
 {
 {
   cmTarget* t = this->Makefile->GetCustomCommandTarget(
   cmTarget* t = this->Makefile->GetCustomCommandTarget(
     target, objLibCommands, this->DirectoryBacktrace);
     target, objLibCommands, this->DirectoryBacktrace);
@@ -1078,7 +1079,7 @@ cmTarget* cmLocalGenerator::AddCustomCommandToTarget(
   detail::AddCustomCommandToTarget(
   detail::AddCustomCommandToTarget(
     *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, t, byproducts,
     *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, t, byproducts,
     depends, commandLines, type, comment, workingDir, escapeOldStyle,
     depends, commandLines, type, comment, workingDir, escapeOldStyle,
-    uses_terminal, depfile, job_pool, command_expand_lists);
+    uses_terminal, depfile, job_pool, command_expand_lists, stdPipesUTF8);
 
 
   return t;
   return t;
 }
 }
@@ -1088,14 +1089,14 @@ cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
   const std::string& main_dependency, const cmCustomCommandLines& commandLines,
   const std::string& main_dependency, const cmCustomCommandLines& commandLines,
   const char* comment, const char* workingDir, bool replace,
   const char* comment, const char* workingDir, bool replace,
   bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
   bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
-  const std::string& depfile, const std::string& job_pool)
+  const std::string& depfile, const std::string& job_pool, bool stdPipesUTF8)
 {
 {
   std::vector<std::string> no_byproducts;
   std::vector<std::string> no_byproducts;
   cmImplicitDependsList no_implicit_depends;
   cmImplicitDependsList no_implicit_depends;
   return this->AddCustomCommandToOutput(
   return this->AddCustomCommandToOutput(
     { output }, no_byproducts, depends, main_dependency, no_implicit_depends,
     { output }, no_byproducts, depends, main_dependency, no_implicit_depends,
     commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
     commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
-    command_expand_lists, depfile, job_pool);
+    command_expand_lists, depfile, job_pool, stdPipesUTF8);
 }
 }
 
 
 cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
 cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
@@ -1106,7 +1107,7 @@ cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
   const cmCustomCommandLines& commandLines, const char* comment,
   const cmCustomCommandLines& commandLines, const char* comment,
   const char* workingDir, bool replace, bool escapeOldStyle,
   const char* workingDir, bool replace, bool escapeOldStyle,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
-  const std::string& job_pool)
+  const std::string& job_pool, bool stdPipesUTF8)
 {
 {
   // Make sure there is at least one output.
   // Make sure there is at least one output.
   if (outputs.empty()) {
   if (outputs.empty()) {
@@ -1118,7 +1119,7 @@ cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
     *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, outputs,
     *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, outputs,
     byproducts, depends, main_dependency, implicit_depends, commandLines,
     byproducts, depends, main_dependency, implicit_depends, commandLines,
     comment, workingDir, replace, escapeOldStyle, uses_terminal,
     comment, workingDir, replace, escapeOldStyle, uses_terminal,
-    command_expand_lists, depfile, job_pool);
+    command_expand_lists, depfile, job_pool, stdPipesUTF8);
 }
 }
 
 
 cmTarget* cmLocalGenerator::AddUtilityCommand(
 cmTarget* cmLocalGenerator::AddUtilityCommand(
@@ -1127,7 +1128,7 @@ cmTarget* cmLocalGenerator::AddUtilityCommand(
   const std::vector<std::string>& depends,
   const std::vector<std::string>& depends,
   const cmCustomCommandLines& commandLines, bool escapeOldStyle,
   const cmCustomCommandLines& commandLines, bool escapeOldStyle,
   const char* comment, bool uses_terminal, bool command_expand_lists,
   const char* comment, bool uses_terminal, bool command_expand_lists,
-  const std::string& job_pool)
+  const std::string& job_pool, bool stdPipesUTF8)
 {
 {
   cmTarget* target =
   cmTarget* target =
     this->Makefile->AddNewUtilityTarget(utilityName, excludeFromAll);
     this->Makefile->AddNewUtilityTarget(utilityName, excludeFromAll);
@@ -1141,7 +1142,7 @@ cmTarget* cmLocalGenerator::AddUtilityCommand(
     *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, target,
     *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, target,
     this->Makefile->GetUtilityOutput(target), workingDir, byproducts, depends,
     this->Makefile->GetUtilityOutput(target), workingDir, byproducts, depends,
     commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists,
     commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists,
-    job_pool);
+    job_pool, stdPipesUTF8);
 
 
   return target;
   return target;
 }
 }
@@ -2633,6 +2634,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
                   file << "endif()\n";
                   file << "endif()\n";
                 }
                 }
 
 
+                bool stdPipesUTF8 = true;
                 cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
                 cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
                   { cmSystemTools::GetCMakeCommand(),
                   { cmSystemTools::GetCMakeCommand(),
                     cmStrCat("-DPDB_PREFIX=", pdb_prefix), "-P",
                     cmStrCat("-DPDB_PREFIX=", pdb_prefix), "-P",
@@ -2651,14 +2653,16 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
                 if (this->GetGlobalGenerator()->IsVisualStudio()) {
                 if (this->GetGlobalGenerator()->IsVisualStudio()) {
                   this->AddCustomCommandToTarget(
                   this->AddCustomCommandToTarget(
                     target->GetName(), outputs, no_deps, commandLines,
                     target->GetName(), outputs, no_deps, commandLines,
-                    cmCustomCommandType::PRE_BUILD, no_message,
-                    no_current_dir);
+                    cmCustomCommandType::PRE_BUILD, no_message, no_current_dir,
+                    true, false, "", "", false,
+                    cmObjectLibraryCommands::Reject, stdPipesUTF8);
                 } else {
                 } else {
                   cmImplicitDependsList no_implicit_depends;
                   cmImplicitDependsList no_implicit_depends;
                   cmSourceFile* copy_rule = this->AddCustomCommandToOutput(
                   cmSourceFile* copy_rule = this->AddCustomCommandToOutput(
                     outputs, no_byproducts, no_deps, no_main_dependency,
                     outputs, no_byproducts, no_deps, no_main_dependency,
                     no_implicit_depends, commandLines, no_message,
                     no_implicit_depends, commandLines, no_message,
-                    no_current_dir);
+                    no_current_dir, false, true, false, false, "", "",
+                    stdPipesUTF8);
 
 
                   if (copy_rule) {
                   if (copy_rule) {
                     target->AddSource(copy_rule->ResolveFullPath());
                     target->AddSource(copy_rule->ResolveFullPath());
@@ -3715,7 +3719,7 @@ cmSourceFile* AddCustomCommand(
   const cmCustomCommandLines& commandLines, const char* comment,
   const cmCustomCommandLines& commandLines, const char* comment,
   const char* workingDir, bool replace, bool escapeOldStyle,
   const char* workingDir, bool replace, bool escapeOldStyle,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
-  const std::string& job_pool)
+  const std::string& job_pool, bool stdPipesUTF8)
 {
 {
   cmMakefile* mf = lg.GetMakefile();
   cmMakefile* mf = lg.GetMakefile();
 
 
@@ -3777,7 +3781,8 @@ cmSourceFile* AddCustomCommand(
     }
     }
 
 
     std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>(
     std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>(
-      outputs, byproducts, depends2, commandLines, lfbt, comment, workingDir);
+      outputs, byproducts, depends2, commandLines, lfbt, comment, workingDir,
+      stdPipesUTF8);
     cc->SetEscapeOldStyle(escapeOldStyle);
     cc->SetEscapeOldStyle(escapeOldStyle);
     cc->SetEscapeAllowMakeVars(true);
     cc->SetEscapeAllowMakeVars(true);
     cc->SetImplicitDepends(implicit_depends);
     cc->SetImplicitDepends(implicit_depends);
@@ -3804,7 +3809,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
                               const char* workingDir, bool escapeOldStyle,
                               const char* workingDir, bool escapeOldStyle,
                               bool uses_terminal, const std::string& depfile,
                               bool uses_terminal, const std::string& depfile,
                               const std::string& job_pool,
                               const std::string& job_pool,
-                              bool command_expand_lists)
+                              bool command_expand_lists, bool stdPipesUTF8)
 {
 {
   cmMakefile* mf = lg.GetMakefile();
   cmMakefile* mf = lg.GetMakefile();
 
 
@@ -3814,7 +3819,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
   // Add the command to the appropriate build step for the target.
   // Add the command to the appropriate build step for the target.
   std::vector<std::string> no_output;
   std::vector<std::string> no_output;
   cmCustomCommand cc(no_output, byproducts, depends, commandLines, lfbt,
   cmCustomCommand cc(no_output, byproducts, depends, commandLines, lfbt,
-                     comment, workingDir);
+                     comment, workingDir, stdPipesUTF8);
   cc.SetEscapeOldStyle(escapeOldStyle);
   cc.SetEscapeOldStyle(escapeOldStyle);
   cc.SetEscapeAllowMakeVars(true);
   cc.SetEscapeAllowMakeVars(true);
   cc.SetUsesTerminal(uses_terminal);
   cc.SetUsesTerminal(uses_terminal);
@@ -3845,7 +3850,7 @@ cmSourceFile* AddCustomCommandToOutput(
   const cmCustomCommandLines& commandLines, const char* comment,
   const cmCustomCommandLines& commandLines, const char* comment,
   const char* workingDir, bool replace, bool escapeOldStyle,
   const char* workingDir, bool replace, bool escapeOldStyle,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
-  const std::string& job_pool)
+  const std::string& job_pool, bool stdPipesUTF8)
 {
 {
   // Always create the output sources and mark them generated.
   // Always create the output sources and mark them generated.
   CreateGeneratedSources(lg, outputs, origin, lfbt);
   CreateGeneratedSources(lg, outputs, origin, lfbt);
@@ -3854,7 +3859,7 @@ cmSourceFile* AddCustomCommandToOutput(
   return AddCustomCommand(
   return AddCustomCommand(
     lg, lfbt, outputs, byproducts, depends, main_dependency, implicit_depends,
     lg, lfbt, outputs, byproducts, depends, main_dependency, implicit_depends,
     commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
     commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
-    command_expand_lists, depfile, job_pool);
+    command_expand_lists, depfile, job_pool, stdPipesUTF8);
 }
 }
 
 
 void AppendCustomCommandToOutput(cmLocalGenerator& lg,
 void AppendCustomCommandToOutput(cmLocalGenerator& lg,
@@ -3890,7 +3895,7 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
                        const cmCustomCommandLines& commandLines,
                        const cmCustomCommandLines& commandLines,
                        bool escapeOldStyle, const char* comment,
                        bool escapeOldStyle, const char* comment,
                        bool uses_terminal, bool command_expand_lists,
                        bool uses_terminal, bool command_expand_lists,
-                       const std::string& job_pool)
+                       const std::string& job_pool, bool stdPipesUTF8)
 {
 {
   // Always create the byproduct sources and mark them generated.
   // Always create the byproduct sources and mark them generated.
   CreateGeneratedSource(lg, force.Name, origin, lfbt);
   CreateGeneratedSource(lg, force.Name, origin, lfbt);
@@ -3907,7 +3912,7 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
     lg, lfbt, { force.Name }, byproducts, depends, no_main_dependency,
     lg, lfbt, { force.Name }, byproducts, depends, no_main_dependency,
     no_implicit_depends, commandLines, comment, workingDir, /*replace=*/false,
     no_implicit_depends, commandLines, comment, workingDir, /*replace=*/false,
     escapeOldStyle, uses_terminal, command_expand_lists, /*depfile=*/"",
     escapeOldStyle, uses_terminal, command_expand_lists, /*depfile=*/"",
-    job_pool);
+    job_pool, stdPipesUTF8);
   if (rule) {
   if (rule) {
     lg.GetMakefile()->AddTargetByproducts(target, byproducts);
     lg.GetMakefile()->AddTargetByproducts(target, byproducts);
   }
   }

+ 11 - 7
Source/cmLocalGenerator.h

@@ -297,7 +297,8 @@ public:
     const char* comment, const char* workingDir, bool escapeOldStyle = true,
     const char* comment, const char* workingDir, bool escapeOldStyle = true,
     bool uses_terminal = false, const std::string& depfile = "",
     bool uses_terminal = false, const std::string& depfile = "",
     const std::string& job_pool = "", bool command_expand_lists = false,
     const std::string& job_pool = "", bool command_expand_lists = false,
-    cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject);
+    cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject,
+    bool stdPipesUTF8 = false);
 
 
   /**
   /**
    * Add a custom command to a source file.
    * Add a custom command to a source file.
@@ -308,7 +309,8 @@ public:
     const cmCustomCommandLines& commandLines, const char* comment,
     const cmCustomCommandLines& commandLines, const char* comment,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     bool uses_terminal = false, bool command_expand_lists = false,
     bool uses_terminal = false, bool command_expand_lists = false,
-    const std::string& depfile = "", const std::string& job_pool = "");
+    const std::string& depfile = "", const std::string& job_pool = "",
+    bool stdPipesUTF8 = false);
   cmSourceFile* AddCustomCommandToOutput(
   cmSourceFile* AddCustomCommandToOutput(
     const std::vector<std::string>& outputs,
     const std::vector<std::string>& outputs,
     const std::vector<std::string>& byproducts,
     const std::vector<std::string>& byproducts,
@@ -318,7 +320,8 @@ public:
     const cmCustomCommandLines& commandLines, const char* comment,
     const cmCustomCommandLines& commandLines, const char* comment,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     bool uses_terminal = false, bool command_expand_lists = false,
     bool uses_terminal = false, bool command_expand_lists = false,
-    const std::string& depfile = "", const std::string& job_pool = "");
+    const std::string& depfile = "", const std::string& job_pool = "",
+    bool stdPipesUTF8 = false);
 
 
   /**
   /**
    * Add a utility to the build.  A utility target is a command that is run
    * Add a utility to the build.  A utility target is a command that is run
@@ -330,7 +333,8 @@ public:
     const std::vector<std::string>& depends,
     const std::vector<std::string>& depends,
     const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
     const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
     const char* comment = nullptr, bool uses_terminal = false,
     const char* comment = nullptr, bool uses_terminal = false,
-    bool command_expand_lists = false, const std::string& job_pool = "");
+    bool command_expand_lists = false, const std::string& job_pool = "",
+    bool stdPipesUTF8 = false);
 
 
   std::string GetProjectName() const;
   std::string GetProjectName() const;
 
 
@@ -547,7 +551,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
                               const char* workingDir, bool escapeOldStyle,
                               const char* workingDir, bool escapeOldStyle,
                               bool uses_terminal, const std::string& depfile,
                               bool uses_terminal, const std::string& depfile,
                               const std::string& job_pool,
                               const std::string& job_pool,
-                              bool command_expand_lists);
+                              bool command_expand_lists, bool stdPipesUTF8);
 
 
 cmSourceFile* AddCustomCommandToOutput(
 cmSourceFile* AddCustomCommandToOutput(
   cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
   cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
@@ -558,7 +562,7 @@ cmSourceFile* AddCustomCommandToOutput(
   const cmCustomCommandLines& commandLines, const char* comment,
   const cmCustomCommandLines& commandLines, const char* comment,
   const char* workingDir, bool replace, bool escapeOldStyle,
   const char* workingDir, bool replace, bool escapeOldStyle,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
-  const std::string& job_pool);
+  const std::string& job_pool, bool stdPipesUTF8);
 
 
 void AppendCustomCommandToOutput(cmLocalGenerator& lg,
 void AppendCustomCommandToOutput(cmLocalGenerator& lg,
                                  const cmListFileBacktrace& lfbt,
                                  const cmListFileBacktrace& lfbt,
@@ -575,7 +579,7 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
                        const cmCustomCommandLines& commandLines,
                        const cmCustomCommandLines& commandLines,
                        bool escapeOldStyle, const char* comment,
                        bool escapeOldStyle, const char* comment,
                        bool uses_terminal, bool command_expand_lists,
                        bool uses_terminal, bool command_expand_lists,
-                       const std::string& job_pool);
+                       const std::string& job_pool, bool stdPipesUTF8);
 }
 }
 
 
 #endif
 #endif

+ 4 - 3
Source/cmLocalVisualStudio7Generator.cxx

@@ -251,14 +251,15 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
   std::string argB = cmStrCat("-B", this->GetBinaryDirectory());
   std::string argB = cmStrCat("-B", this->GetBinaryDirectory());
   std::string stampName =
   std::string stampName =
     cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/generate.stamp");
     cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/generate.stamp");
+  bool stdPipesUTF8 = true;
   cmCustomCommandLines commandLines =
   cmCustomCommandLines commandLines =
     cmMakeSingleCommandLine({ cmSystemTools::GetCMakeCommand(), argS, argB,
     cmMakeSingleCommandLine({ cmSystemTools::GetCMakeCommand(), argS, argB,
                               "--check-stamp-file", stampName });
                               "--check-stamp-file", stampName });
   std::string comment = cmStrCat("Building Custom Rule ", makefileIn);
   std::string comment = cmStrCat("Building Custom Rule ", makefileIn);
   const char* no_working_directory = nullptr;
   const char* no_working_directory = nullptr;
-  this->AddCustomCommandToOutput(stampName, listFiles, makefileIn,
-                                 commandLines, comment.c_str(),
-                                 no_working_directory, true, false);
+  this->AddCustomCommandToOutput(
+    stampName, listFiles, makefileIn, commandLines, comment.c_str(),
+    no_working_directory, true, false, false, false, "", "", stdPipesUTF8);
   if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
   if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
     // Finalize the source file path now since we're adding this after
     // Finalize the source file path now since we're adding this after
     // the generator validated all project-named sources.
     // the generator validated all project-named sources.

+ 3 - 1
Source/cmLocalVisualStudioGenerator.cxx

@@ -102,10 +102,12 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target,
   std::vector<std::string> no_output;
   std::vector<std::string> no_output;
   std::vector<std::string> no_byproducts;
   std::vector<std::string> no_byproducts;
   std::vector<std::string> no_depends;
   std::vector<std::string> no_depends;
+  bool stdPipesUTF8 = true;
   cmCustomCommandLines commands = cmMakeSingleCommandLine(
   cmCustomCommandLines commands = cmMakeSingleCommandLine(
     { cmSystemTools::GetCMakeCommand(), "-E", "make_directory", impDir });
     { cmSystemTools::GetCMakeCommand(), "-E", "make_directory", impDir });
   pcc.reset(new cmCustomCommand(no_output, no_byproducts, no_depends, commands,
   pcc.reset(new cmCustomCommand(no_output, no_byproducts, no_depends, commands,
-                                cmListFileBacktrace(), nullptr, nullptr));
+                                cmListFileBacktrace(), nullptr, nullptr,
+                                stdPipesUTF8));
   pcc->SetEscapeOldStyle(false);
   pcc->SetEscapeOldStyle(false);
   pcc->SetEscapeAllowMakeVars(true);
   pcc->SetEscapeAllowMakeVars(true);
   return pcc;
   return pcc;

+ 28 - 26
Source/cmMakefile.cxx

@@ -1021,7 +1021,7 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
   const cmCustomCommandLines& commandLines, cmCustomCommandType type,
   const cmCustomCommandLines& commandLines, cmCustomCommandType type,
   const char* comment, const char* workingDir, bool escapeOldStyle,
   const char* comment, const char* workingDir, bool escapeOldStyle,
   bool uses_terminal, const std::string& depfile, const std::string& job_pool,
   bool uses_terminal, const std::string& depfile, const std::string& job_pool,
-  bool command_expand_lists)
+  bool command_expand_lists, bool stdPipesUTF8)
 {
 {
   cmTarget* t = this->GetCustomCommandTarget(
   cmTarget* t = this->GetCustomCommandTarget(
     target, cmObjectLibraryCommands::Reject, this->Backtrace);
     target, cmObjectLibraryCommands::Reject, this->Backtrace);
@@ -1039,14 +1039,15 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
   cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
   cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
 
 
   // Dispatch command creation to allow generator expressions in outputs.
   // Dispatch command creation to allow generator expressions in outputs.
-  this->AddGeneratorAction([=](cmLocalGenerator& lg,
-                               const cmListFileBacktrace& lfbt) {
-    BacktraceGuard guard(this->Backtrace, lfbt);
-    detail::AddCustomCommandToTarget(
-      lg, lfbt, cmCommandOrigin::Project, t, byproducts, depends, commandLines,
-      type, GetCStrOrNull(commentStr), GetCStrOrNull(workingStr),
-      escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists);
-  });
+  this->AddGeneratorAction(
+    [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
+      BacktraceGuard guard(this->Backtrace, lfbt);
+      detail::AddCustomCommandToTarget(
+        lg, lfbt, cmCommandOrigin::Project, t, byproducts, depends,
+        commandLines, type, GetCStrOrNull(commentStr),
+        GetCStrOrNull(workingStr), escapeOldStyle, uses_terminal, depfile,
+        job_pool, command_expand_lists, stdPipesUTF8);
+    });
 
 
   return t;
   return t;
 }
 }
@@ -1057,14 +1058,14 @@ void cmMakefile::AddCustomCommandToOutput(
   const char* comment, const char* workingDir,
   const char* comment, const char* workingDir,
   const CommandSourceCallback& callback, bool replace, bool escapeOldStyle,
   const CommandSourceCallback& callback, bool replace, bool escapeOldStyle,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
   bool uses_terminal, bool command_expand_lists, const std::string& depfile,
-  const std::string& job_pool)
+  const std::string& job_pool, bool stdPipesUTF8)
 {
 {
   std::vector<std::string> no_byproducts;
   std::vector<std::string> no_byproducts;
   cmImplicitDependsList no_implicit_depends;
   cmImplicitDependsList no_implicit_depends;
   this->AddCustomCommandToOutput(
   this->AddCustomCommandToOutput(
     { output }, no_byproducts, depends, main_dependency, no_implicit_depends,
     { output }, no_byproducts, depends, main_dependency, no_implicit_depends,
     commandLines, comment, workingDir, callback, replace, escapeOldStyle,
     commandLines, comment, workingDir, callback, replace, escapeOldStyle,
-    uses_terminal, command_expand_lists, depfile, job_pool);
+    uses_terminal, command_expand_lists, depfile, job_pool, stdPipesUTF8);
 }
 }
 
 
 void cmMakefile::AddCustomCommandToOutput(
 void cmMakefile::AddCustomCommandToOutput(
@@ -1075,7 +1076,7 @@ void cmMakefile::AddCustomCommandToOutput(
   const cmCustomCommandLines& commandLines, const char* comment,
   const cmCustomCommandLines& commandLines, const char* comment,
   const char* workingDir, const CommandSourceCallback& callback, bool replace,
   const char* workingDir, const CommandSourceCallback& callback, bool replace,
   bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
   bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
-  const std::string& depfile, const std::string& job_pool)
+  const std::string& depfile, const std::string& job_pool, bool stdPipesUTF8)
 {
 {
   // Make sure there is at least one output.
   // Make sure there is at least one output.
   if (outputs.empty()) {
   if (outputs.empty()) {
@@ -1097,18 +1098,19 @@ void cmMakefile::AddCustomCommandToOutput(
   cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
   cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
 
 
   // Dispatch command creation to allow generator expressions in outputs.
   // Dispatch command creation to allow generator expressions in outputs.
-  this->AddGeneratorAction([=](cmLocalGenerator& lg,
-                               const cmListFileBacktrace& lfbt) {
-    BacktraceGuard guard(this->Backtrace, lfbt);
-    cmSourceFile* sf = detail::AddCustomCommandToOutput(
-      lg, lfbt, cmCommandOrigin::Project, outputs, byproducts, depends,
-      main_dependency, implicit_depends, commandLines,
-      GetCStrOrNull(commentStr), GetCStrOrNull(workingStr), replace,
-      escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool);
-    if (callback && sf) {
-      callback(sf);
-    }
-  });
+  this->AddGeneratorAction(
+    [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
+      BacktraceGuard guard(this->Backtrace, lfbt);
+      cmSourceFile* sf = detail::AddCustomCommandToOutput(
+        lg, lfbt, cmCommandOrigin::Project, outputs, byproducts, depends,
+        main_dependency, implicit_depends, commandLines,
+        GetCStrOrNull(commentStr), GetCStrOrNull(workingStr), replace,
+        escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool,
+        stdPipesUTF8);
+      if (callback && sf) {
+        callback(sf);
+      }
+    });
 }
 }
 
 
 void cmMakefile::AddCustomCommandOldStyle(
 void cmMakefile::AddCustomCommandOldStyle(
@@ -1224,7 +1226,7 @@ cmTarget* cmMakefile::AddUtilityCommand(
   const std::vector<std::string>& depends,
   const std::vector<std::string>& depends,
   const cmCustomCommandLines& commandLines, bool escapeOldStyle,
   const cmCustomCommandLines& commandLines, bool escapeOldStyle,
   const char* comment, bool uses_terminal, bool command_expand_lists,
   const char* comment, bool uses_terminal, bool command_expand_lists,
-  const std::string& job_pool)
+  const std::string& job_pool, bool stdPipesUTF8)
 {
 {
   cmTarget* target = this->AddNewUtilityTarget(utilityName, excludeFromAll);
   cmTarget* target = this->AddNewUtilityTarget(utilityName, excludeFromAll);
 
 
@@ -1253,7 +1255,7 @@ cmTarget* cmMakefile::AddUtilityCommand(
                                 force, GetCStrOrNull(workingStr), byproducts,
                                 force, GetCStrOrNull(workingStr), byproducts,
                                 depends, commandLines, escapeOldStyle,
                                 depends, commandLines, escapeOldStyle,
                                 GetCStrOrNull(commentStr), uses_terminal,
                                 GetCStrOrNull(commentStr), uses_terminal,
-                                command_expand_lists, job_pool);
+                                command_expand_lists, job_pool, stdPipesUTF8);
     });
     });
 
 
   return target;
   return target;

+ 8 - 4
Source/cmMakefile.h

@@ -188,7 +188,8 @@ public:
     const cmCustomCommandLines& commandLines, cmCustomCommandType type,
     const cmCustomCommandLines& commandLines, cmCustomCommandType type,
     const char* comment, const char* workingDir, bool escapeOldStyle = true,
     const char* comment, const char* workingDir, bool escapeOldStyle = true,
     bool uses_terminal = false, const std::string& depfile = "",
     bool uses_terminal = false, const std::string& depfile = "",
-    const std::string& job_pool = "", bool command_expand_lists = false);
+    const std::string& job_pool = "", bool command_expand_lists = false,
+    bool stdPipesUTF8 = false);
 
 
   /**
   /**
    * Called for each file with custom command.
    * Called for each file with custom command.
@@ -205,7 +206,8 @@ public:
     const char* workingDir, const CommandSourceCallback& callback = nullptr,
     const char* workingDir, const CommandSourceCallback& callback = nullptr,
     bool replace = false, bool escapeOldStyle = true,
     bool replace = false, bool escapeOldStyle = true,
     bool uses_terminal = false, bool command_expand_lists = false,
     bool uses_terminal = false, bool command_expand_lists = false,
-    const std::string& depfile = "", const std::string& job_pool = "");
+    const std::string& depfile = "", const std::string& job_pool = "",
+    bool stdPipesUTF8 = false);
   void AddCustomCommandToOutput(
   void AddCustomCommandToOutput(
     const std::vector<std::string>& outputs,
     const std::vector<std::string>& outputs,
     const std::vector<std::string>& byproducts,
     const std::vector<std::string>& byproducts,
@@ -216,7 +218,8 @@ public:
     const char* workingDir, const CommandSourceCallback& callback = nullptr,
     const char* workingDir, const CommandSourceCallback& callback = nullptr,
     bool replace = false, bool escapeOldStyle = true,
     bool replace = false, bool escapeOldStyle = true,
     bool uses_terminal = false, bool command_expand_lists = false,
     bool uses_terminal = false, bool command_expand_lists = false,
-    const std::string& depfile = "", const std::string& job_pool = "");
+    const std::string& depfile = "", const std::string& job_pool = "",
+    bool stdPipesUTF8 = false);
   void AddCustomCommandOldStyle(const std::string& target,
   void AddCustomCommandOldStyle(const std::string& target,
                                 const std::vector<std::string>& outputs,
                                 const std::vector<std::string>& outputs,
                                 const std::vector<std::string>& depends,
                                 const std::vector<std::string>& depends,
@@ -284,7 +287,8 @@ public:
     const std::vector<std::string>& depends,
     const std::vector<std::string>& depends,
     const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
     const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
     const char* comment = nullptr, bool uses_terminal = false,
     const char* comment = nullptr, bool uses_terminal = false,
-    bool command_expand_lists = false, const std::string& job_pool = "");
+    bool command_expand_lists = false, const std::string& job_pool = "",
+    bool stdPipesUTF8 = false);
 
 
   /**
   /**
    * Add a subdirectory to the build.
    * Add a subdirectory to the build.

+ 9 - 4
Source/cmQtAutoGenInitializer.cxx

@@ -1097,6 +1097,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
   // of fiddling with the include directories
   // of fiddling with the include directories
   std::vector<std::string> configs;
   std::vector<std::string> configs;
   this->GlobalGen->GetQtAutoGenConfigs(configs);
   this->GlobalGen->GetQtAutoGenConfigs(configs);
+  bool stdPipesUTF8 = true;
   cmCustomCommandLines commandLines;
   cmCustomCommandLines commandLines;
   for (auto const& config : configs) {
   for (auto const& config : configs) {
     commandLines.push_back(cmMakeCommandLine(
     commandLines.push_back(cmMakeCommandLine(
@@ -1141,7 +1142,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
     const std::vector<std::string> no_deps;
     const std::vector<std::string> no_deps;
     cmCustomCommand cc(no_output, autogenProvides, no_deps, commandLines,
     cmCustomCommand cc(no_output, autogenProvides, no_deps, commandLines,
                        this->Makefile->GetBacktrace(), autogenComment.c_str(),
                        this->Makefile->GetBacktrace(), autogenComment.c_str(),
-                       this->Dir.Work.c_str());
+                       this->Dir.Work.c_str(), stdPipesUTF8);
     cc.SetEscapeOldStyle(false);
     cc.SetEscapeOldStyle(false);
     cc.SetEscapeAllowMakeVars(true);
     cc.SetEscapeAllowMakeVars(true);
     this->GenTarget->Target->AddPreBuildCommand(std::move(cc));
     this->GenTarget->Target->AddPreBuildCommand(std::move(cc));
@@ -1211,7 +1212,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
         autogenComment.c_str(), this->Dir.Work.c_str(), /*replace=*/false,
         autogenComment.c_str(), this->Dir.Work.c_str(), /*replace=*/false,
         /*escapeOldStyle=*/false,
         /*escapeOldStyle=*/false,
         /*uses_terminal=*/false,
         /*uses_terminal=*/false,
-        /*command_expand_lists=*/false, this->AutogenTarget.DepFile);
+        /*command_expand_lists=*/false, this->AutogenTarget.DepFile, "",
+        stdPipesUTF8);
 
 
       // Alter variables for the autogen target which now merely wraps the
       // Alter variables for the autogen target which now merely wraps the
       // custom command
       // custom command
@@ -1282,6 +1284,7 @@ bool cmQtAutoGenInitializer::InitRccTargets()
     ccDepends.push_back(qrc.QrcFile);
     ccDepends.push_back(qrc.QrcFile);
     ccDepends.push_back(qrc.InfoFile);
     ccDepends.push_back(qrc.InfoFile);
 
 
+    bool stdPipesUTF8 = true;
     cmCustomCommandLines commandLines;
     cmCustomCommandLines commandLines;
     if (this->MultiConfig) {
     if (this->MultiConfig) {
       // Build for all configurations
       // Build for all configurations
@@ -1310,7 +1313,8 @@ bool cmQtAutoGenInitializer::InitRccTargets()
 
 
         cmTarget* autoRccTarget = this->LocalGen->AddUtilityCommand(
         cmTarget* autoRccTarget = this->LocalGen->AddUtilityCommand(
           ccName, true, this->Dir.Work.c_str(), ccOutput, ccDepends,
           ccName, true, this->Dir.Work.c_str(), ccOutput, ccDepends,
-          commandLines, false, ccComment.c_str());
+          commandLines, false, ccComment.c_str(), false, false, "",
+          stdPipesUTF8);
 
 
         // Create autogen generator target
         // Create autogen generator target
         this->LocalGen->AddGeneratorTarget(
         this->LocalGen->AddGeneratorTarget(
@@ -1350,7 +1354,8 @@ bool cmQtAutoGenInitializer::InitRccTargets()
         this->LocalGen->AddCustomCommandToOutput(
         this->LocalGen->AddCustomCommandToOutput(
           ccOutput, ccByproducts, ccDepends, no_main_dependency,
           ccOutput, ccByproducts, ccDepends, no_main_dependency,
           no_implicit_depends, commandLines, ccComment.c_str(),
           no_implicit_depends, commandLines, ccComment.c_str(),
-          this->Dir.Work.c_str());
+          this->Dir.Work.c_str(), false, true, false, false, "", "",
+          stdPipesUTF8);
       }
       }
       // Reconfigure when .qrc file changes
       // Reconfigure when .qrc file changes
       this->Makefile->AddCMakeDependFile(qrc.QrcFile);
       this->Makefile->AddCMakeDependFile(qrc.QrcFile);

+ 14 - 0
Source/cmVisualStudio10TargetGenerator.cxx

@@ -1404,6 +1404,9 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
     spe2 = cm::make_unique<Elem>(*spe1, "CustomBuild");
     spe2 = cm::make_unique<Elem>(*spe1, "CustomBuild");
     this->WriteSource(*spe2, source);
     this->WriteSource(*spe2, source);
     spe2->SetHasElements();
     spe2->SetHasElements();
+    if (command.GetStdPipesUTF8()) {
+      this->WriteStdOutEncodingUtf8(*spe2);
+    }
   } else {
   } else {
     Elem e1(e0, "ItemGroup");
     Elem e1(e0, "ItemGroup");
     Elem e2(e1, "None");
     Elem e2(e1, "None");
@@ -4048,6 +4051,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
   std::string script;
   std::string script;
   const char* pre = "";
   const char* pre = "";
   std::string comment;
   std::string comment;
+  bool stdPipesUTF8 = false;
   for (cmCustomCommand const& cc : commands) {
   for (cmCustomCommand const& cc : commands) {
     cmCustomCommandGenerator ccg(cc, configName, lg);
     cmCustomCommandGenerator ccg(cc, configName, lg);
     if (!ccg.HasOnlyEmptyCommandLines()) {
     if (!ccg.HasOnlyEmptyCommandLines()) {
@@ -4056,11 +4060,16 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
       script += pre;
       script += pre;
       pre = "\n";
       pre = "\n";
       script += lg->ConstructScript(ccg);
       script += lg->ConstructScript(ccg);
+
+      stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8();
     }
     }
   }
   }
   comment = cmVS10EscapeComment(comment);
   comment = cmVS10EscapeComment(comment);
   if (this->ProjectType != csproj) {
   if (this->ProjectType != csproj) {
     Elem e2(e1, name);
     Elem e2(e1, name);
+    if (stdPipesUTF8) {
+      this->WriteStdOutEncodingUtf8(e2);
+    }
     e2.Element("Message", comment);
     e2.Element("Message", comment);
     e2.Element("Command", script);
     e2.Element("Command", script);
   } else {
   } else {
@@ -4905,3 +4914,8 @@ std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
 
 
   return path;
   return path;
 }
 }
+
+void cmVisualStudio10TargetGenerator::WriteStdOutEncodingUtf8(Elem& e1)
+{
+  e1.Element("StdOutEncoding", "UTF-8");
+}

+ 2 - 0
Source/cmVisualStudio10TargetGenerator.h

@@ -184,6 +184,8 @@ private:
     Elem& e2, const std::map<std::string, std::string>& tags);
     Elem& e2, const std::map<std::string, std::string>& tags);
   std::string GetCSharpSourceLink(cmSourceFile const* source);
   std::string GetCSharpSourceLink(cmSourceFile const* source);
 
 
+  void WriteStdOutEncodingUtf8(Elem& e1);
+
 private:
 private:
   friend class cmVS10GeneratorOptions;
   friend class cmVS10GeneratorOptions;
   using Options = cmVS10GeneratorOptions;
   using Options = cmVS10GeneratorOptions;