1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

StdIo: Replace uses of KWSys Terminal with StdIo::Print

The latter:

* uses a type-safe representation of text attributes,

* works with `StdIo::Console` to print arbitrary UTF-8 text in color, and

* writes VT100 sequences to Windows Consoles when supported, eliminating
  racy console text attribute changes in parallel `make` output.

Fixes: #22450, #26689, #26924
This commit is contained in:
Brad King
2025-05-08 09:41:45 -04:00
parent 329d755dbd
commit 509c424472
5 changed files with 44 additions and 44 deletions

View File

@@ -6,6 +6,7 @@
#include <cassert>
#include <cstdio>
#include <functional>
#include <iostream>
#include <utility>
#include <cm/memory>
@@ -16,7 +17,6 @@
#include <cmext/string_view>
#include "cmsys/FStream.hxx"
#include "cmsys/Terminal.h"
#include "cmCMakePath.h"
#include "cmCustomCommand.h" // IWYU pragma: keep
@@ -41,6 +41,8 @@
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStdIoStream.h"
#include "cmStdIoTerminal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTargetDepend.h"
@@ -1377,9 +1379,15 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
this->CheckMultipleOutputs(verbose);
auto echoColor = [color](std::string const& m) {
cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
cmsysTerminal_Color_ForegroundBold,
m.c_str(), true, color);
cm::StdIo::TermAttrSet attrs;
if (color) {
attrs = {
cm::StdIo::TermAttr::ForegroundMagenta,
cm::StdIo::TermAttr::ForegroundBold,
};
}
Print(cm::StdIo::Out(), attrs, m);
std::cout << std::endl;
};
std::string const targetDir = cmSystemTools::GetFilenamePath(tgtInfo);

View File

@@ -2,10 +2,10 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include "cmsys/Terminal.h"
#include "cmStdIoTerminal.h"
struct cmMessageMetadata
{
char const* title = nullptr;
int desiredColor = cmsysTerminal_Color_Normal;
cm::StdIo::TermAttrSet attrs = cm::StdIo::TermAttr::Normal;
};

View File

@@ -5,6 +5,7 @@
#include "cmDocumentationFormatter.h"
#include "cmMessageMetadata.h"
#include "cmMessageType.h"
#include "cmStdIoTerminal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -17,8 +18,6 @@
#include <sstream>
#include <utility>
#include "cmsys/Terminal.h"
#ifdef CMake_ENABLE_DEBUGGER
# include "cmDebuggerAdapter.h"
#endif
@@ -47,18 +46,18 @@ char const* getMessageTypeStr(MessageType t)
return "Warning";
}
int getMessageColor(MessageType t)
cm::StdIo::TermAttr getMessageColor(MessageType t)
{
switch (t) {
case MessageType::INTERNAL_ERROR:
case MessageType::FATAL_ERROR:
case MessageType::AUTHOR_ERROR:
return cmsysTerminal_Color_ForegroundRed;
return cm::StdIo::TermAttr::ForegroundRed;
case MessageType::AUTHOR_WARNING:
case MessageType::WARNING:
return cmsysTerminal_Color_ForegroundYellow;
return cm::StdIo::TermAttr::ForegroundYellow;
default:
return cmsysTerminal_Color_Normal;
return cm::StdIo::TermAttr::Normal;
}
}
@@ -99,7 +98,7 @@ void displayMessage(MessageType t, std::ostringstream& msg)
// Output the message.
cmMessageMetadata md;
md.desiredColor = getMessageColor(t);
md.attrs = getMessageColor(t);
if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
cmSystemTools::SetErrorOccurred();

View File

