diff options
author | Daniel Mensinger <daniel@mensinger-ka.de> | 2019-11-30 11:48:26 (GMT) |
---|---|---|
committer | Daniel Mensinger <daniel@mensinger-ka.de> | 2019-12-23 13:05:36 (GMT) |
commit | 482497e0debc3de9f125c8c849a40872971a4a7e (patch) | |
tree | 2ae4aefba1e626668e411c53399cc241662e18d7 /Source | |
parent | 10fea25139cc302ef0f0a41aa68b44cda72a4fd2 (diff) | |
download | CMake-482497e0debc3de9f125c8c849a40872971a4a7e.zip CMake-482497e0debc3de9f125c8c849a40872971a4a7e.tar.gz CMake-482497e0debc3de9f125c8c849a40872971a4a7e.tar.bz2 |
trace: Add JSON output format
Add a new `--trace-format=` flag, to enable the new JSON trace
output format. This new format is easier to parse by machines
than the existing format. This new format also removes the
ambiguity of the whitespace in the "old" format (e.g. is that
whitespace part of a file path, or does it seperate arguments)
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmMakefile.cxx | 47 | ||||
-rw-r--r-- | Source/cmake.cxx | 73 | ||||
-rw-r--r-- | Source/cmake.h | 17 | ||||
-rw-r--r-- | Source/cmakemain.cxx | 1 |
4 files changed, 129 insertions, 9 deletions
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 75f00fc..eff7ddc 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -7,6 +7,7 @@ #include <algorithm> #include <cassert> #include <cctype> +#include <cstdint> #include <cstdio> #include <cstdlib> #include <cstring> @@ -20,6 +21,8 @@ #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" #include "cm_sys_stat.h" #include "cmAlgorithms.h" @@ -315,21 +318,51 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const } std::ostringstream msg; - msg << full_path << "(" << lff.Line << "): "; - msg << lff.Name.Original << "("; - bool expand = this->GetCMakeInstance()->GetTraceExpand(); + std::vector<std::string> args; std::string temp; + bool expand = this->GetCMakeInstance()->GetTraceExpand(); + + args.reserve(lff.Arguments.size()); for (cmListFileArgument const& arg : lff.Arguments) { if (expand) { temp = arg.Value; this->ExpandVariablesInString(temp); - msg << temp; + args.push_back(temp); } else { - msg << arg.Value; + args.push_back(arg.Value); + } + } + + switch (this->GetCMakeInstance()->GetTraceFormat()) { + case cmake::TraceFormat::TRACE_JSON_V1: { +#ifndef CMAKE_BOOTSTRAP + Json::Value val; + Json::StreamWriterBuilder builder; + builder["indentation"] = ""; + val["file"] = full_path; + val["line"] = static_cast<std::int64_t>(lff.Line); + val["cmd"] = lff.Name.Original; + val["args"] = Json::Value(Json::arrayValue); + for (std::string const& arg : args) { + val["args"].append(arg); + } + msg << Json::writeString(builder, val); +#endif + break; } - msg << " "; + case cmake::TraceFormat::TRACE_HUMAN: + msg << full_path << "(" << lff.Line << "): "; + msg << lff.Name.Original << "("; + + for (std::string const& arg : args) { + msg << arg << " "; + } + msg << ")"; + break; + case cmake::TraceFormat::TRACE_UNDEFINED: + msg << "INTERNAL ERROR: Trace format is TRACE_UNDEFINED"; + break; } - msg << ")"; auto& f = this->GetCMakeInstance()->GetTraceFile(); if (f) { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index fdb3687..b1300c9 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -755,6 +755,15 @@ void cmake::SetArgs(const std::vector<std::string>& args) std::cout << "Running with expanded trace output on.\n"; this->SetTrace(true); this->SetTraceExpand(true); + } else if (arg.find("--trace-format=", 0) == 0) { + this->SetTrace(true); + const auto traceFormat = + StringToTraceFormat(arg.substr(strlen("--trace-format="))); + if (traceFormat == TraceFormat::TRACE_UNDEFINED) { + cmSystemTools::Error("Invalid format specified for --trace-format"); + return; + } + this->SetTraceFormat(traceFormat); } else if (arg.find("--trace-source=", 0) == 0) { std::string file = arg.substr(strlen("--trace-source=")); cmSystemTools::ConvertToUnixSlashes(file); @@ -895,6 +904,23 @@ cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr) return (it != levels.cend()) ? it->second : LogLevel::LOG_UNDEFINED; } +cmake::TraceFormat cmake::StringToTraceFormat(const std::string& traceStr) +{ + using TracePair = std::pair<std::string, TraceFormat>; + static const std::vector<TracePair> levels = { + { "human", TraceFormat::TRACE_HUMAN }, + { "json-v1", TraceFormat::TRACE_JSON_V1 }, + }; + + const auto traceStrLowCase = cmSystemTools::LowerCase(traceStr); + + const auto it = std::find_if(levels.cbegin(), levels.cend(), + [&traceStrLowCase](const TracePair& p) { + return p.first == traceStrLowCase; + }); + return (it != levels.cend()) ? it->second : TraceFormat::TRACE_UNDEFINED; +} + void cmake::SetTraceFile(const std::string& file) { this->TraceFile.close(); @@ -909,6 +935,48 @@ void cmake::SetTraceFile(const std::string& file) std::cout << "Trace will be written to " << file << "\n"; } +void cmake::PrintTraceFormatVersion() +{ + if (!this->GetTrace()) { + return; + } + + std::string msg; + + switch (this->GetTraceFormat()) { + case TraceFormat::TRACE_JSON_V1: { +#ifndef CMAKE_BOOTSTRAP + Json::Value val; + Json::Value version; + Json::StreamWriterBuilder builder; + builder["indentation"] = ""; + version["major"] = 1; + version["minor"] = 0; + val["version"] = version; + msg = Json::writeString(builder, val); +#endif + break; + } + case TraceFormat::TRACE_HUMAN: + msg = ""; + break; + case TraceFormat::TRACE_UNDEFINED: + msg = "INTERNAL ERROR: Trace format is TRACE_UNDEFINED"; + break; + } + + if (msg.empty()) { + return; + } + + auto& f = this->GetTraceFile(); + if (f) { + f << msg << '\n'; + } else { + cmSystemTools::Message(msg); + } +} + void cmake::SetDirectoriesFromFile(const std::string& arg) { // Check if the argument refers to a CMakeCache.txt or @@ -1701,6 +1769,11 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) return -1; } + // Log the trace format version to the desired output + if (this->GetTrace()) { + this->PrintTraceFormatVersion(); + } + // If we are given a stamp list file check if it is really out of date. if (!this->CheckStampList.empty() && cmakeCheckStampList(this->CheckStampList)) { diff --git a/Source/cmake.h b/Source/cmake.h index 02de4c1..54fdc03 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -113,6 +113,14 @@ public: LOG_TRACE }; + /** \brief Define supported trace formats **/ + enum TraceFormat + { + TRACE_UNDEFINED, + TRACE_HUMAN, + TRACE_JSON_V1, + }; + struct GeneratorInfo { std::string name; @@ -389,6 +397,7 @@ public: LogLevel GetLogLevel() const { return this->MessageLogLevel; } void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; } static LogLevel StringToLogLevel(const std::string& levelStr); + static TraceFormat StringToTraceFormat(const std::string& levelStr); bool HasCheckInProgress() const { @@ -418,10 +427,12 @@ public: void SetShowLogContext(bool b) { this->LogContext = b; } //! Do we want trace output during the cmake run. - bool GetTrace() { return this->Trace; } + bool GetTrace() const { return this->Trace; } void SetTrace(bool b) { this->Trace = b; } - bool GetTraceExpand() { return this->TraceExpand; } + bool GetTraceExpand() const { return this->TraceExpand; } void SetTraceExpand(bool b) { this->TraceExpand = b; } + TraceFormat GetTraceFormat() const { return this->TraceFormatVar; } + void SetTraceFormat(TraceFormat f) { this->TraceFormatVar = f; } void AddTraceSource(std::string const& file) { this->TraceOnlyThisSources.push_back(file); @@ -432,6 +443,7 @@ public: } cmGeneratedFileStream& GetTraceFile() { return this->TraceFile; } void SetTraceFile(std::string const& file); + void PrintTraceFormatVersion(); bool GetWarnUninitialized() { return this->WarnUninitialized; } void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; } @@ -579,6 +591,7 @@ private: bool DebugOutput = false; bool Trace = false; bool TraceExpand = false; + TraceFormat TraceFormatVar = TRACE_HUMAN; cmGeneratedFileStream TraceFile; bool WarnUninitialized = false; bool WarnUnused = false; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 0fc39ba..9dd8831 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -81,6 +81,7 @@ const char* cmDocumentationOptions[][2] = { { "--debug-output", "Put cmake in a debug mode." }, { "--trace", "Put cmake in trace mode." }, { "--trace-expand", "Put cmake in trace mode with variable expansion." }, + { "--trace-format=<human|json-v1>", "Set the output format of the trace." }, { "--trace-source=<file>", "Trace only this CMake file/module. Multiple options allowed." }, { "--trace-redirect=<file>", |