From 8a4f536be664c0ef6d79c2bf7fd547355ae59c81 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 28 Apr 2021 12:51:05 -0400 Subject: NMake: Detect nmake version Run `nmake -?` and extract the version from its output. Use a timeout because Watcom tools come with a `nmake` tool that always waits for user input on `-?`. --- Source/cmGlobalNMakeMakefileGenerator.cxx | 34 +++++++++++++++++++++++++++++++ Source/cmGlobalNMakeMakefileGenerator.h | 3 +++ 2 files changed, 37 insertions(+) diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 36f583f..cbcd4b3 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/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,37 @@ 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 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); + } + } + return true; +} + void cmGlobalNMakeMakefileGenerator::GetDocumentation( cmDocumentationEntry& entry) { diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index abe64ff..c23eef8 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -55,6 +55,9 @@ protected: void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override; private: + std::string NMakeVersion; + bool FindMakeProgram(cmMakefile* mf) override; + void PrintCompilerAdvice(std::ostream& os, std::string const& lang, const char* envVar) const override; }; -- cgit v0.12 From 186c9bff5342c1e8e73fce9cf361b6de5dda3f28 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 28 Apr 2021 13:14:31 -0400 Subject: NMake: Check nmake version for support of UTF-8 NMake version 9 and above support UTF-8 encoded makefiles with a BOM. --- Source/cmGlobalNMakeMakefileGenerator.cxx | 7 +++++++ Source/cmGlobalNMakeMakefileGenerator.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index cbcd4b3..313f39b 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -63,11 +63,18 @@ bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf) "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) { diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index c23eef8..ed52378 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -55,8 +55,10 @@ 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; -- cgit v0.12 From f3f57cc4edd528aaf0b8d8633d5f9990f0d804af Mon Sep 17 00:00:00 2001 From: Amine Najahi Date: Thu, 22 Apr 2021 20:26:30 +0100 Subject: NMake: Use UTF-8 with BOM if supported by nmake Fixes: #21792 --- Help/release/dev/nmake-utf8.rst | 5 +++++ Source/cmGeneratedFileStream.cxx | 5 +++++ Source/cmGlobalNMakeMakefileGenerator.h | 2 +- Source/cmMakefileTargetGenerator.cxx | 3 ++- Source/cm_codecvt.cxx | 1 + Source/cm_codecvt.hxx | 1 + 6 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 Help/release/dev/nmake-utf8.rst diff --git a/Help/release/dev/nmake-utf8.rst b/Help/release/dev/nmake-utf8.rst new file mode 100644 index 0000000..ebbb45b --- /dev/null +++ b/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. diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 43f384a..06778b1 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -42,6 +42,11 @@ cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name, #else static_cast(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() diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index ed52378..402b89f 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/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. */ diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index fa469ed..5b6c58d 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/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"; diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx index 15f83e0..216d3f0 100644 --- a/Source/cm_codecvt.cxx +++ b/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 diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx index 1860211..b73204f 100644 --- a/Source/cm_codecvt.hxx +++ b/Source/cm_codecvt.hxx @@ -14,6 +14,7 @@ public: { None, UTF8, + UTF8_WITH_BOM, ANSI }; -- cgit v0.12