instrumentation: Add build snippet

Adds a new snippet generation for recording the full time spent waiting for
`ninja` or `make` invocations to finish.
This commit is contained in:
Martin Duffy
2025-02-10 16:39:35 -05:00
committed by Brad King
parent b2674f3b38
commit 2299b2fcab
5 changed files with 68 additions and 42 deletions

View File

@@ -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``

View File

@@ -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<int()> 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;
}

View File

@@ -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()

View File

@@ -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)

View File

@@ -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()