From 102bc1953f3a4fcbc20279cb22f907a310a88714 Mon Sep 17 00:00:00 2001 From: Chad Condon Date: Tue, 31 Mar 2026 23:16:22 -0700 Subject: [PATCH] Automate coverage via CTest post-test hooks Add cmake/lcov.cmake and cmake/CTestCustom.cmake.in so that lcov capture, filtering, and genhtml run automatically as CTEST_CUSTOM_POST_TEST hooks after ctest completes. Wire the coverage preset to load lcov.cmake via CMAKE_PROJECT_CppUTest_INCLUDE, and update the CI workflow to drop the manual lcov shell steps and point coverallsapp at the new output path (cpputest_build/coverage.lcov). --- .github/workflows/basic.yml | 7 +------ CMakePresets.json | 1 + cmake/CTestCustom.cmake.in | 6 ++++++ cmake/lcov.cmake | 13 +++++++++++++ 4 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 cmake/CTestCustom.cmake.in create mode 100644 cmake/lcov.cmake diff --git a/.github/workflows/basic.yml b/.github/workflows/basic.yml index dd4615e08..de5c5d8ea 100644 --- a/.github/workflows/basic.yml +++ b/.github/workflows/basic.yml @@ -298,15 +298,10 @@ jobs: ctest --test-dir build if: ${{ matrix.install }} - - name: Coverage - run: | - lcov --ignore-errors mismatch --capture --directory . --no-external --output-file lcov.info - lcov --remove lcov.info --output-file lcov.info '*/tests/*' - if: ${{ matrix.name == 'Coverage' }} - name: Coveralls uses: coverallsapp/github-action@master with: - path-to-lcov: lcov.info + path-to-lcov: cpputest_build/coverage.lcov github-token: ${{ secrets.GITHUB_TOKEN }} if: ${{ matrix.name == 'Coverage' }} diff --git a/CMakePresets.json b/CMakePresets.json index a4a3f8327..7fffdefc0 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -81,6 +81,7 @@ }, "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_PROJECT_CppUTest_INCLUDE": "${sourceDir}/cmake/lcov.cmake", "CMAKE_CXX_STANDARD": "11", "CPPUTEST_EXAMPLES": false } diff --git a/cmake/CTestCustom.cmake.in b/cmake/CTestCustom.cmake.in new file mode 100644 index 000000000..ebdac37c8 --- /dev/null +++ b/cmake/CTestCustom.cmake.in @@ -0,0 +1,6 @@ +set(CTEST_CUSTOM_POST_TEST + "@LCOV@ --capture --directory @CMAKE_BINARY_DIR@ --base-directory @CMAKE_SOURCE_DIR@ --no-external --ignore-errors mismatch,inconsistent --output-file @CMAKE_BINARY_DIR@/coverage.lcov" + "@LCOV@ --remove @CMAKE_BINARY_DIR@/coverage.lcov --output-file @CMAKE_BINARY_DIR@/coverage.lcov */tests/*" + "@CMAKE_COMMAND@ -E rm -rf @CMAKE_BINARY_DIR@/coverage" + "@GENHTML@ @CMAKE_BINARY_DIR@/coverage.lcov --output-directory @CMAKE_BINARY_DIR@/coverage" +) diff --git a/cmake/lcov.cmake b/cmake/lcov.cmake new file mode 100644 index 000000000..ca2d02cb7 --- /dev/null +++ b/cmake/lcov.cmake @@ -0,0 +1,13 @@ +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + message(FATAL_ERROR + "Coverage requires GCC or Clang (got ${CMAKE_CXX_COMPILER_ID})") +endif() + +find_program(LCOV lcov REQUIRED) +find_program(GENHTML genhtml REQUIRED) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CTestCustom.cmake.in" + "${CMAKE_BINARY_DIR}/CTestCustom.cmake" + @ONLY +)