summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-05-26 13:36:01 -0400
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-05-27 19:21:05 -0400
commit4ad5ff8eca19b41f75a88ced48b33810ec617b40 (patch)
treed7fb1d53802996e347d7bcb653c72b9c66dd6fd1
parent9341075193d878b8b59f0805164eca3737920990 (diff)
make check: Generate coverage reports
-rw-r--r--.editorconfig2
-rw-r--r--.gitignore4
-rw-r--r--CMakeLists.txt5
-rw-r--r--GNUmakefile8
-rwxr-xr-xbuild-aux/gcov-prune33
5 files changed, 50 insertions, 2 deletions
diff --git a/.editorconfig b/.editorconfig
index 69c649d..9540302 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -48,7 +48,7 @@ _mode = gitignore
[{build-aux/lint-unknown,build-aux/embed-sources.h.gen}]
_mode = sh
-[{build-aux/lint-{bin,h,generic},build-aux/get-dscname,build-aux/valgrind,libusb/include/libusb/tusb_helpers.h.gen}]
+[{build-aux/lint-{bin,h,generic},build-aux/get-dscname,build-aux/valgrind,build-aux/gcov-prune,libusb/include/libusb/tusb_helpers.h.gen}]
_mode = bash
[build-aux/stack.c.gen]
diff --git a/.gitignore b/.gitignore
index e1f5883..9d27e6a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,13 @@
# .gitignore - Which files to ignore
#
-# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
# SPDX-License-Identifier: AGPL-3.0-or-later
*.o
*.log
*.tmp
+*.gcov.json.gz
+
.mypy_cache/
__pycache__/
.gdb_history
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ce49ed..2022bd1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,6 +44,11 @@ function(_suppress_tinyusb_warnings)
COMPILE_OPTIONS "-Wno-switch-enum")
endfunction()
+if (PICO_PLATFORM STREQUAL "host")
+ add_compile_options(--coverage)
+ add_link_options(--coverage)
+endif()
+
function(target_embed_sources arg_compile_target arg_link_target arg_hdrname)
set(embed_objs)
foreach(embed_src IN LISTS ARGN)
diff --git a/GNUmakefile b/GNUmakefile
index 9836b33..146f725 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -101,8 +101,16 @@ check:
$(MAKE) -k INNER=t $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/check))
.PHONY: check
+# `gcc` writes .gcno
+# Running the program writes .gcda (updates existing files, concurrent-safe)
+# GCC `gcov` post-processes .gcno+.gcda to .gcov
+# `gcovr` is a Python script that calls `gcov` and merges and post-processes the .gcov files to other formats
+gcovr_flags = --txt=$(@D)/coverage.txt
+gcovr_flags += --html=$(@D)/coverage.html --html-details --html-single-page=js-enabled
$(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/check)): build/%/check: build/%/build
+ ./build-aux/gcov-prune $(@D)
+cd $(@D) && ctest --output-on-failure $(if $(filter --jobserver-auth=%,$(MAKEFLAGS)),--parallel)
+ gcovr $(gcovr_flags) -- $(@D)
.PHONY: $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/check))
# `lint` and `format` ##########################################################
diff --git a/build-aux/gcov-prune b/build-aux/gcov-prune
new file mode 100755
index 0000000..dc190a9
--- /dev/null
+++ b/build-aux/gcov-prune
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+# build-aux/gcov-prune - Prune old GCC coverage files
+#
+# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+set -e
+
+[[ $# == 1 ]]
+
+sourcedir="$(realpath -- .)"
+builddir="$(realpath -- "$1")"
+
+# `gcc` writes .gcno
+# Running the program writes .gcda (updates existing files, concurrent-safe)
+# GCC `gcov` post-processes .gcno+.gcda to .gcov
+# `gcovr` is a Python script that calls `gcov` and merges and post-processes the .gcov files to other formats
+
+# Prune orphaned .gcno files.
+find "$builddir" -name '*.gcno' -printf '%P\0' | while read -d '' -r gcno_file; do
+ rel_base="${gcno_file%/CMakeFiles/*}"
+ src_file="$gcno_file"
+ src_file="${src_file#*/CMakeFiles/*.dir/}"
+ src_file="${src_file%.gcno}"
+ src_file="${src_file//__/..}"
+ src_file="$rel_base/$src_file"
+ if [[ ! -e "$sourcedir/$src_file" || "$sourcedir/$src_file" -nt "$builddir/$gcno_file" ]]; then
+ rm -fv -- "$builddir/$gcno_file"
+ fi
+done
+
+# Prune all .gcda files.
+find "$builddir" -name '*.gcda' -delete