This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake".
The branch, next has been updated via 8bc1788a12d60261a957b98254694c4a776ce62a (commit) via 0a8182399db73fc85a98802faae8e534e4d22767 (commit) from bf26fa0d1e1eea567b656366e0510e9018b530cd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8bc1788a12d60261a957b98254694c4a776ce62a commit 8bc1788a12d60261a957b98254694c4a776ce62a Merge: bf26fa0 0a81823 Author: Brad King <brad.k...@kitware.com> AuthorDate: Tue Aug 16 14:08:29 2016 -0400 Commit: CMake Topic Stage <kwro...@kitware.com> CommitDate: Tue Aug 16 14:08:29 2016 -0400 Merge topic 'process-output-encoding' into next 0a818239 Windows: Encode child process output to internally-used encoding https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0a8182399db73fc85a98802faae8e534e4d22767 commit 0a8182399db73fc85a98802faae8e534e4d22767 Author: Dāvis Mosāns <davis...@gmail.com> AuthorDate: Mon Aug 15 23:34:21 2016 +0300 Commit: Brad King <brad.k...@kitware.com> CommitDate: Tue Aug 16 13:59:17 2016 -0400 Windows: Encode child process output to internally-used encoding Typically Windows applications (eg. MSVC compiler) use current console's codepage for output to pipes so we need to encode that to our internally-used encoding (`KWSYS_ENCODING_DEFAULT_CODEPAGE`). diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index cdc8fb1..580c3eb 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -317,6 +317,8 @@ set(SRCS cmOrderDirectories.h cmPolicies.h cmPolicies.cxx + cmProcessOutput.cxx + cmProcessOutput.hxx cmProcessTools.cxx cmProcessTools.h cmProperty.cxx @@ -375,6 +377,9 @@ set(SRCS cm_utf8.c ) +SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS + KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) + set(COMMAND_INCLUDES "#include \"cmTargetPropCommandBase.cxx\"\n") list(APPEND SRCS cmTargetPropCommandBase.cxx) set_property(SOURCE cmTargetPropCommandBase.cxx PROPERTY HEADER_FILE_ONLY ON) diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index 58bbc31..4391a19 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -11,6 +11,7 @@ ============================================================================*/ #include "cmExecProgramCommand.h" +#include "cmProcessOutput.hxx" #include "cmSystemTools.h" #include <cmsys/Process.h> @@ -219,6 +220,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, int length; char* data; int p; + cmProcessOutput processOutput; while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { if (p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) { if (verbose) { @@ -230,6 +232,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, // All output has been read. Wait for the process to exit. cmsysProcess_WaitForExit(cp, CM_NULLPTR); + processOutput.DecodeText(output, output); // Check the result of running the process. std::string msg; diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index d97b25f..1ffb163 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -11,6 +11,7 @@ ============================================================================*/ #include "cmExecuteProcessCommand.h" +#include "cmProcessOutput.hxx" #include "cmSystemTools.h" #include <cmsys/Process.h> @@ -228,17 +229,21 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, int length; char* data; int p; + cmProcessOutput processOutput; + std::string strdata; while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { // Put the output in the right place. if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) { if (output_variable.empty()) { - cmSystemTools::Stdout(data, length); + processOutput.DecodeText(data, length, strdata, 1); + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); } else { cmExecuteProcessCommandAppend(tempOutput, data, length); } } else if (p == cmsysProcess_Pipe_STDERR && !error_quiet) { if (error_variable.empty()) { - cmSystemTools::Stderr(data, length); + processOutput.DecodeText(data, length, strdata, 2); + cmSystemTools::Stderr(strdata.c_str(), strdata.size()); } else { cmExecuteProcessCommandAppend(tempError, data, length); } @@ -247,6 +252,8 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, // All output has been read. Wait for the process to exit. cmsysProcess_WaitForExit(cp, CM_NULLPTR); + processOutput.DecodeText(tempOutput, tempOutput); + processOutput.DecodeText(tempError, tempError); // Fix the text in the output strings. cmExecuteProcessCommandFixText(tempOutput, output_strip_trailing_whitespace); diff --git a/Source/cmProcessOutput.cxx b/Source/cmProcessOutput.cxx new file mode 100644 index 0000000..59101dd --- /dev/null +++ b/Source/cmProcessOutput.cxx @@ -0,0 +1,155 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2016 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmProcessOutput.hxx" + +#if defined(_WIN32) +#include <windows.h> +unsigned int cmProcessOutput::defaultCodepage = + KWSYS_ENCODING_DEFAULT_CODEPAGE; +#endif + +cmProcessOutput::cmProcessOutput(unsigned int maxSize) +{ +#if defined(_WIN32) + bufferSize = maxSize; + codepage = GetConsoleCP(); + if (!codepage) { + codepage = GetACP(); + } +#else + static_cast<void>(maxSize); +#endif +} + +cmProcessOutput::~cmProcessOutput() +{ +} + +bool cmProcessOutput::DecodeText(std::string raw, std::string& decoded, + size_t id) +{ + bool success = true; + decoded = raw; +#if defined(_WIN32) + if (id > 0) { + if (rawparts.size() < id) { + rawparts.reserve(id); + while (rawparts.size() < id) + rawparts.push_back(std::string()); + } + raw = rawparts[id - 1] + raw; + rawparts[id - 1].clear(); + decoded = raw; + } + if (raw.size() > 0 && codepage != defaultCodepage) { + success = false; + CPINFOEXW cpinfo; + if (id > 0 && raw.size() == bufferSize && + GetCPInfoExW(codepage, 0, &cpinfo) == 1 && cpinfo.MaxCharSize > 1) { + if (cpinfo.MaxCharSize == 2 && cpinfo.LeadByte[0] != 0) { + LPSTR prevChar = + CharPrevExA(codepage, raw.c_str(), raw.c_str() + raw.size(), 0); + bool isLeadByte = + (*(prevChar + 1) == 0) && IsDBCSLeadByteEx(codepage, *prevChar); + if (isLeadByte) { + rawparts[id - 1] += *(raw.end() - 1); + raw.resize(raw.size() - 1); + } + success = DoDecodeText(raw, decoded, NULL); + } else { + bool restoreDecoded = false; + std::string firstDecoded = decoded; + wchar_t lastChar = 0; + for (UINT i = 0; i < cpinfo.MaxCharSize; i++) { + success = DoDecodeText(raw, decoded, &lastChar); + if (success && lastChar != 0) { + if (i == 0) { + firstDecoded = decoded; + } + if (lastChar == cpinfo.UnicodeDefaultChar) { + restoreDecoded = true; + rawparts[id - 1] = *(raw.end() - 1) + rawparts[id - 1]; + raw.resize(raw.size() - 1); + } else { + restoreDecoded = false; + break; + } + } else { + break; + } + } + if (restoreDecoded) { + decoded = firstDecoded; + rawparts[id - 1].clear(); + } + } + } else { + success = DoDecodeText(raw, decoded, NULL); + } + } +#else + static_cast<void>(id); +#endif + return success; +} + +bool cmProcessOutput::DecodeText(const char* data, size_t length, + std::string& decoded, size_t id) +{ + return DecodeText(std::string(data, length), decoded, id); +} + +bool cmProcessOutput::DecodeText(std::vector<char> raw, + std::vector<char>& decoded, size_t id) +{ + std::string str; + const bool success = + DecodeText(std::string(raw.begin(), raw.end()), str, id); + decoded.assign(str.begin(), str.end()); + return success; +} + +#if defined(_WIN32) +bool cmProcessOutput::DoDecodeText(std::string raw, std::string& decoded, + wchar_t* lastChar) +{ + bool success = false; + const int wlength = + MultiByteToWideChar(codepage, 0, raw.c_str(), int(raw.size()), NULL, 0); + wchar_t* wdata = new wchar_t[wlength]; + int r = MultiByteToWideChar(codepage, 0, raw.c_str(), int(raw.size()), wdata, + wlength); + if (r > 0) { + if (lastChar) { + *lastChar = 0; + if ((wlength >= 2 && wdata[wlength - 2] != wdata[wlength - 1]) || + wlength >= 1) { + *lastChar = wdata[wlength - 1]; + } + } + int length = WideCharToMultiByte(defaultCodepage, 0, wdata, wlength, NULL, + 0, NULL, NULL); + char* data = new char[length + 1]; + r = WideCharToMultiByte(defaultCodepage, 0, wdata, wlength, data, length, + NULL, NULL); + if (r > 0) { + data[length] = '\0'; + decoded = data; + success = true; + } + delete[] data; + } + delete[] wdata; + return success; +} +#endif diff --git a/Source/cmProcessOutput.hxx b/Source/cmProcessOutput.hxx new file mode 100644 index 0000000..c896720 --- /dev/null +++ b/Source/cmProcessOutput.hxx @@ -0,0 +1,42 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2016 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmProcessOutput_hxx +#define cmProcessOutput_hxx + +#include "cmStandardIncludes.h" + +#include <string> +#include <vector> + +class cmProcessOutput +{ +public: + static unsigned int defaultCodepage; + // must match to KWSYSPE_PIPE_BUFFER_SIZE + cmProcessOutput(unsigned int maxSize = 1024); + ~cmProcessOutput(); + bool DecodeText(std::string raw, std::string& decoded, size_t id = 0); + bool DecodeText(const char* data, size_t length, std::string& decoded, + size_t id = 0); + bool DecodeText(std::vector<char> raw, std::vector<char>& decoded, + size_t id = 0); + +private: + unsigned int codepage; + unsigned int bufferSize; + std::vector<std::string> rawparts; +#if defined(_WIN32) + bool DoDecodeText(std::string raw, std::string& decoded, wchar_t* lastChar); +#endif +}; + +#endif diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx index 34b8df2..396d4b9 100644 --- a/Source/cmProcessTools.cxx +++ b/Source/cmProcessTools.cxx @@ -10,6 +10,7 @@ See the License for more information. ============================================================================*/ #include "cmProcessTools.h" +#include "cmProcessOutput.hxx" #include <cmsys/Process.h> @@ -20,14 +21,18 @@ void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out, char* data = CM_NULLPTR; int length = 0; int p; + cmProcessOutput processOutput; + std::string strdata; while ((out || err) && (p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { if (out && p == cmsysProcess_Pipe_STDOUT) { - if (!out->Process(data, length)) { + processOutput.DecodeText(data, length, strdata, 1); + if (!out->Process(strdata.c_str(), int(strdata.size()))) { out = CM_NULLPTR; } } else if (err && p == cmsysProcess_Pipe_STDERR) { - if (!err->Process(data, length)) { + processOutput.DecodeText(data, length, strdata, 2); + if (!err->Process(strdata.c_str(), int(strdata.size()))) { err = CM_NULLPTR; } } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 5745a01..fcf0945 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -21,6 +21,7 @@ #ifdef __QNX__ #include <malloc.h> /* for malloc/free on QNX */ #endif +#include "cmProcessOutput.hxx" #include <cmsys/Directory.hxx> #include <cmsys/Encoding.hxx> #include <cmsys/Glob.hxx> @@ -612,6 +613,8 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, char* data; int length; int pipe; + cmProcessOutput processOutput; + std::string strdata; if (outputflag != OUTPUT_PASSTHROUGH && (captureStdOut || captureStdErr || outputflag != OUTPUT_NONE)) { while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) > @@ -627,14 +630,16 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, if (pipe == cmsysProcess_Pipe_STDOUT) { if (outputflag != OUTPUT_NONE) { - cmSystemTools::Stdout(data, length); + processOutput.DecodeText(data, length, strdata, 1); + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); } if (captureStdOut) { tempStdOut.insert(tempStdOut.end(), data, data + length); } } else if (pipe == cmsysProcess_Pipe_STDERR) { if (outputflag != OUTPUT_NONE) { - cmSystemTools::Stderr(data, length); + processOutput.DecodeText(data, length, strdata, 2); + cmSystemTools::Stderr(strdata.c_str(), strdata.size()); } if (captureStdErr) { tempStdErr.insert(tempStdErr.end(), data, data + length); @@ -646,9 +651,11 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, cmsysProcess_WaitForExit(cp, CM_NULLPTR); if (captureStdOut) { captureStdOut->assign(tempStdOut.begin(), tempStdOut.end()); + processOutput.DecodeText(*captureStdOut, *captureStdOut); } if (captureStdErr) { captureStdErr->assign(tempStdErr.begin(), tempStdErr.end()); + processOutput.DecodeText(*captureStdErr, *captureStdErr); } bool result = true; diff --git a/bootstrap b/bootstrap index 742fa2b..3402c9d 100755 --- a/bootstrap +++ b/bootstrap @@ -328,6 +328,7 @@ CMAKE_CXX_SOURCES="\ cmExprLexer \ cmExprParser \ cmExprParserHelper \ + cmProcessOutput \ " if ${cmake_system_mingw}; then @@ -1343,6 +1344,7 @@ fi cmake_c_flags_String="-DKWSYS_STRING_C" if ${cmake_system_mingw}; then cmake_c_flags_EncodingC="-DKWSYS_ENCODING_DEFAULT_CODEPAGE=CP_ACP" + cmake_cxx_flags_cmProcessOutput="${cmake_c_flags_EncodingC}" fi cmake_cxx_flags_SystemTools=" -DKWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} @@ -1359,8 +1361,9 @@ echo "cmake: ${objs}" > "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_cxx_compiler} ${cmake_ld_flags} ${cmake_cxx_flags} ${objs} -o cmake" >> "${cmake_bootstrap_dir}/Makefile" for a in ${CMAKE_CXX_SOURCES}; do src=`cmake_escape "${cmake_source_dir}/Source/${a}.cxx"` + src_flags=`eval echo \\${cmake_cxx_flags_\${a}}` echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" + echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} ${src_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done echo "cmBootstrapCommands1.o : $cmBootstrapCommands1Deps" >> "${cmake_bootstrap_dir}/Makefile" echo "cmBootstrapCommands2.o : $cmBootstrapCommands2Deps" >> "${cmake_bootstrap_dir}/Makefile" ----------------------------------------------------------------------- Summary of changes: Source/CMakeLists.txt | 5 ++ Source/cmExecProgramCommand.cxx | 3 + Source/cmExecuteProcessCommand.cxx | 11 ++- Source/cmProcessOutput.cxx | 155 ++++++++++++++++++++++++++++++++++++ Source/cmProcessOutput.hxx | 42 ++++++++++ Source/cmProcessTools.cxx | 9 ++- Source/cmSystemTools.cxx | 11 ++- bootstrap | 5 +- 8 files changed, 234 insertions(+), 7 deletions(-) create mode 100644 Source/cmProcessOutput.cxx create mode 100644 Source/cmProcessOutput.hxx hooks/post-receive -- CMake _______________________________________________ Cmake-commits mailing list Cmake-commits@cmake.org http://public.kitware.com/mailman/listinfo/cmake-commits