diff options
author | Johnny Jazeix <jazeix@gmail.com> | 2020-10-13 21:48:12 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2020-10-14 16:08:07 (GMT) |
commit | f7a5f283188c1e51b0fb549f0a78afaf1d570383 (patch) | |
tree | c5fade762b9cada9b7fd9cf964528c43ccd45c80 | |
parent | 90b39a52090e6ba52424b441d5827b2b6e11ff56 (diff) | |
download | CMake-f7a5f283188c1e51b0fb549f0a78afaf1d570383.zip CMake-f7a5f283188c1e51b0fb549f0a78afaf1d570383.tar.gz CMake-f7a5f283188c1e51b0fb549f0a78afaf1d570383.tar.bz2 |
cmake: Fix '-E cat' command for binary files on Windows
Reset `std::cout` to write in binary mode with no encoding conversions.
Co-Author: Brad King <brad.king@kitware.com>
Fixes: #21295
-rw-r--r-- | Source/cmakemain.cxx | 13 | ||||
-rw-r--r-- | Source/cmcmd.cxx | 14 | ||||
-rw-r--r-- | Source/cmcmd.h | 6 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/.gitattributes | 2 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj | bin | 0 -> 124 bytes | |||
-rw-r--r-- | Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt | bin | 0 -> 248 bytes | |||
-rw-r--r-- | Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 3 |
7 files changed, 31 insertions, 7 deletions
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index eb44329..7e589c0 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -9,8 +9,10 @@ #include <cstring> #include <iostream> #include <string> +#include <utility> #include <vector> +#include <cm/memory> #include <cmext/algorithm> #include <cm3p/uv.h> @@ -107,13 +109,14 @@ const char* cmDocumentationOptions[][2] = { #endif -int do_command(int ac, char const* const* av) +int do_command(int ac, char const* const* av, + std::unique_ptr<cmConsoleBuf> consoleBuf) { std::vector<std::string> args; args.reserve(ac - 1); args.emplace_back(av[0]); cm::append(args, av + 2, av + ac); - return cmcmd::ExecuteCMakeCommand(args); + return cmcmd::ExecuteCMakeCommand(args, std::move(consoleBuf)); } cmMakefile* cmakemainGetMakefile(cmake* cm) @@ -687,8 +690,8 @@ int main(int ac, char const* const* av) cmSystemTools::EnsureStdPipes(); // Replace streambuf so we can output Unicode to console - cmConsoleBuf consoleBuf; - consoleBuf.SetUTF8Pipes(); + auto consoleBuf = cm::make_unique<cmConsoleBuf>(); + consoleBuf->SetUTF8Pipes(); cmsys::Encoding::CommandLineArguments args = cmsys::Encoding::CommandLineArguments::Main(ac, av); @@ -708,7 +711,7 @@ int main(int ac, char const* const* av) return do_open(ac, av); } if (strcmp(av[1], "-E") == 0) { - return do_command(ac, av); + return do_command(ac, av, std::move(consoleBuf)); } } int ret = do_cmake(ac, av); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 150fefd..a1fafcb 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -48,6 +48,12 @@ #include <sstream> #include <utility> +#ifdef _WIN32 +# include <fcntl.h> // for _O_BINARY +# include <io.h> // for _setmode +# include <stdio.h> // for std{out,err} and fileno +#endif + #include <cm/string_view> #include "cmsys/Directory.hxx" @@ -178,6 +184,9 @@ static bool cmTarFilesFrom(std::string const& file, static void cmCatFile(const std::string& fileToAppend) { +#ifdef _WIN32 + _setmode(fileno(stdout), _O_BINARY); +#endif cmsys::ifstream source(fileToAppend.c_str(), (std::ios::binary | std::ios::in)); std::cout << source.rdbuf(); @@ -497,7 +506,8 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args) return ret; } -int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) +int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, + std::unique_ptr<cmConsoleBuf> consoleBuf) { // IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx if (args.size() > 1) { @@ -951,6 +961,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) cmSystemTools::Error(arg + ": no such file or directory (ignoring)"); return_value = 1; } else { + // Destroy console buffers to drop cout/cerr encoding transform. + consoleBuf.reset(); cmCatFile(arg); } } diff --git a/Source/cmcmd.h b/Source/cmcmd.h index 5b6c813..ffadd5a 100644 --- a/Source/cmcmd.h +++ b/Source/cmcmd.h @@ -5,11 +5,14 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <string> #include <vector> #include "cmCryptoHash.h" +class cmConsoleBuf; + class cmcmd { public: @@ -17,7 +20,8 @@ public: * Execute commands during the build process. Supports options such * as echo, remove file etc. */ - static int ExecuteCMakeCommand(std::vector<std::string> const&); + static int ExecuteCMakeCommand(std::vector<std::string> const&, + std::unique_ptr<cmConsoleBuf> consoleBuf); protected: static int HandleCoCompileCommands(std::vector<std::string> const& args); diff --git a/Tests/RunCMake/CommandLine/.gitattributes b/Tests/RunCMake/CommandLine/.gitattributes new file mode 100644 index 0000000..b0b0588 --- /dev/null +++ b/Tests/RunCMake/CommandLine/.gitattributes @@ -0,0 +1,2 @@ +E_cat_binary_files/binary.obj -text +E_cat_good_binary_cat-stdout.txt -text -whitespace diff --git a/Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj b/Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj Binary files differnew file mode 100644 index 0000000..73f1749 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj diff --git a/Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt b/Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt Binary files differnew file mode 100644 index 0000000..0951d85 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 973391d..abb9050 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -498,6 +498,9 @@ run_cmake_command(E_cat_good_cat ${CMAKE_COMMAND} -E cat "${out}/first_file.txt" "${out}/second_file.txt" "${out}/unicode_file.txt") unset(out) +run_cmake_command(E_cat_good_binary_cat + ${CMAKE_COMMAND} -E cat "${RunCMake_SOURCE_DIR}/E_cat_binary_files/binary.obj" "${RunCMake_SOURCE_DIR}/E_cat_binary_files/binary.obj") + run_cmake_command(E_env-no-command0 ${CMAKE_COMMAND} -E env) run_cmake_command(E_env-no-command1 ${CMAKE_COMMAND} -E env TEST_ENV=1) run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1) |