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 644cdf712be93436cbd3401d72852f5d4bdb0e2a (commit) via 12924660b9881d24b60ff13da840d7312fa0486f (commit) from 2b7105307a5d47cf29bf03d1d1bcc21b16b476bd (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=644cdf712be93436cbd3401d72852f5d4bdb0e2a commit 644cdf712be93436cbd3401d72852f5d4bdb0e2a Merge: 2b71053 1292466 Author: Brad King <brad.k...@kitware.com> AuthorDate: Wed Aug 17 09:32:46 2016 -0400 Commit: CMake Topic Stage <kwro...@kitware.com> CommitDate: Wed Aug 17 09:32:46 2016 -0400 Merge topic 'process-output-encoding' into next 12924660 Windows: Encode child process output to internally-used encoding https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=12924660b9881d24b60ff13da840d7312fa0486f commit 12924660b9881d24b60ff13da840d7312fa0486f 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: Wed Aug 17 09:32:23 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..daffad1 --- /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: +#if defined(_WIN32) + unsigned int codepage; + unsigned int bufferSize; + std::vector<std::string> rawparts; + 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: hooks/post-receive -- CMake _______________________________________________ Cmake-commits mailing list Cmake-commits@cmake.org http://public.kitware.com/mailman/listinfo/cmake-commits