Pārlūkot izejas kodu

Merge topic 'nmake-utf8'

f3f57cc4ed NMake: Use UTF-8 with BOM if supported by nmake
186c9bff53 NMake: Check nmake version for support of UTF-8
8a4f536be6 NMake: Detect nmake version

Acked-by: Kitware Robot <[email protected]>
Merge-request: !6041
Brad King 4 gadi atpakaļ
vecāks
revīzija
e0b4a22ca6

+ 5 - 0
Help/release/dev/nmake-utf8.rst

@@ -0,0 +1,5 @@
+nmake-utf8
+----------
+
+* The :generator:`NMake Makefiles` generator now encodes the generated
+  makefiles as UTF-8 with a BOM when using ``nmake`` from VS 9 or above.

+ 5 - 0
Source/cmGeneratedFileStream.cxx

@@ -42,6 +42,11 @@ cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name,
 #else
   static_cast<void>(encoding);
 #endif
+  if (encoding == codecvt::UTF8_WITH_BOM) {
+    // Write the BOM encoding header into the file
+    char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
+    this->write(magic, 3);
+  }
 }
 
 cmGeneratedFileStream::~cmGeneratedFileStream()

+ 41 - 0
Source/cmGlobalNMakeMakefileGenerator.cxx

@@ -2,7 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGlobalNMakeMakefileGenerator.h"
 
+#include "cmsys/RegularExpression.hxx"
+
 #include "cmDocumentationEntry.h"
+#include "cmDuration.h"
 #include "cmLocalUnixMakefileGenerator3.h"
 #include "cmMakefile.h"
 #include "cmState.h"
@@ -34,6 +37,44 @@ void cmGlobalNMakeMakefileGenerator::EnableLanguage(
   this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
 }
 
+bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf)
+{
+  if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
+    return false;
+  }
+  if (cmProp nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
+    std::vector<std::string> command;
+    command.emplace_back(*nmakeCommand);
+    command.emplace_back("-?");
+    std::string out;
+    std::string err;
+    if (!cmSystemTools::RunSingleCommand(command, &out, &err, nullptr, nullptr,
+                                         cmSystemTools::OUTPUT_NONE,
+                                         cmDuration(30))) {
+      mf->IssueMessage(MessageType::FATAL_ERROR,
+                       cmStrCat("Running\n '", cmJoin(command, "' '"),
+                                "'\n"
+                                "failed with:\n ",
+                                err));
+      cmSystemTools::SetFatalErrorOccured();
+      return false;
+    }
+    cmsys::RegularExpression regex(
+      "Program Maintenance Utility Version ([1-9][0-9.]+)");
+    if (regex.find(err)) {
+      this->NMakeVersion = regex.match(1);
+      this->CheckNMakeFeatures();
+    }
+  }
+  return true;
+}
+
+void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures()
+{
+  this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare(
+    cmSystemTools::OP_LESS, this->NMakeVersion.c_str(), "9");
+}
+
 void cmGlobalNMakeMakefileGenerator::GetDocumentation(
   cmDocumentationEntry& entry)
 {

+ 6 - 1
Source/cmGlobalNMakeMakefileGenerator.h

@@ -31,7 +31,7 @@ public:
   /** Get encoding used by generator for makefile files */
   codecvt::Encoding GetMakefileEncoding() const override
   {
-    return codecvt::ANSI;
+    return this->NMakeSupportsUTF8 ? codecvt::UTF8_WITH_BOM : codecvt::ANSI;
   }
 
   /** Get the documentation entry for this generator.  */
@@ -55,6 +55,11 @@ protected:
   void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
 
 private:
+  bool NMakeSupportsUTF8 = false;
+  std::string NMakeVersion;
+  bool FindMakeProgram(cmMakefile* mf) override;
+  void CheckNMakeFeatures();
+
   void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
                            const char* envVar) const override;
 };

+ 2 - 1
Source/cmMakefileTargetGenerator.cxx

@@ -2058,7 +2058,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
   // Create the response file.
   std::string responseFileNameFull =
     cmStrCat(this->TargetBuildDirectoryFull, '/', name);
-  cmGeneratedFileStream responseStream(responseFileNameFull);
+  cmGeneratedFileStream responseStream(
+    responseFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
   responseStream.SetCopyIfDifferent(true);
   responseStream << options << "\n";
 

+ 1 - 0
Source/cm_codecvt.cxx

@@ -31,6 +31,7 @@ codecvt::codecvt(Encoding e)
     // We don't know which ANSI encoding to use for other platforms than
     // Windows so we don't do any conversion there
     case codecvt::UTF8:
+    case codecvt::UTF8_WITH_BOM:
     // Assume internal encoding is UTF-8
     case codecvt::None:
     // No encoding

+ 1 - 0
Source/cm_codecvt.hxx

@@ -14,6 +14,7 @@ public:
   {
     None,
     UTF8,
+    UTF8_WITH_BOM,
     ANSI
   };