From 751359ca43209bc85a48d37329f741176cd13062 Mon Sep 17 00:00:00 2001 From: Alicia Klinvex Date: Mon, 29 Jun 2026 16:08:14 -0400 Subject: [PATCH] Added codecov integration to stdBLAS Closes NavalNuclearLab/stdBLAS#7 --- .github/workflows/coverage.yml | 93 ++++++++++++++++++++++++++++++++++ CMakeLists.txt | 28 ++++++++++ codecov.yml | 20 ++++++++ tests/native/CMakeLists.txt | 1 + 4 files changed, 142 insertions(+) create mode 100644 .github/workflows/coverage.yml create mode 100644 codecov.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..153e8bb1 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,93 @@ +name: Coverage + +on: + push: + pull_request: + +jobs: + coverage: + runs-on: ubuntu-latest + + strategy: + matrix: + std: [17, 20] + + env: + COVERAGE_ROOT: ${{ github.workspace }}/.coverage + LLVM_PREFIX: /usr + LLVM_PROFILE_FILE: "$COVERAGE_ROOT/cxx${{ matrix.std }}/%p.profraw" + + steps: + - uses: actions/checkout@v4 + + - name: Install LLVM + run: | + sudo apt-get update + sudo apt-get install -y llvm clang + + - name: Configure + run: | + cmake -B build \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_STANDARD=${{ matrix.std }} \ + -DLINALG_ENABLE_TESTS=ON \ + -DLINALG_ENABLE_COVERAGE=ON \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ + + - name: Build + run: cmake --build build -j + + - name: Run tests (gtest) + working-directory: build + run: | + ctest --output-on-failure + + - name: Collect profraw + working-directory: build + run: | + mkdir -p $COVERAGE_ROOT/cxx${{ matrix.std }} + + find . -name "*.profraw" -exec cp {} $COVERAGE_ROOT/cxx${{ matrix.std }}/ \; + + - name: Merge profdata + run: | + llvm-profdata merge -sparse \ + $COVERAGE_ROOT/cxx${{ matrix.std }}/*.profraw \ + -o $COVERAGE_ROOT/cxx${{ matrix.std }}.profdata + + - name: Build binaries list + working-directory: build + run: | + find tests/native -type f -executable > $COVERAGE_ROOT/binaries.txt + + - name: Export per-binary LCOV + working-directory: build + run: | + : > $COVERAGE_ROOT/cxx${{ matrix.std }}.lcov + + while read exe; do + llvm-cov export "$exe" \ + -instr-profile=$COVERAGE_ROOT/cxx${{ matrix.std }}.profdata \ + --format=lcov >> $COVERAGE_ROOT/cxx${{ matrix.std }}.lcov + + echo >> $COVERAGE_ROOT/cxx${{ matrix.std }}.lcov + done < $COVERAGE_ROOT/binaries.txt + + - name: Normalize paths (CRITICAL) + run: | + sed -i "s|$GITHUB_WORKSPACE/||g" \ + $COVERAGE_ROOT/cxx${{ matrix.std }}.lcov + + - name: Remove external dependencies + run: | + grep -v "_deps" $COVERAGE_ROOT/cxx${{ matrix.std }}.lcov > tmp.lcov + mv tmp.lcov $COVERAGE_ROOT/cxx${{ matrix.std }}.lcov + + - name: Upload to Codecov + uses: codecov/codecov-action@v4 + with: + files: ${{ env.COVERAGE_ROOT }}/cxx${{ matrix.std }}.lcov + flags: cxx${{ matrix.std }} + name: stdBLAS-${{ matrix.std }} + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 96977aea..cdeec0ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") ################################################################################ +option(LINALG_ENABLE_COVERAGE "Enable LLVM source-based coverage" Off) option(LINALG_ENABLE_TESTS "Enable tests." Off) option(LINALG_ENABLE_EXAMPLES "Build examples." Off) #option(LINALG_ENABLE_BENCHMARKS "Enable benchmarks." Off) @@ -206,6 +207,33 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/LinAlgConfig.cmake ${CMAKE_CURRENT_BIN ################################################################################ +set(COVERAGE_BINARIES_FILE "${CMAKE_BINARY_DIR}/coverage_binaries.txt") + +# Reset file at configure time +file(WRITE ${COVERAGE_BINARIES_FILE} "") + +if(LINALG_ENABLE_COVERAGE) + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message(STATUS "Enabling Clang source-based coverage") + set(COVERAGE_FLAGS "-O0 -g -fprofile-instr-generate -fcoverage-mapping") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-instr-generate") + else() + message(FATAL_ERROR "LINALG_ENABLE_COVERAGE requires Clang") + endif() +endif() + +function(register_gtest_coverage target) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "$" >> ${COVERAGE_BINARIES_FILE} + COMMENT "Registering ${target} for coverage" + ) +endfunction() + +################################################################################ + if(LINALG_ENABLE_TESTS) enable_testing() add_subdirectory(tests) diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..5ce25391 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,20 @@ +codecov: + require_ci_to_pass: yes + +coverage: + status: + project: + default: + target: auto + informational: true + +flags: + cxx17: + paths: + - include/ + - tests/ + + cxx20: + paths: + - include/ + - tests/ \ No newline at end of file diff --git a/tests/native/CMakeLists.txt b/tests/native/CMakeLists.txt index efd0b4da..ee578822 100644 --- a/tests/native/CMakeLists.txt +++ b/tests/native/CMakeLists.txt @@ -10,6 +10,7 @@ macro(linalg_add_test name) target_link_libraries(${name} linalg GTest::GTest GTest::Main) endif() add_test(${name} ${name}) + register_gtest_coverage(${name}) endmacro() linalg_add_test(abs_if_needed)