Skip to content

Commit 9b14fb6

Browse files
authored
Merge pull request #171 from steve-downey/cmakeinstrument
Add cmake instrumentation module
2 parents d4cc351 + 2c9d7f6 commit 9b14fb6

5 files changed

Lines changed: 171 additions & 3 deletions

File tree

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ define run_cmake =
4545
-DCMAKE_INSTALL_PREFIX=$(abspath $(INSTALL_PREFIX)) \
4646
-DCMAKE_EXPORT_COMPILE_COMMANDS=1 \
4747
-DCMAKE_PREFIX_PATH=$(CURDIR)/infra/cmake \
48-
-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="./cmake/use-fetch-content.cmake" \
48+
-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="./cmake/use-fetch-content.cmake;infra/cmake/bemancmakeinstrumentation.cmake" \
4949
$(_cmake_args) \
5050
$(CURDIR)
5151
endef
@@ -85,10 +85,10 @@ clean-install:
8585
realclean: clean-install
8686

8787
ctest: $(_build_path)/CMakeCache.txt ## Run CTest on current build
88-
cd $(_build_path) && ctest --output-on-failure -C $(CONFIG)
88+
cd $(_build_path) && ctest --parallel --output-on-failure -C $(CONFIG)
8989

9090
ctest_ : compile
91-
cd $(_build_path) && ctest --output-on-failure -C $(CONFIG)
91+
cd $(_build_path) && ctest --parallel --output-on-failure -C $(CONFIG)
9292

9393
test: ctest_ ## Rebuild and run tests
9494

infra/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,21 @@ Some options for the project and target will also be supported:
5353
* `BEMAN_INSTALL_CONFIG_FILE_PACKAGES` - a list of package names (e.g., `beman.something`) for which to install the config file
5454
(default: all packages)
5555
* `<BEMAN_NAME>_INSTALL_CONFIG_FILE_PACKAGE` - a per-project option to enable/disable config file installation (default: `ON` if the project is top-level, `OFF` otherwise). For instance for `beman.something`, the option would be `BEMAN_SOMETHING_INSTALL_CONFIG_FILE_PACKAGE`.
56+
57+
#### `beman_cmake_instrumentation`
58+
59+
The cmake modules in this library are intended to provide access to CMake instrumentation data in Google Trace format which is visualizable with chrome://tracing and https://ui.perfetto.dev.
60+
61+
Instrumentation may be enabled either by adding to the CMAKE_PROJECT_TOP_LEVEL_INCLUDES
62+
```sh
63+
-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=infra/cmake/bemancmakeinstrumentation.cmake
64+
```
65+
or by calling explicitly within the CMakeList.txt file.
66+
```cmake
67+
find_package(BemanCMakeInstrumentation)
68+
configure_beman_cmake_instrumentation()
69+
```
70+
71+
In either form, CMake will call `instrumentation.sh` which will copy the trace data in json format into a `.trace` subdirectory within the build directory.
72+
73+
Multiple calls to `configure_beman_cmake_instrumentation` will only configure the callback hooks once, so it is safe to include multiple times, including by TOP_LEVEL_INCLUDE.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
include_guard(GLOBAL)
2+
3+
cmake_minimum_required (VERSION 4.2)
4+
5+
set(BEMAN_CMAKE_INSTRUMENTATION_DIR ${CMAKE_CURRENT_LIST_DIR})
6+
7+
function(configure_beman_cmake_instrumentation)
8+
if(NOT BEMAN_CMAKE_INSTRUMENTATION_CONFIGURATION)
9+
message(WARNING "Configuring Beman CMake Instrumentation")
10+
11+
# Enable experimental feature!!
12+
set(CMAKE_EXPERIMENTAL_INSTRUMENTATION ec7aa2dc-b87f-45a3-8022-fe01c5f59984)
13+
14+
# Instrumentation query
15+
cmake_instrumentation(
16+
API_VERSION 1
17+
DATA_VERSION 1
18+
19+
OPTIONS staticSystemInformation dynamicSystemInformation trace
20+
HOOKS postGenerate preBuild postBuild preCMakeBuild postCMakeBuild postCMakeInstall postCTest
21+
CALLBACK ${BEMAN_CMAKE_INSTRUMENTATION_DIR}/instrumentation.sh
22+
)
23+
message(WARNING "using callback script ${BB_CMAKE_INSTRUMENTATION_DIR}/instrumentation.sh")
24+
25+
# Mark task as done in cache
26+
set(BEMAN_CMAKE_INSTRUMENTATION_CONFIGURATION TRUE CACHE INTERNAL "Flag to ensure CMake Instrumentation configured only once")
27+
endif()
28+
29+
endfunction(configure_beman_cmake_instrumentation)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
include_guard(GLOBAL)
2+
3+
cmake_minimum_required (VERSION 4.2)
4+
5+
find_package(BemanCMakeInstrumentation)
6+
configure_beman_cmake_instrumentation()

