Fix some errors in processing of code coverage data

We were using mismatched compiler and gcov, which led to either
segfaults or errors like "GCOV_TAG_COUNTER_ARCS mismatch". Add some
cmake code that tries to find the gcov that matches the compiler.

This should hopefully fix some of the mysterious missing coverage
problems that we've been experiencing for a while.
This commit is contained in:
Alexander Kuzmenkov 2023-02-13 11:29:58 +04:00
parent 9ec11d8af6
commit d00c1f3721
3 changed files with 56 additions and 21 deletions

View File

@ -65,8 +65,6 @@ jobs:
sudo apt-get update
sudo apt-get install flex bison lcov systemd-coredump gdb libipc-run-perl \
libtest-most-perl ${{ matrix.extra_packages }}
# The GCC 11 gcov segfaults with the coverage info generated by clang.
sudo ln -sf $(which llvm-cov-14) $(which gcov)
- name: Install macOS Dependencies
if: runner.os == 'macOS'
@ -173,12 +171,19 @@ jobs:
if: matrix.coverage
run: make -j $MAKE_JOBS -k -C build coverage
- name: Upload coverage report
- name: Send coverage report to Codecov.io app
if: matrix.coverage
uses: codecov/codecov-action@v3
with:
file: ./build/codecov/timescaledb-codecov.info
- name: Save LCOV coverage report
if: matrix.coverage
uses: actions/upload-artifact@v3
with:
name: LCOV coverage report ${{ matrix.os }} ${{ matrix.name }} ${{ matrix.pg }}
path: ./build/codecov/codecov-report
- name: Show regression diffs
if: always()
id: collectlogs

View File

@ -644,6 +644,7 @@ add_custom_target(licensecheck
if(CODECOVERAGE)
add_subdirectory(codecov)
endif()
if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/.git)
configure_file(${PROJECT_SOURCE_DIR}/scripts/githooks/commit_msg.py
${PROJECT_SOURCE_DIR}/.git/hooks/commit-msg COPYONLY)

View File

@ -5,7 +5,7 @@
# the --coverage option for the compiler and this is done in the top-level
# CMakeLists.txt so that the option covers all build targets in the project.
#
# Given that all dependencies (lcov, genhtml) are installed, and CMake is
# Given that all dependencies (lcov, gcov, genhtml) are installed, and CMake is
# initialized with -DCODECOVERAGE=ON, it should be possible to generate a code
# coverage report by running:
#
@ -13,16 +13,43 @@
#
# The report is generated in REPORT_DIR and can be viewed in a web browser.
# If we use clang, prefer the LLVM gcov. The "normal" gcov segfaults with the
# coverage info generated by clang, and the LLVM gcov with GCC-generated
# coverage gives weird errors like GCOV_TAG_COUNTER_ARCS mismatch.
set(GCOV_NAMES "gcov")
if(CMAKE_C_COMPILER_ID MATCHES "Clang|AppleClang")
string(REGEX MATCH "^[0-9]+" CMAKE_C_COMPILER_VERSION_MAJOR
${CMAKE_C_COMPILER_VERSION})
list(PREPEND GCOV_NAMES "llvm-cov-${CMAKE_C_COMPILER_VERSION_MAJOR}")
endif()
find_program(GCOV NAMES ${GCOV_NAMES})
# Find lcov for html output
find_program(LCOV lcov)
if(LCOV)
if(NOT GCOV)
message(STATUS "Install gcov to generate code coverage reports")
elseif(NOT LCOV)
message(STATUS "Install lcov to generate code coverage reports")
else()
message(STATUS "Using lcov ${LCOV}:")
execute_process(COMMAND ${LCOV} --version)
message(STATUS "Using gcov ${GCOV}:")
execute_process(COMMAND ${GCOV} --version)
# Final tracefile for code coverage
set(OUTPUT_FILE "timescaledb-codecov.info")
# Directory where to generate the HTML report
set(REPORT_DIR "codecov-report")
# We can't directly use llvm-cov as --gcov-tool, because it has to be called
# like "llvm-cov gcov <gcov args>" for that. Thankfully, if its $0 is gcov, it
# will understand that we want it to operate like gcov. Just create a symlink.
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gcov
COMMAND ln -s ${GCOV} ${CMAKE_CURRENT_BINARY_DIR}/gcov)
# The baseline run needs to run before tests to learn what zero coverage looks
# like
add_custom_command(
@ -32,12 +59,12 @@ if(LCOV)
${LCOV} --capture --initial # Initial run
--no-external # Do not include external source files
--base-directory ${CMAKE_SOURCE_DIR} --directory ${CMAKE_BINARY_DIR}
--output-file ${OUTPUT_FILE}.base
DEPENDS timescaledb-tsl timescaledb timescaledb-loader)
--output-file ${OUTPUT_FILE}.base --gcov-tool
${CMAKE_CURRENT_BINARY_DIR}/gcov
DEPENDS timescaledb-tsl timescaledb timescaledb-loader
${CMAKE_CURRENT_BINARY_DIR}/gcov)
add_custom_target(
coverage_base DEPENDS timescaledb-tsl timescaledb timescaledb-loader
${OUTPUT_FILE}.base)
add_custom_target(coverage_base DEPENDS ${OUTPUT_FILE}.base)
# Ensure baseline file is generated before tests
add_dependencies(installcheck coverage_base)
@ -46,8 +73,10 @@ if(LCOV)
add_custom_command(
OUTPUT ${OUTPUT_FILE}.test
COMMENT "Generating code coverage test file"
COMMAND ${LCOV} --capture --no-external --base-directory ${CMAKE_SOURCE_DIR}
--directory ${CMAKE_BINARY_DIR} --output-file ${OUTPUT_FILE}.test
COMMAND
${LCOV} --capture --no-external --base-directory ${CMAKE_SOURCE_DIR}
--directory ${CMAKE_BINARY_DIR} --output-file ${OUTPUT_FILE}.test
--gcov-tool ${CMAKE_CURRENT_BINARY_DIR}/gcov
DEPENDS ${OUTPUT_FILE}.base coverage_base)
# Make sure coverage_test runs after tests (installcheck) finish
@ -59,8 +88,10 @@ if(LCOV)
add_custom_command(
OUTPUT ${OUTPUT_FILE}
COMMENT "Generating final code coverage file"
COMMAND ${LCOV} --add-tracefile ${OUTPUT_FILE}.base --add-tracefile
${OUTPUT_FILE}.test --output-file ${OUTPUT_FILE}
COMMAND
${LCOV} --add-tracefile ${OUTPUT_FILE}.base --add-tracefile
${OUTPUT_FILE}.test --output-file ${OUTPUT_FILE} --gcov-tool
${CMAKE_CURRENT_BINARY_DIR}/gcov
DEPENDS ${OUTPUT_FILE}.test coverage_test)
add_custom_target(coverage_final DEPENDS ${OUTPUT_FILE})
@ -90,14 +121,12 @@ if(LCOV)
add_dependencies(coverage coverage_final)
add_custom_command(
TARGET coverage
POST_BUILD
COMMENT
COMMAND
echo
"Open file://${CMAKE_CURRENT_BINARY_DIR}/${REPORT_DIR}/index.html in a browser to view the report"
)
TARGET coverage POST_BUILD
COMMENT)
else()
message(STATUS "Install genhtml to generate code coverage reports")
endif(GENHTML)
else()
message(STATUS "Install lcov to generate code coverage reports")
endif(LCOV)
endif()