diff --git a/Source/cmInstrumentation.cxx b/Source/cmInstrumentation.cxx index 3d743dce56..aba09d454e 100644 --- a/Source/cmInstrumentation.cxx +++ b/Source/cmInstrumentation.cxx @@ -3,11 +3,11 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -27,7 +27,10 @@ #include "cmUVProcessChain.h" #include "cmValue.h" -cmInstrumentation::cmInstrumentation(std::string const& binary_dir) +using LoadQueriesAfter = cmInstrumentation::LoadQueriesAfter; + +cmInstrumentation::cmInstrumentation(std::string const& binary_dir, + LoadQueriesAfter loadQueries) { std::string const uuid = cmExperimental::DataForFeature(cmExperimental::Feature::Instrumentation) @@ -40,7 +43,9 @@ cmInstrumentation::cmInstrumentation(std::string const& binary_dir) this->userTimingDirv1 = cmStrCat(configDir.value(), "/instrumentation-", uuid, "/v1"); } - this->LoadQueries(); + if (loadQueries == LoadQueriesAfter::Yes) { + this->LoadQueries(); + } } void cmInstrumentation::LoadQueries() @@ -126,6 +131,14 @@ void cmInstrumentation::LoadQueries() } } +cmsys::SystemInformation& cmInstrumentation::GetSystemInformation() +{ + if (!this->systemInformation) { + this->systemInformation = cm::make_unique(); + } + return *this->systemInformation; +} + bool cmInstrumentation::ReadJSONQueries(std::string const& directory) { cmsys::Directory d; @@ -210,8 +223,7 @@ bool cmInstrumentation::HasPreOrPostBuildHook() const int cmInstrumentation::CollectTimingData(cmInstrumentationQuery::Hook hook) { // Don't run collection if hook is disabled - if (hook != cmInstrumentationQuery::Hook::Manual && - this->hooks.find(hook) == this->hooks.end()) { + if (hook != cmInstrumentationQuery::Hook::Manual && !this->HasHook(hook)) { return 0; } @@ -299,36 +311,38 @@ int cmInstrumentation::CollectTimingData(cmInstrumentationQuery::Hook hook) void cmInstrumentation::InsertDynamicSystemInformation( Json::Value& root, std::string const& prefix) { - cmsys::SystemInformation info; Json::Value data; - info.RunCPUCheck(); - info.RunMemoryCheck(); + double memory; + double load; + this->GetDynamicSystemInformation(memory, load); if (!root.isMember("dynamicSystemInformation")) { root["dynamicSystemInformation"] = Json::objectValue; } root["dynamicSystemInformation"][cmStrCat(prefix, "HostMemoryUsed")] = - (double)info.GetHostMemoryUsed(); - root["dynamicSystemInformation"][cmStrCat(prefix, "CPULoadAverage")] = - info.GetLoadAverage(); + memory; + root["dynamicSystemInformation"][cmStrCat(prefix, "CPULoadAverage")] = load; } void cmInstrumentation::GetDynamicSystemInformation(double& memory, double& load) { - cmsys::SystemInformation info; - Json::Value data; - info.RunCPUCheck(); - info.RunMemoryCheck(); + cmsys::SystemInformation& info = this->GetSystemInformation(); + if (!this->ranSystemChecks) { + info.RunCPUCheck(); + info.RunMemoryCheck(); + this->ranSystemChecks = true; + } memory = (double)info.GetHostMemoryUsed(); load = info.GetLoadAverage(); } void cmInstrumentation::InsertStaticSystemInformation(Json::Value& root) { - cmsys::SystemInformation info; - info.RunCPUCheck(); - info.RunOSCheck(); - info.RunMemoryCheck(); + cmsys::SystemInformation& info = this->GetSystemInformation(); + if (!this->ranOSCheck) { + info.RunOSCheck(); + this->ranOSCheck = true; + } Json::Value infoRoot; infoRoot["familyId"] = info.GetFamilyID(); infoRoot["hostname"] = info.GetHostname(); @@ -408,7 +422,7 @@ std::string cmInstrumentation::InstrumentTest( this->InsertDynamicSystemInformation(root, "after"); } - cmsys::SystemInformation info; + cmsys::SystemInformation& info = this->GetSystemInformation(); std::string file_name = cmStrCat( "test-", this->ComputeSuffixHash(cmStrCat(command_str, info.GetProcessId())), @@ -430,12 +444,12 @@ int cmInstrumentation::InstrumentCommand( std::function const& callback, cm::optional> options, cm::optional> arrayOptions, - bool reloadQueriesAfterCommand) + LoadQueriesAfter reloadQueriesAfterCommand) { // Always begin gathering data for configure in case cmake_instrumentation // command creates a query - if (!this->hasQuery && !reloadQueriesAfterCommand) { + if (!this->hasQuery && reloadQueriesAfterCommand == LoadQueriesAfter::No) { return callback(); } @@ -457,7 +471,7 @@ int cmInstrumentation::InstrumentCommand( if (this->HasQuery( cmInstrumentationQuery::Query::DynamicSystemInformation)) { this->InsertDynamicSystemInformation(root, "before"); - } else if (reloadQueriesAfterCommand) { + } else if (reloadQueriesAfterCommand == LoadQueriesAfter::Yes) { this->GetDynamicSystemInformation(preConfigureMemory, preConfigureLoad); } @@ -466,9 +480,9 @@ int cmInstrumentation::InstrumentCommand( root["result"] = ret; // Exit early if configure didn't generate a query - if (reloadQueriesAfterCommand) { + if (reloadQueriesAfterCommand == LoadQueriesAfter::Yes) { this->LoadQueries(); - if (!this->hasQuery) { + if (!this->HasQuery()) { return ret; } if (this->HasQuery( @@ -530,7 +544,7 @@ int cmInstrumentation::InstrumentCommand( root["workingDir"] = cmSystemTools::GetLogicalWorkingDirectory(); // Write Json - cmsys::SystemInformation info; + cmsys::SystemInformation& info = this->GetSystemInformation(); std::string const& file_name = cmStrCat( command_type, "-", this->ComputeSuffixHash(cmStrCat(command_str, info.GetProcessId())), @@ -625,7 +639,7 @@ int cmInstrumentation::CollectTimingAfterBuild(int ppid) }; int ret = this->InstrumentCommand( "build", {}, [waitForBuild]() { return waitForBuild(); }, cm::nullopt, - cm::nullopt, false); + cm::nullopt, LoadQueriesAfter::No); this->CollectTimingData(cmInstrumentationQuery::Hook::PostBuild); return ret; } diff --git a/Source/cmInstrumentation.h b/Source/cmInstrumentation.h index b04488575a..602ce063ef 100644 --- a/Source/cmInstrumentation.h +++ b/Source/cmInstrumentation.h @@ -11,9 +11,13 @@ #include #include +#include #include #include +#ifndef CMAKE_BOOTSTRAP +# include +#endif #include #include "cmInstrumentationQuery.h" @@ -21,14 +25,21 @@ class cmInstrumentation { public: - cmInstrumentation(std::string const& binary_dir); + enum class LoadQueriesAfter + { + Yes, + No + }; + cmInstrumentation(std::string const& binary_dir, + LoadQueriesAfter loadQueries = LoadQueriesAfter::Yes); + void LoadQueries(); int InstrumentCommand( std::string command_type, std::vector const& command, std::function const& callback, cm::optional> options = cm::nullopt, cm::optional> arrayOptions = cm::nullopt, - bool reloadQueriesAfterCommand = false); + LoadQueriesAfter reloadQueriesAfterCommand = LoadQueriesAfter::No); std::string InstrumentTest(std::string const& name, std::string const& command, std::vector const& args, @@ -37,7 +48,6 @@ public: std::chrono::system_clock::time_point systemStart, std::string config); void GetPreTestStats(); - void LoadQueries(); bool HasQuery() const; bool HasQuery(cmInstrumentationQuery::Query) const; bool HasHook(cmInstrumentationQuery::Hook) const; @@ -60,13 +70,13 @@ private: void WriteInstrumentationJson(Json::Value& index, std::string const& directory, std::string const& file_name); - static void InsertStaticSystemInformation(Json::Value& index); - static void GetDynamicSystemInformation(double& memory, double& load); - static void InsertDynamicSystemInformation(Json::Value& index, - std::string const& instant); - static void InsertTimingData( - Json::Value& root, std::chrono::steady_clock::time_point steadyStart, - std::chrono::system_clock::time_point systemStart); + void InsertStaticSystemInformation(Json::Value& index); + void GetDynamicSystemInformation(double& memory, double& load); + void InsertDynamicSystemInformation(Json::Value& index, + std::string const& instant); + void InsertTimingData(Json::Value& root, + std::chrono::steady_clock::time_point steadyStart, + std::chrono::system_clock::time_point systemStart); bool HasQueryFile(std::string const& file); static std::string GetCommandStr(std::vector const& args); static std::string ComputeSuffixHash(std::string const& command_str); @@ -84,4 +94,10 @@ private: std::map cdashSnippetsMap; Json::Value preTestStats; bool hasQuery = false; + bool ranSystemChecks = false; + bool ranOSCheck = false; +#ifndef CMAKE_BOOTSTRAP + std::unique_ptr systemInformation; + cmsys::SystemInformation& GetSystemInformation(); +#endif }; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index df71ed39ae..40c7e0cb03 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2620,16 +2620,18 @@ int cmake::ActualConfigure() this->FileAPI = cm::make_unique(this); this->FileAPI->ReadQueries(); + this->Instrumentation = cm::make_unique( + this->State->GetBinaryDirectory(), + cmInstrumentation::LoadQueriesAfter::No); + this->Instrumentation->ClearGeneratedQueries(); + if (!this->GetIsInTryCompile()) { this->TruncateOutputLog("CMakeConfigureLog.yaml"); this->ConfigureLog = cm::make_unique( cmStrCat(this->GetHomeOutputDirectory(), "/CMakeFiles"_s), this->FileAPI->GetConfigureLogVersions()); + this->Instrumentation->LoadQueries(); } - - this->Instrumentation = - cm::make_unique(this->State->GetBinaryDirectory()); - this->Instrumentation->ClearGeneratedQueries(); #endif // actually do the configure @@ -2645,7 +2647,9 @@ int cmake::ActualConfigure() }; int ret = this->Instrumentation->InstrumentCommand( "configure", this->cmdArgs, [doConfigure]() { return doConfigure(); }, - cm::nullopt, cm::nullopt, true); + cm::nullopt, cm::nullopt, + this->GetIsInTryCompile() ? cmInstrumentation::LoadQueriesAfter::No + : cmInstrumentation::LoadQueriesAfter::Yes); if (ret != 0) { return ret; } @@ -2688,7 +2692,6 @@ int cmake::ActualConfigure() } // Setup launchers for instrumentation #if !defined(CMAKE_BOOTSTRAP) - this->Instrumentation->LoadQueries(); if (this->Instrumentation->HasQuery()) { std::string launcher; if (mf->IsOn("CTEST_USE_LAUNCHERS")) { @@ -3046,7 +3049,6 @@ int cmake::Generate() return 0; }; - this->Instrumentation->LoadQueries(); int ret = this->Instrumentation->InstrumentCommand( "generate", this->cmdArgs, [doGenerate]() { return doGenerate(); }); if (ret != 0) { diff --git a/Tests/RunCMake/Instrumentation/RunCMakeTest.cmake b/Tests/RunCMake/Instrumentation/RunCMakeTest.cmake index 1e86d440bb..39f06a70f9 100644 --- a/Tests/RunCMake/Instrumentation/RunCMakeTest.cmake +++ b/Tests/RunCMake/Instrumentation/RunCMakeTest.cmake @@ -6,7 +6,7 @@ function(instrument test) set(config "${CMAKE_CURRENT_LIST_DIR}/config") set(ENV{CMAKE_CONFIG_DIR} ${config}) cmake_parse_arguments(ARGS - "BUILD;BUILD_MAKE_PROGRAM;INSTALL;TEST;COPY_QUERIES;NO_WARN;STATIC_QUERY;DYNAMIC_QUERY;INSTALL_PARALLEL;MANUAL_HOOK" + "BUILD;BUILD_MAKE_PROGRAM;INSTALL;TEST;COPY_QUERIES;COPY_QUERIES_GENERATED;NO_WARN;STATIC_QUERY;DYNAMIC_QUERY;INSTALL_PARALLEL;MANUAL_HOOK" "CHECK_SCRIPT;CONFIGURE_ARG" "" ${ARGN}) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}) set(uuid "a37d1069-1972-4901-b9c9-f194aaf2b6e0") @@ -34,14 +34,18 @@ function(instrument test) list(APPEND ARGS_CONFIGURE_ARG "-DINSTRUMENT_COMMAND_FILE=${cmake_file}") endif() - # Configure generated query files to compare CMake output + set(copy_loc ${RunCMake_TEST_BINARY_DIR}/query) + if (ARGS_COPY_QUERIES_GENERATED) + set(ARGS_COPY_QUERIES TRUE) + set(copy_loc ${v1}/query/generated) # Copied files here should be cleared on configure + endif() if (ARGS_COPY_QUERIES) - file(MAKE_DIRECTORY ${RunCMake_TEST_BINARY_DIR}/query) + file(MAKE_DIRECTORY ${copy_loc}) set(generated_queries "0;1;2") foreach(n IN LISTS generated_queries) configure_file( "${query_dir}/generated/query-${n}.json.in" - "${RunCMake_TEST_BINARY_DIR}/query/query-${n}.json" + "${copy_loc}/query-${n}.json" ) endforeach() endif() @@ -118,6 +122,10 @@ instrument(cmake-command-bad-arg NO_WARN) instrument(cmake-command-parallel-install BUILD INSTALL TEST NO_WARN INSTALL_PARALLEL DYNAMIC_QUERY CHECK_SCRIPT check-data-dir.cmake) +instrument(cmake-command-resets-generated NO_WARN + COPY_QUERIES_GENERATED + CHECK_SCRIPT check-data-dir.cmake +) # FIXME(#26668) This does not work on Windows if (UNIX) diff --git a/Tests/RunCMake/Instrumentation/query/cmake-command-resets-generated.cmake b/Tests/RunCMake/Instrumentation/query/cmake-command-resets-generated.cmake new file mode 100644 index 0000000000..bdfdacf6f1 --- /dev/null +++ b/Tests/RunCMake/Instrumentation/query/cmake-command-resets-generated.cmake @@ -0,0 +1,4 @@ +cmake_instrumentation( + API_VERSION 1 + DATA_VERSION 1 +)