diff options
-rw-r--r-- | Source/cmMakefile.cxx | 13 | ||||
-rw-r--r-- | Source/cmMakefileProfilingData.cxx | 60 | ||||
-rw-r--r-- | Source/cmMakefileProfilingData.h | 30 | ||||
-rw-r--r-- | Source/cmake.h | 15 |
4 files changed, 97 insertions, 21 deletions
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 90a38be..2091f27 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -375,19 +375,15 @@ public: ++this->Makefile->RecursionDepth; this->Makefile->ExecutionStatusStack.push_back(&status); #if !defined(CMAKE_BOOTSTRAP) - if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) { - this->Makefile->GetCMakeInstance()->GetProfilingOutput().StartEntry(lff, - lfc); - } + this->ProfilingDataRAII = + this->Makefile->GetCMakeInstance()->CreateProfilingEntry(lff, lfc); #endif } ~cmMakefileCall() { #if !defined(CMAKE_BOOTSTRAP) - if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) { - this->Makefile->GetCMakeInstance()->GetProfilingOutput().StopEntry(); - } + this->ProfilingDataRAII.reset(); #endif this->Makefile->ExecutionStatusStack.pop_back(); --this->Makefile->RecursionDepth; @@ -399,6 +395,9 @@ public: private: cmMakefile* Makefile; +#if !defined(CMAKE_BOOTSTRAP) + cm::optional<cmMakefileProfilingData::RAII> ProfilingDataRAII; +#endif }; void cmMakefile::OnExecuteCommand(std::function<void()> callback) diff --git a/Source/cmMakefileProfilingData.cxx b/Source/cmMakefileProfilingData.cxx index 1cd97c9..dc974b1 100644 --- a/Source/cmMakefileProfilingData.cxx +++ b/Source/cmMakefileProfilingData.cxx @@ -4,8 +4,12 @@ #include <chrono> #include <stdexcept> +#include <type_traits> +#include <utility> #include <vector> +#include <cm/utility> + #include <cm3p/json/value.h> #include <cm3p/json/writer.h> @@ -46,6 +50,23 @@ cmMakefileProfilingData::~cmMakefileProfilingData() noexcept void cmMakefileProfilingData::StartEntry(const cmListFileFunction& lff, cmListFileContext const& lfc) { + cm::optional<Json::Value> argsValue(cm::in_place, Json::objectValue); + if (!lff.Arguments().empty()) { + std::string args; + for (auto const& a : lff.Arguments()) { + args = cmStrCat(args, args.empty() ? "" : " ", a.Value); + } + (*argsValue)["functionArgs"] = args; + } + (*argsValue)["location"] = + cmStrCat(lfc.FilePath, ':', std::to_string(lfc.Line)); + this->StartEntry("cmake", lff.LowerCaseName(), std::move(argsValue)); +} + +void cmMakefileProfilingData::StartEntry(const std::string& category, + const std::string& name, + cm::optional<Json::Value> args) +{ /* Do not try again if we previously failed to write to output. */ if (!this->ProfileStream.good()) { return; @@ -58,24 +79,17 @@ void cmMakefileProfilingData::StartEntry(const cmListFileFunction& lff, cmsys::SystemInformation info; Json::Value v; v["ph"] = "B"; - v["name"] = lff.LowerCaseName(); - v["cat"] = "cmake"; + v["name"] = name; + v["cat"] = category; v["ts"] = static_cast<Json::Value::UInt64>( std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::steady_clock::now().time_since_epoch()) .count()); v["pid"] = static_cast<int>(info.GetProcessId()); v["tid"] = 0; - Json::Value argsValue; - if (!lff.Arguments().empty()) { - std::string args; - for (auto const& a : lff.Arguments()) { - args += (args.empty() ? "" : " ") + a.Value; - } - argsValue["functionArgs"] = args; + if (args) { + v["args"] = *std::move(args); } - argsValue["location"] = lfc.FilePath + ":" + std::to_string(lfc.Line); - v["args"] = argsValue; this->JsonWriter->write(v, &this->ProfileStream); } catch (std::ios_base::failure& fail) { @@ -112,3 +126,27 @@ void cmMakefileProfilingData::StopEntry() cmSystemTools::Error("Error writing profiling output!"); } } + +cmMakefileProfilingData::RAII::RAII(RAII&& other) noexcept + : Data(other.Data) +{ + other.Data = nullptr; +} + +cmMakefileProfilingData::RAII::~RAII() +{ + if (this->Data) { + this->Data->StopEntry(); + } +} + +cmMakefileProfilingData::RAII& cmMakefileProfilingData::RAII::operator=( + RAII&& other) noexcept +{ + if (this->Data) { + this->Data->StopEntry(); + } + this->Data = other.Data; + other.Data = nullptr; + return *this; +} diff --git a/Source/cmMakefileProfilingData.h b/Source/cmMakefileProfilingData.h index a86764a..e8d7dfa 100644 --- a/Source/cmMakefileProfilingData.h +++ b/Source/cmMakefileProfilingData.h @@ -3,6 +3,11 @@ #pragma once #include <memory> #include <string> +#include <utility> + +#include <cm/optional> + +#include <cm3p/json/value.h> // IWYU pragma: keep #include "cmsys/FStream.hxx" @@ -19,8 +24,33 @@ public: cmMakefileProfilingData(const std::string&); ~cmMakefileProfilingData() noexcept; void StartEntry(const cmListFileFunction& lff, cmListFileContext const& lfc); + void StartEntry(const std::string& category, const std::string& name, + cm::optional<Json::Value> args = cm::nullopt); void StopEntry(); + class RAII + { + public: + RAII() = delete; + RAII(const RAII&) = delete; + RAII(RAII&&) noexcept; + + template <typename... Args> + RAII(cmMakefileProfilingData& data, Args&&... args) + : Data(&data) + { + this->Data->StartEntry(std::forward<Args>(args)...); + } + + ~RAII(); + + RAII& operator=(const RAII&) = delete; + RAII& operator=(RAII&&) noexcept; + + private: + cmMakefileProfilingData* Data = nullptr; + }; + private: cmsys::ofstream ProfileStream; std::unique_ptr<Json::StreamWriter> JsonWriter; diff --git a/Source/cmake.h b/Source/cmake.h index 5b5425c..a9a8bf2 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -33,6 +33,7 @@ # include <cm3p/json/value.h> # include "cmCMakePresetsGraph.h" +# include "cmMakefileProfilingData.h" #endif class cmExternalMakefileProjectGeneratorFactory; @@ -41,9 +42,6 @@ class cmFileTimeCache; class cmGlobalGenerator; class cmGlobalGeneratorFactory; class cmMakefile; -#if !defined(CMAKE_BOOTSTRAP) -class cmMakefileProfilingData; -#endif class cmMessenger; class cmVariableWatch; struct cmBuildOptions; @@ -628,6 +626,17 @@ public: #if !defined(CMAKE_BOOTSTRAP) cmMakefileProfilingData& GetProfilingOutput(); bool IsProfilingEnabled() const; + + template <typename... Args> + cm::optional<cmMakefileProfilingData::RAII> CreateProfilingEntry( + Args&&... args) + { + if (this->IsProfilingEnabled()) { + return cm::make_optional<cmMakefileProfilingData::RAII>( + this->GetProfilingOutput(), std::forward<Args>(args)...); + } + return cm::nullopt; + } #endif protected: |