From 2299b2fcab26dc5d7d4e82da7068da23af17623a Mon Sep 17 00:00:00 2001 From: Martin Duffy Date: Mon, 10 Feb 2025 16:39:35 -0500 Subject: instrumentation: Add build snippet Adds a new snippet generation for recording the full time spent waiting for `ninja` or `make` invocations to finish. --- Help/manual/cmake-instrumentation.7.rst | 3 +- Source/cmInstrumentation.cxx | 17 ++++-- .../Instrumentation/check-make-program-hooks.cmake | 10 ++++ Tests/RunCMake/Instrumentation/hook.cmake | 61 ++++++++++++---------- .../RunCMake/Instrumentation/verify-snippet.cmake | 19 ++++--- 5 files changed, 68 insertions(+), 42 deletions(-) diff --git a/Help/manual/cmake-instrumentation.7.rst b/Help/manual/cmake-instrumentation.7.rst index 3a70843..677e639 100644 --- a/Help/manual/cmake-instrumentation.7.rst +++ b/Help/manual/cmake-instrumentation.7.rst @@ -243,7 +243,7 @@ and contain the following data: always ``1``. ``command`` - The full command executed. + The full command executed. Excluded when ``role`` is ``build``. ``result`` The exit-value of the command, an integer. @@ -255,6 +255,7 @@ and contain the following data: * ``link`` * ``custom`` * ``cmakeBuild`` + * ``build`` * ``install`` * ``ctest`` * ``test`` diff --git a/Source/cmInstrumentation.cxx b/Source/cmInstrumentation.cxx index 87f59a8..6dffc4c 100644 --- a/Source/cmInstrumentation.cxx +++ b/Source/cmInstrumentation.cxx @@ -365,7 +365,9 @@ int cmInstrumentation::InstrumentCommand( Json::Value commandInfo(Json::objectValue); std::string command_str = GetCommandStr(command); - root["command"] = command_str; + if (!command_str.empty()) { + root["command"] = command_str; + } root["version"] = 1; // Pre-Command @@ -533,8 +535,15 @@ int cmInstrumentation::SpawnBuildDaemon() */ int cmInstrumentation::CollectTimingAfterBuild(int ppid) { - while (0 == uv_kill(ppid, 0)) { - cmSystemTools::Delay(100); + std::function waitForBuild = [ppid]() -> int { + while (0 == uv_kill(ppid, 0)) { + cmSystemTools::Delay(100); + }; + return 0; }; - return this->CollectTimingData(cmInstrumentationQuery::Hook::PostBuild); + int ret = this->InstrumentCommand( + "build", {}, [waitForBuild]() { return waitForBuild(); }, cm::nullopt, + cm::nullopt, false); + this->CollectTimingData(cmInstrumentationQuery::Hook::PostBuild); + return ret; } diff --git a/Tests/RunCMake/Instrumentation/check-make-program-hooks.cmake b/Tests/RunCMake/Instrumentation/check-make-program-hooks.cmake index 60b2f7b..239af3b 100644 --- a/Tests/RunCMake/Instrumentation/check-make-program-hooks.cmake +++ b/Tests/RunCMake/Instrumentation/check-make-program-hooks.cmake @@ -33,3 +33,13 @@ endif() if (NOT dataDirClean) string(APPEND RunCMake_TEST_FAILED "Snippet files not fully removed post build\n") endif() + +file(READ ${v1}/postBuild.hook postBuildErrors) +if (NOT postBuildErrors MATCHES "^$") + string(APPEND RunCMake_TEST_FAILED "Errors found in data during postBuild hook:\n${postBuildErrors}\n") +endif() + +file(READ ${v1}/preBuild.hook preBuildErrors) +if (NOT preBuildErrors MATCHES "^$") + string(APPEND RunCMake_TEST_FAILED "Errors found in data during preBuild hook:\n${preBuildErrors}\n") +endif() diff --git a/Tests/RunCMake/Instrumentation/hook.cmake b/Tests/RunCMake/Instrumentation/hook.cmake index cef088d..a139a37 100644 --- a/Tests/RunCMake/Instrumentation/hook.cmake +++ b/Tests/RunCMake/Instrumentation/hook.cmake @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.30) include(${CMAKE_CURRENT_LIST_DIR}/json.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/verify-snippet.cmake) # Test CALLBACK script. Prints output information and verifies index file # Called as: cmake -P hook.cmake [CheckForStaticQuery?] [index.json] set(index ${CMAKE_ARGV4}) @@ -19,7 +20,7 @@ function(add_error error) return(PROPAGATE ERROR_MESSAGE) endfunction() -function(has_key key json) +function(has_key_index key json) cmake_parse_arguments(ARG "UNEXPECTED" "" "" ${ARGN}) unset(missingKey) string(JSON ${key} ERROR_VARIABLE missingKey GET "${json}" ${key}) @@ -28,13 +29,13 @@ function(has_key key json) elseif(ARG_UNEXPECTED AND missingKey MATCHES NOTFOUND) add_error("\nUnexpected key \"${key}\" in index:\n${json}") endif() - return(PROPAGATE RunCMake_TEST_FAILED ${key}) + return(PROPAGATE ERROR_MESSAGE ${key}) endfunction() -has_key(version "${contents}") -has_key(buildDir "${contents}") -has_key(dataDir "${contents}") -has_key(snippets "${contents}") +has_key_index(version "${contents}") +has_key_index(buildDir "${contents}") +has_key_index(dataDir "${contents}") +has_key_index(snippets "${contents}") if (NOT version EQUAL 1) add_error("Version must be 1, got: ${version}") @@ -47,32 +48,34 @@ foreach(i RANGE ${length}) if (NOT EXISTS ${dataDir}/${filename}) add_error("Listed snippet: ${dataDir}/${filename} does not exist") endif() + read_json(${dataDir}/${filename} snippet_contents) + verify_snippet(${dataDir}/${filename} "${snippet_contents}") endforeach() -has_key(staticSystemInformation "${contents}" ${hasStaticInfo}) -has_key(OSName "${staticSystemInformation}" ${hasStaticInfo}) -has_key(OSPlatform "${staticSystemInformation}" ${hasStaticInfo}) -has_key(OSRelease "${staticSystemInformation}" ${hasStaticInfo}) -has_key(OSVersion "${staticSystemInformation}" ${hasStaticInfo}) -has_key(familyId "${staticSystemInformation}" ${hasStaticInfo}) -has_key(hostname "${staticSystemInformation}" ${hasStaticInfo}) -has_key(is64Bits "${staticSystemInformation}" ${hasStaticInfo}) -has_key(modelId "${staticSystemInformation}" ${hasStaticInfo}) -has_key(numberOfLogicalCPU "${staticSystemInformation}" ${hasStaticInfo}) -has_key(numberOfPhysicalCPU "${staticSystemInformation}" ${hasStaticInfo}) -has_key(processorAPICID "${staticSystemInformation}" ${hasStaticInfo}) -has_key(processorCacheSize "${staticSystemInformation}" ${hasStaticInfo}) -has_key(processorClockFrequency "${staticSystemInformation}" ${hasStaticInfo}) -has_key(processorName "${staticSystemInformation}" ${hasStaticInfo}) -has_key(totalPhysicalMemory "${staticSystemInformation}" ${hasStaticInfo}) -has_key(totalVirtualMemory "${staticSystemInformation}" ${hasStaticInfo}) -has_key(vendorID "${staticSystemInformation}" ${hasStaticInfo}) -has_key(vendorString "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(staticSystemInformation "${contents}" ${hasStaticInfo}) +has_key_index(OSName "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(OSPlatform "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(OSRelease "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(OSVersion "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(familyId "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(hostname "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(is64Bits "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(modelId "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(numberOfLogicalCPU "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(numberOfPhysicalCPU "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(processorAPICID "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(processorCacheSize "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(processorClockFrequency "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(processorName "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(totalPhysicalMemory "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(totalVirtualMemory "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(vendorID "${staticSystemInformation}" ${hasStaticInfo}) +has_key_index(vendorString "${staticSystemInformation}" ${hasStaticInfo}) + +get_filename_component(dataDir ${index} DIRECTORY) +get_filename_component(v1 ${dataDir} DIRECTORY) +file(WRITE ${v1}/${hook}.hook "${ERROR_MESSAGE}") if (NOT ERROR_MESSAGE MATCHES "^$") message(FATAL_ERROR ${ERROR_MESSAGE}) endif() - -get_filename_component(dataDir ${index} DIRECTORY) -get_filename_component(v1 ${dataDir} DIRECTORY) -file(TOUCH ${v1}/${hook}.hook) diff --git a/Tests/RunCMake/Instrumentation/verify-snippet.cmake b/Tests/RunCMake/Instrumentation/verify-snippet.cmake index d64f686..ec997e3 100644 --- a/Tests/RunCMake/Instrumentation/verify-snippet.cmake +++ b/Tests/RunCMake/Instrumentation/verify-snippet.cmake @@ -2,12 +2,13 @@ function(add_error error) string(APPEND RunCMake_TEST_FAILED " ${error}\n") - return(PROPAGATE RunCMake_TEST_FAILED) + string(APPEND ERROR_MESSAGE " ${error}\n") + return(PROPAGATE RunCMake_TEST_FAILED ERROR_MESSAGE) endfunction() function(snippet_error snippet error) add_error("Error in snippet file ${snippet}:\n${error}") - return(PROPAGATE RunCMake_TEST_FAILED) + return(PROPAGATE RunCMake_TEST_FAILED ERROR_MESSAGE) endfunction() function(has_key snippet json key) @@ -15,7 +16,7 @@ function(has_key snippet json key) if (NOT missingKey MATCHES NOTFOUND) snippet_error("${snippet}" "Missing ${key}") endif() - return(PROPAGATE RunCMake_TEST_FAILED) + return(PROPAGATE RunCMake_TEST_FAILED ERROR_MESSAGE) endfunction() function(has_not_key snippet json key) @@ -23,14 +24,16 @@ function(has_not_key snippet json key) if (missingKey MATCHES NOTFOUND) snippet_error("${snippet}" "Has unexpected ${key}") endif() - return(PROPAGATE RunCMake_TEST_FAILED) + return(PROPAGATE RunCMake_TEST_FAILED ERROR_MESSAGE) endfunction() function(snippet_has_fields snippet contents) get_filename_component(filename "${snippet}" NAME) - has_key("${snippet}" "${contents}" command) has_key("${snippet}" "${contents}" role) has_key("${snippet}" "${contents}" result) + if (NOT filename MATCHES "^build-*") + has_key("${snippet}" "${contents}" command) + endif() if (filename MATCHES "^link-*") has_key("${snippet}" "${contents}" target) has_key("${snippet}" "${contents}" outputs) @@ -72,7 +75,7 @@ function(snippet_has_fields snippet contents) has_not_key("${snippet}" ${dynamicSystemInfo} beforeHostMemoryUsed) endif() endif() - return(PROPAGATE RunCMake_TEST_FAILED) + return(PROPAGATE RunCMake_TEST_FAILED ERROR_MESSAGE) endfunction() function(snippet_valid_timing contents) @@ -84,7 +87,7 @@ function(snippet_valid_timing contents) if (duration LESS 0) snippet_error("${snippet}" "Negative duration: ${end}") endif() - return(PROPAGATE RunCMake_TEST_FAILED) + return(PROPAGATE RunCMake_TEST_FAILED ERROR_MESSAGE) endfunction() function(verify_snippet snippet contents) @@ -108,5 +111,5 @@ function(verify_snippet snippet contents) snippet_error("${snippet}" "outputs and outputSizes do not match") endif() endif() - return(PROPAGATE RunCMake_TEST_FAILED role) + return(PROPAGATE ERROR_MESSAGE RunCMake_TEST_FAILED role) endfunction() -- cgit v0.12