summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohnny Jazeix <jazeix@gmail.com>2020-10-13 21:48:12 (GMT)
committerBrad King <brad.king@kitware.com>2020-10-14 16:08:07 (GMT)
commitf7a5f283188c1e51b0fb549f0a78afaf1d570383 (patch)
treec5fade762b9cada9b7fd9cf964528c43ccd45c80
parent90b39a52090e6ba52424b441d5827b2b6e11ff56 (diff)
downloadCMake-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.cxx13
-rw-r--r--Source/cmcmd.cxx14
-rw-r--r--Source/cmcmd.h6
-rw-r--r--Tests/RunCMake/CommandLine/.gitattributes2
-rw-r--r--Tests/RunCMake/CommandLine/E_cat_binary_files/binary.objbin0 -> 124 bytes
-rw-r--r--Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txtbin0 -> 248 bytes
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake3
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
new file mode 100644
index 0000000..73f1749
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj
Binary files differ
diff --git a/Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt b/Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt
new file mode 100644
index 0000000..0951d85
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt
Binary files differ
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)