@@ -7,7 +7,6 @@
#include <cassert>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
@@ -34,6 +33,8 @@
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStdIoConsole.h"
#include "cmStdIoStream.h"
#include "cmStdIoTerminal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
@@ -46,7 +47,6 @@
#include "cmsys/Encoding.hxx"
#include "cmsys/RegularExpression.hxx"
#include "cmsys/Terminal.h"
namespace {
#ifndef CMAKE_BOOTSTRAP
@@ -174,20 +174,8 @@ std::string cmakemainGetStack(cmake* cm)
void cmakemainMessageCallback(std::string const& m,
cmMessageMetadata const& md, cmake* cm)
{
#if defined(_WIN32)
// FIXME: On Windows we replace cerr's streambuf with a custom
// implementation that converts our internal UTF-8 encoding to the
// console's encoding. It also does *not* replace LF with CRLF.
// Since stderr does not convert encoding and does convert LF, we
// cannot use it to print messages. Another implementation will
// be needed to print colored messages on Windows.
static_cast<void>(md);
std::cerr << m << cmakemainGetStack(cm) << std::endl;
#else
cmsysTerminal_cfprintf(md.desiredColor, stderr, "%s", m.c_str());
fflush(stderr); // stderr is buffered in some cases.
Print(cm::StdIo::Err(), md.attrs, m);
std::cerr << cmakemainGetStack(cm) << std::endl;
#endif
}
void cmakemainProgressCallback(std::string const& m, float prog, cmake* cm)

View File

@@ -3,6 +3,7 @@
#include "cmcmd.h"
#include <functional>
#include <iomanip>
#include <iterator>
#include <cm/optional>
@@ -26,6 +27,8 @@
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStdIoConsole.h"
#include "cmStdIoStream.h"
#include "cmStdIoTerminal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTransformDepfile.h"
@@ -73,7 +76,6 @@
#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
#include "cmsys/Terminal.h"
int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd);
@@ -1859,8 +1861,8 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num)
int fileNum =
static_cast<int>(cmsys::Directory::GetNumberOfFilesInDirectory(dirName));
if (count > 0) {
// print the progress
fprintf(stdout, "[%3i%%] ", ((fileNum - 3) * 100) / count);
int const percent = ((fileNum - 3) * 100) / count;
std::cout << '[' << std::setw(3) << percent << "%] ";
}
}
@@ -1871,7 +1873,8 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string> const& args)
// args[1] == cmake_echo_color
bool enabled = true;
int color = cmsysTerminal_Color_Normal;
static cm::StdIo::TermAttrSet const noAttrs;
cm::StdIo::TermAttrSet attrs = cm::StdIo::TermAttr::Normal;
bool newline = true;
std::string progressDir;
for (auto const& arg : cmMakeRange(args).advance(2)) {
@@ -1889,32 +1892,34 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string> const& args)
cmcmdProgressReport(progressDir, progressNum);
}
} else if (arg == "--normal") {
color = cmsysTerminal_Color_Normal;
attrs = cm::StdIo::TermAttr::Normal;
} else if (arg == "--black") {
color = cmsysTerminal_Color_ForegroundBlack;
attrs = cm::StdIo::TermAttr::ForegroundBlack;
} else if (arg == "--red") {
color = cmsysTerminal_Color_ForegroundRed;
attrs = cm::StdIo::TermAttr::ForegroundRed;
} else if (arg == "--green") {
color = cmsysTerminal_Color_ForegroundGreen;
attrs = cm::StdIo::TermAttr::ForegroundGreen;
} else if (arg == "--yellow") {
color = cmsysTerminal_Color_ForegroundYellow;
attrs = cm::StdIo::TermAttr::ForegroundYellow;
} else if (arg == "--blue") {
color = cmsysTerminal_Color_ForegroundBlue;
attrs = cm::StdIo::TermAttr::ForegroundBlue;
} else if (arg == "--magenta") {
color = cmsysTerminal_Color_ForegroundMagenta;
attrs = cm::StdIo::TermAttr::ForegroundMagenta;
} else if (arg == "--cyan") {
color = cmsysTerminal_Color_ForegroundCyan;
attrs = cm::StdIo::TermAttr::ForegroundCyan;
} else if (arg == "--white") {
color = cmsysTerminal_Color_ForegroundWhite;
attrs = cm::StdIo::TermAttr::ForegroundWhite;
} else if (arg == "--bold") {
color |= cmsysTerminal_Color_ForegroundBold;
attrs |= cm::StdIo::TermAttr::ForegroundBold;
} else if (arg == "--no-newline") {
newline = false;
} else if (arg == "--newline") {
newline = true;
} else {
// Color is enabled. Print with the current color.
cmSystemTools::MakefileColorEcho(color, arg.c_str(), newline, enabled);
Print(cm::StdIo::Out(), enabled ? attrs : noAttrs, arg);
if (newline) {
std::cout << std::endl;
}
}
}