forked from OSchip/llvm-project
Support -color-diagnostics={auto,always,never}.
-color-diagnostics=auto is default because that's the same as Clang's default. When color is enabled, error or warning messages are colored like this. error: <bold>ld.lld</bold> <red>error:</red> foo.o: no such file warning: <bold>ld.lld</bold> <magenta>warning:</magenta> foo.o: no such file Differential Revision: https://reviews.llvm.org/D27117 llvm-svn: 287949
This commit is contained in:
parent
6066641423
commit
8c8818a58c
|
@ -34,6 +34,9 @@ enum ELFKind {
|
||||||
// For --build-id.
|
// For --build-id.
|
||||||
enum class BuildIdKind { None, Fast, Md5, Sha1, Hexstring, Uuid };
|
enum class BuildIdKind { None, Fast, Md5, Sha1, Hexstring, Uuid };
|
||||||
|
|
||||||
|
// For --color-diagnostics.
|
||||||
|
enum class ColorPolicy { Auto, Always, Never };
|
||||||
|
|
||||||
// For --discard-{all,locals,none}.
|
// For --discard-{all,locals,none}.
|
||||||
enum class DiscardPolicy { Default, All, Locals, None };
|
enum class DiscardPolicy { Default, All, Locals, None };
|
||||||
|
|
||||||
|
@ -135,6 +138,7 @@ struct Configuration {
|
||||||
bool ZRelro;
|
bool ZRelro;
|
||||||
bool ExitEarly;
|
bool ExitEarly;
|
||||||
bool ZWxneeded;
|
bool ZWxneeded;
|
||||||
|
ColorPolicy ColorDiagnostics = ColorPolicy::Auto;
|
||||||
DiscardPolicy Discard;
|
DiscardPolicy Discard;
|
||||||
SortSectionPolicy SortSection;
|
SortSectionPolicy SortSection;
|
||||||
StripPolicy Strip = StripPolicy::None;
|
StripPolicy Strip = StripPolicy::None;
|
||||||
|
|
|
@ -392,6 +392,24 @@ static bool getArg(opt::InputArgList &Args, unsigned K1, unsigned K2,
|
||||||
return Default;
|
return Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse -color-diagnostics={auto,always,never} or -no-color-diagnostics.
|
||||||
|
static ColorPolicy getColorDiagnostics(opt::InputArgList &Args) {
|
||||||
|
auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_no_color_diagnostics);
|
||||||
|
if (!Arg)
|
||||||
|
return ColorPolicy::Auto;
|
||||||
|
if (Arg->getOption().getID() == OPT_no_color_diagnostics)
|
||||||
|
return ColorPolicy::Never;
|
||||||
|
|
||||||
|
StringRef S = Arg->getValue();
|
||||||
|
if (S == "auto")
|
||||||
|
return ColorPolicy::Auto;
|
||||||
|
if (S == "always")
|
||||||
|
return ColorPolicy::Always;
|
||||||
|
if (S != "never")
|
||||||
|
error("unknown -color-diagnostics value: " + S);
|
||||||
|
return ColorPolicy::Never;
|
||||||
|
}
|
||||||
|
|
||||||
static DiscardPolicy getDiscardOption(opt::InputArgList &Args) {
|
static DiscardPolicy getDiscardOption(opt::InputArgList &Args) {
|
||||||
auto *Arg =
|
auto *Arg =
|
||||||
Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none);
|
Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none);
|
||||||
|
@ -486,6 +504,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
|
||||||
Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
|
Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
|
||||||
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
|
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
|
||||||
Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
|
Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
|
||||||
|
Config->ColorDiagnostics = getColorDiagnostics(Args);
|
||||||
Config->Demangle = getArg(Args, OPT_demangle, OPT_no_demangle, true);
|
Config->Demangle = getArg(Args, OPT_demangle, OPT_no_demangle, true);
|
||||||
Config->DisableVerify = Args.hasArg(OPT_disable_verify);
|
Config->DisableVerify = Args.hasArg(OPT_disable_verify);
|
||||||
Config->Discard = getDiscardOption(Args);
|
Config->Discard = getDiscardOption(Args);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
|
#include "llvm/Support/Process.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace lld::elf;
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace lld {
|
namespace lld {
|
||||||
|
@ -32,6 +34,26 @@ StringRef elf::Argv0;
|
||||||
// but outs() or errs() are not thread-safe. We protect them using a mutex.
|
// but outs() or errs() are not thread-safe. We protect them using a mutex.
|
||||||
static std::mutex Mu;
|
static std::mutex Mu;
|
||||||
|
|
||||||
|
static bool useColor() {
|
||||||
|
if (Config->ColorDiagnostics == ColorPolicy::Always)
|
||||||
|
return true;
|
||||||
|
if (Config->ColorDiagnostics == ColorPolicy::Never)
|
||||||
|
return false;
|
||||||
|
return ErrorOS == &errs() && sys::Process::StandardErrHasColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print(StringRef S, raw_ostream::Colors C) {
|
||||||
|
if (useColor()) {
|
||||||
|
ErrorOS->changeColor(raw_ostream::WHITE, /*Bold=*/true);
|
||||||
|
*ErrorOS << Argv0 + ": ";
|
||||||
|
ErrorOS->changeColor(C, true);
|
||||||
|
*ErrorOS << S;
|
||||||
|
ErrorOS->resetColor();
|
||||||
|
} else {
|
||||||
|
*ErrorOS << Argv0 + ": " << S;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void elf::log(const Twine &Msg) {
|
void elf::log(const Twine &Msg) {
|
||||||
std::lock_guard<std::mutex> Lock(Mu);
|
std::lock_guard<std::mutex> Lock(Mu);
|
||||||
if (Config->Verbose)
|
if (Config->Verbose)
|
||||||
|
@ -44,16 +66,19 @@ void elf::warn(const Twine &Msg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> Lock(Mu);
|
std::lock_guard<std::mutex> Lock(Mu);
|
||||||
*ErrorOS << Argv0 << ": warning: " << Msg << "\n";
|
print("warning: ", raw_ostream::MAGENTA);
|
||||||
|
*ErrorOS << Msg << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void elf::error(const Twine &Msg) {
|
void elf::error(const Twine &Msg) {
|
||||||
std::lock_guard<std::mutex> Lock(Mu);
|
std::lock_guard<std::mutex> Lock(Mu);
|
||||||
|
|
||||||
if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) {
|
if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) {
|
||||||
*ErrorOS << Argv0 << ": error: " << Msg << "\n";
|
print("error: ", raw_ostream::RED);
|
||||||
|
*ErrorOS << Msg << "\n";
|
||||||
} else if (ErrorCount == Config->ErrorLimit) {
|
} else if (ErrorCount == Config->ErrorLimit) {
|
||||||
*ErrorOS << Argv0 << ": error: too many errors emitted, stopping now"
|
print("error: ", raw_ostream::RED);
|
||||||
|
*ErrorOS << "too many errors emitted, stopping now"
|
||||||
<< " (use -error-limit=0 to see all errors)\n";
|
<< " (use -error-limit=0 to see all errors)\n";
|
||||||
if (Config->ExitEarly)
|
if (Config->ExitEarly)
|
||||||
exitLld(1);
|
exitLld(1);
|
||||||
|
@ -79,7 +104,8 @@ void elf::exitLld(int Val) {
|
||||||
|
|
||||||
void elf::fatal(const Twine &Msg) {
|
void elf::fatal(const Twine &Msg) {
|
||||||
std::lock_guard<std::mutex> Lock(Mu);
|
std::lock_guard<std::mutex> Lock(Mu);
|
||||||
*ErrorOS << Argv0 << ": error: " << Msg << "\n";
|
print("error: ", raw_ostream::RED);
|
||||||
|
*ErrorOS << Msg << "\n";
|
||||||
exitLld(1);
|
exitLld(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,9 @@ def allow_multiple_definition: F<"allow-multiple-definition">,
|
||||||
def as_needed: F<"as-needed">,
|
def as_needed: F<"as-needed">,
|
||||||
HelpText<"Only set DT_NEEDED for shared libraries if used">;
|
HelpText<"Only set DT_NEEDED for shared libraries if used">;
|
||||||
|
|
||||||
|
def color_diagnostics: S<"color-diagnostics">,
|
||||||
|
HelpText<"Use colors in diagnostics">;
|
||||||
|
|
||||||
def disable_new_dtags: F<"disable-new-dtags">,
|
def disable_new_dtags: F<"disable-new-dtags">,
|
||||||
HelpText<"Disable new dynamic tags">;
|
HelpText<"Disable new dynamic tags">;
|
||||||
|
|
||||||
|
@ -121,6 +124,9 @@ def nostdlib: F<"nostdlib">,
|
||||||
def no_as_needed: F<"no-as-needed">,
|
def no_as_needed: F<"no-as-needed">,
|
||||||
HelpText<"Always DT_NEEDED for shared libraries">;
|
HelpText<"Always DT_NEEDED for shared libraries">;
|
||||||
|
|
||||||
|
def no_color_diagnostics: F<"no-color-diagnostics">,
|
||||||
|
HelpText<"Do not use colors in diagnostics">;
|
||||||
|
|
||||||
def no_demangle: F<"no-demangle">,
|
def no_demangle: F<"no-demangle">,
|
||||||
HelpText<"Do not demangle symbol names">;
|
HelpText<"Do not demangle symbol names">;
|
||||||
|
|
||||||
|
@ -238,6 +244,7 @@ def alias_Bstatic_dn: F<"dn">, Alias<Bstatic>;
|
||||||
def alias_Bstatic_non_shared: F<"non_shared">, Alias<Bstatic>;
|
def alias_Bstatic_non_shared: F<"non_shared">, Alias<Bstatic>;
|
||||||
def alias_Bstatic_static: F<"static">, Alias<Bstatic>;
|
def alias_Bstatic_static: F<"static">, Alias<Bstatic>;
|
||||||
def alias_L__library_path: J<"library-path=">, Alias<L>;
|
def alias_L__library_path: J<"library-path=">, Alias<L>;
|
||||||
|
def alias_color_diagnostics: J<"color-diagnostics=">, Alias<color_diagnostics>;
|
||||||
def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>;
|
def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>;
|
||||||
def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>;
|
def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>;
|
||||||
def alias_dynamic_list: J<"dynamic-list=">, Alias<dynamic_list>;
|
def alias_dynamic_list: J<"dynamic-list=">, Alias<dynamic_list>;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Windows command prompt doesn't support ANSI escape sequences.
|
||||||
|
# REQUIRES: shell
|
||||||
|
|
||||||
|
# RUN: not ld.lld -color-diagnostics=always /nosuchfile 2>&1 \
|
||||||
|
# RUN: | FileCheck -check-prefix=COLOR %s
|
||||||
|
|
||||||
|
# COLOR: {{^.\[0;1;37m.*/ld.lld: .\[0;1;31merror: .\[0mcannot open /nosuchfile}}
|
||||||
|
|
||||||
|
# RUN: not ld.lld -color-diagnostics=always -no-color-diagnostics /nosuchfile 2>&1 \
|
||||||
|
# RUN: | FileCheck -check-prefix=NOCOLOR %s
|
||||||
|
|
||||||
|
# NOCOLOR: ld.lld: error: cannot open /nosuchfile
|
Loading…
Reference in New Issue