infra/cmake/instrumentation.sh

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/usr/bin/env bash
2+
3+
set -o nounset
4+
set -o errexit
5+
trap 'echo "Aborting due to errexit on line $LINENO. Exit code: $?" >&2' ERR
6+
set -o errtrace
7+
set -o pipefail
8+
IFS=$'\n\t'
9+
10+
###############################################################################
11+
# Environment
12+
###############################################################################
13+
14+
# $_ME
15+
#
16+
# This program's basename.
17+
_ME="$(basename "${0}")"
18+
19+
###############################################################################
20+
# Help
21+
###############################################################################
22+
23+
# _print_help()
24+
#
25+
# Usage:
26+
# _print_help
27+
#
28+
# Print the program help information.
29+
_print_help() {
30+
cat <<HEREDOC
31+
32+
Callback script to process CMake Instrumentation data
33+
https://cmake.org/cmake/help/latest/command/cmake_instrumentation.html
34+
35+
Usage:
36+
${_ME} [<arguments>]
37+
${_ME} -h | --help
38+
39+
Options:
40+
-h --help Show this screen.
41+
HEREDOC
42+
}
43+
44+
###############################################################################
45+
# Program Functions
46+
###############################################################################
47+
_debug_print() {
48+
if [[ -n "${DEBUG:-}" ]]; then
49+
printf "[DEBUG] $(date +'%H:%M:%S'): %s \n" "$1" >&2
50+
fi
51+
}
52+
53+
_check_file_exists() {
54+
local file="$1"
55+
if [[ ! -f "${file}" ]]; then
56+
echo "Error: File not found: ${file}" >&2
57+
exit 1 # Exit the entire script with a non-zero status
58+
fi
59+
}
60+
61+
_process_index() {
62+
indexFile=${1:-}
63+
_check_file_exists "${indexFile}"
64+
_debug_print "$(cat "${indexFile}")"
65+
66+
local buildDir
67+
buildDir=$(jq -r '.buildDir' "${1:-}")
68+
_debug_print "$(printf "buildDir is |%q|" "${buildDir}")"
69+
70+
local dataDir
71+
dataDir=$(jq -r '.dataDir' "${1:-}")
72+
_debug_print "$(printf "dataDir is |%q|" "${dataDir}")"
73+
74+
local hook
75+
hook=$(jq -r '.hook' "${1:-}")
76+
_debug_print "$(printf "hook is |%q|" "${hook}")"
77+
78+
local trace
79+
trace=$(jq -r '.trace' "${1:-}")
80+
_debug_print "$(printf "trace is |%q|" "${trace}")"
81+
82+
local outputDir
83+
outputDir="${buildDir}/.trace"
84+
_debug_print "$(printf "Copy trace to |%q|" "${outputDir}")"
85+
mkdir -p "${outputDir}"
86+
87+
local traceDestFile
88+
traceDestFile="${outputDir}/${hook}-$(basename "${trace}")"
89+
_debug_print "$(printf "traceDestFile: |%q|" "${traceDestFile}")"
90+
cp "${dataDir}/${trace}" "${outputDir}/${hook}-$(basename "${trace}")"
91+
}
92+
93+
###############################################################################
94+
# Main
95+
###############################################################################
96+
97+
# _main()
98+
#
99+
# Usage:
100+
# _main [<options>] [<arguments>]
101+
#
102+
# Description:
103+
# Entry point for the program, handling basic option parsing and dispatching.
104+
_main() {
105+
# Avoid complex option parsing when only one program option is expected.
106+
if [[ "${1:-}" =~ ^-h|--help$ ]]
107+
then
108+
_print_help
109+
else
110+
_process_index "$@"
111+
fi
112+
}
113+
114+
# Call `_main` after everything has been defined.
115+
_main "$@"

0 commit comments

Comments
 (0)