mirror of
https://github.com/Xahau/xahaud.git
synced 2026-09-27 07:36:52 +00:00
* ci: add -Dcoverage_tool=gcov|llvm option, wire native llvm-cov in matrix
introduces native llvm source-based coverage as an alternative to the
existing gcov + gcovr pipeline. driven by a new -Dcoverage_tool cache
variable (default 'gcov' for backwards compat; 'llvm' enables
-fprofile-instr-generate / -fcoverage-mapping + llvm-profdata + llvm-cov).
cmake:
- RippledSettings.cmake: add coverage_tool with validation
- RippledInterface.cmake: split coverage compile/link flags by tool
- RippledCov.cmake: dispatch to the new helper when tool=llvm
- CodeCoverageLLVM.cmake (new): setup_target_for_coverage_llvm() driving
profraw -> profdata -> export with format-aware output (lcov/json/txt/html)
ci:
- new clang-20 llvm-cov coverage matrix row (apt.llvm.org bootstrap for
clang >= 19 since 24.04 default repos cap at clang-18)
- conditional install of llvm-N vs gcovr based on coverage_tool
- artifact + codecov upload generalised to coverage.lcov | coverage.xml
- coverage cmake-args switched to *_FLAGS_DEBUG so the build action's
stdlib flag isn't clobbered
temp (revert before merging to dev):
- matrix narrowed to just the llvm-cov row on non-main refs so we can
iterate without burning runners
- 'coverage-llm' added to push trigger for direct-push CI runs
* ci: drop coverage-llm from push triggers, PR trigger covers it
* ci: actually narrow matrix to just the llvm-cov row
prior guard checked base_ref against ['dev','candidate','release'] which
excluded the very PR we're iterating on. drop the guard - this branch
is for iteration only and must be reverted before merging anyway.
* ci(deps): apply Wno-missing-template-arg-list workaround to Linux clang
grpc 1.50.1 hits -Werror=missing-template-arg-list-after-template-kw on
clang-19+. macOS clang already had this workaround in the conan profile;
mirror it to the Linux branch, gated on compiler==clang.
* ci(temp): disable all workflows except Nix GA on this branch
renames every non-nix workflow to .yml.disabled so they stop firing on
PR pushes while we iterate on the llvm-cov coverage row. MUST be
reverted before merging to dev.
* fix(cov): use absolute binary path in llvm-cov run command
bare 'rippled' wasn't on PATH and the build dir isn't '.', so the
profile-collection step failed with 'No such file or directory'.
splice the resolved absolute path back into Cov_EXECUTABLE before
the run command consumes it.
* ci(deps): replace hardcoded grpc workaround with matrix-driven conan_deps_cxxflags
new dependencies action input `conan_deps_cxxflags` (json list, default
'[]') drives `tools.build:cxxflags` in the conan profile. clearly named
to indicate the flags only apply to conan dependency builds, not the
rippled build itself.
removes the per-os/per-compiler hardcoded workaround (linux clang
conditional + unconditional macOS block) that used to set the same flag
in two places kept-in-sync by hand.
call sites:
- xahau-ga-nix.yml: clang-20 coverage row gets the
-Wno-missing-template-arg-list-after-template-kw workaround for grpc 1.50.1
- xahau-ga-macos.yml.disabled: same flag plumbed through (preserves
prior behaviour when re-enabled)
drop the workaround entries when grpc is bumped past the fix.
* fix(cov): tighten coverage_tool=llvm validation + macOS tool discovery
two bugs caught in review:
- RippledSettings.cmake: the clang-only guard for coverage_tool=llvm ran
before coverage_test could auto-enable coverage. so
'-Dcoverage_tool=llvm -Dcoverage_test=Foo' on a gcc build slipped past
the guard and produced an instrumentation/tool mismatch. move the
guard after the auto-enable block.
- CodeCoverageLLVM.cmake: _find_llvm_cov_tools unconditionally
preferred xcrun's tools on APPLE, which on a homebrew clang-N build
would pair the user's clang with xcode's llvm-cov - exactly the
version mismatch the helper is trying to avoid. gate the xcrun branch
on CMAKE_CXX_COMPILER_ID == AppleClang.
* chore(cov): drop dead BASE_DIRECTORY arg + revert .disabled file edit
- CodeCoverageLLVM.cmake: BASE_DIRECTORY was parsed but never used
(no analog to gcovr's -r in the llvm-cov commands we emit). dead arg.
- xahau-ga-macos.yml.disabled: revert the conan_deps_cxxflags addition.
the file is disabled so the edit was bit-rotting in unreachable code.
whoever revives the macOS workflow can wire up the field then.
* Revert "chore(cov): drop ... .disabled file edit" (partial)
restore the conan_deps_cxxflags addition to xahau-ga-macos.yml.disabled.
prior commit framed it as dead code, but the .disabled rename is itself
a TEMP measure being reverted before merge - the field is needed for the
macOS workflow to keep building grpc 1.50.1 once it's re-enabled, since
the unconditional workaround was removed from the dependencies action.
* fix(ci): restore conan_deps_cxxflags on macOS workflow
reverts part of f8a30c528d - removing this line dropped the apple-clang
grpc workaround that the dependencies action used to apply
unconditionally before the matrix-driven refactor. the .disabled rename
is itself a TEMP measure being reverted before merge, so the field needs
to be in place when the macOS workflow comes back.
* ci: restore matrix-row comments explaining clang-20 + grpc workaround
* ci: dedupe conan_deps_cxxflags in macOS workflow row
prior turn-of-events created two identical conan_deps_cxxflags entries
in the same matrix row from overlapping restore commits. keep one.
* ci: undisable workflows, drop gcc-13 coverage row, keep clang-20 llvm-cov as sole codecov reporter
- restore the 8 .yml.disabled workflows back to .yml
- drop the gcc-13 gcov coverage matrix row; native clang-20 llvm-cov is
now the only codecov reporter
- update minimal_matrix indices to match
- remove the TEMP narrowing block that filtered to just the llvm-cov row
- log line says '7 configs (build x6 + clang-20 llvm-cov coverage)' to
reflect the new shape
* fix(ci): scope conan_deps_cxxflags per Conan package pattern
prior shape (bare json list -> 'tools.build:cxxflags=[...]') leaked into
the consumer/rippled build via the conan-generated toolchain
(CMAKE_CXX_FLAGS_INIT). on macOS, where the build action doesn't
override CMAKE_CXX_FLAGS, this would silently apply the workaround flag
to rippled itself.
reshape the input to a json object keyed by Conan package pattern:
{"grpc/*":["-Wno-..."]}
action emits package-pattern scoped lines:
grpc/*:tools.build:cxxflags=["-Wno-..."]
flags only apply while building the matching dependency. consumer
toolchain stays clean. python validator rejects the consumer pattern
('&') and malformed shapes.
* ci: bump apt retries to 5 to handle ppa.launchpadcontent.net flakes
* ci: relax patch coverage for PeerImp
157 lines
6.4 KiB
CMake
157 lines
6.4 KiB
CMake
#[===================================================================[
|
|
Native LLVM source-based code coverage helper.
|
|
|
|
Drives the -fprofile-instr-generate / -fcoverage-mapping pipeline:
|
|
1. Run instrumented binary with LLVM_PROFILE_FILE=...%m-%p.profraw
|
|
2. llvm-profdata merge -sparse -> coverage.profdata
|
|
3. llvm-cov export/show/report -> final report
|
|
|
|
Output filename per coverage_format:
|
|
lcov -> coverage.lcov
|
|
json -> coverage.json
|
|
txt | text -> coverage.txt
|
|
html | html-details -> <NAME>/index.html
|
|
#]===================================================================]
|
|
|
|
include(CMakeParseArguments)
|
|
|
|
# Locate llvm-profdata / llvm-cov, preferring versioned variants matching the
|
|
# Clang we're building with so we don't accidentally pair clang-20 with
|
|
# llvm-cov-14 (profile format mismatch -> hard failure).
|
|
function(_find_llvm_cov_tools)
|
|
if(LLVM_PROFDATA_PATH AND LLVM_COV_PATH)
|
|
return()
|
|
endif()
|
|
|
|
string(REGEX MATCH "^[0-9]+" _major "${CMAKE_CXX_COMPILER_VERSION}")
|
|
|
|
set(_pd_names llvm-profdata)
|
|
set(_cov_names llvm-cov)
|
|
if(_major)
|
|
list(PREPEND _pd_names "llvm-profdata-${_major}")
|
|
list(PREPEND _cov_names "llvm-cov-${_major}")
|
|
endif()
|
|
|
|
# Only delegate to xcrun when the *compiler* is AppleClang. On macOS with
|
|
# Homebrew/system clang-N, xcrun would resolve to Xcode's llvm tools which
|
|
# could be a different version - exactly the mismatch we want to avoid.
|
|
if(APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
|
execute_process(COMMAND xcrun -f llvm-profdata
|
|
OUTPUT_VARIABLE _pd_xcrun OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
ERROR_QUIET RESULT_VARIABLE _pd_rc)
|
|
if(_pd_rc EQUAL 0 AND _pd_xcrun)
|
|
set(LLVM_PROFDATA_PATH "${_pd_xcrun}" CACHE FILEPATH "llvm-profdata" FORCE)
|
|
endif()
|
|
execute_process(COMMAND xcrun -f llvm-cov
|
|
OUTPUT_VARIABLE _cov_xcrun OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
ERROR_QUIET RESULT_VARIABLE _cov_rc)
|
|
if(_cov_rc EQUAL 0 AND _cov_xcrun)
|
|
set(LLVM_COV_PATH "${_cov_xcrun}" CACHE FILEPATH "llvm-cov" FORCE)
|
|
endif()
|
|
endif()
|
|
|
|
if(NOT LLVM_PROFDATA_PATH)
|
|
find_program(LLVM_PROFDATA_PATH NAMES ${_pd_names})
|
|
endif()
|
|
if(NOT LLVM_COV_PATH)
|
|
find_program(LLVM_COV_PATH NAMES ${_cov_names})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(setup_target_for_coverage_llvm)
|
|
set(oneValueArgs NAME FORMAT)
|
|
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
|
cmake_parse_arguments(Cov "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
|
|
_find_llvm_cov_tools()
|
|
if(NOT LLVM_PROFDATA_PATH)
|
|
message(FATAL_ERROR "llvm-profdata not found (needed for coverage_tool=llvm)")
|
|
endif()
|
|
if(NOT LLVM_COV_PATH)
|
|
message(FATAL_ERROR "llvm-cov not found (needed for coverage_tool=llvm)")
|
|
endif()
|
|
|
|
if(NOT Cov_FORMAT)
|
|
set(Cov_FORMAT lcov)
|
|
endif()
|
|
|
|
set(_profraw_dir "${PROJECT_BINARY_DIR}/${Cov_NAME}-profraw")
|
|
set(_profdata "${PROJECT_BINARY_DIR}/${Cov_NAME}.profdata")
|
|
|
|
# Resolve binary path: accept either an absolute path or a bare target name
|
|
# (resolved against PROJECT_BINARY_DIR). Splice the resolved path back into
|
|
# Cov_EXECUTABLE so the run command invokes it via absolute path - bare
|
|
# names aren't on PATH and the build dir isn't `.` either.
|
|
list(GET Cov_EXECUTABLE 0 _exec_name)
|
|
if(IS_ABSOLUTE "${_exec_name}")
|
|
set(_binary "${_exec_name}")
|
|
else()
|
|
set(_binary "${PROJECT_BINARY_DIR}/${_exec_name}")
|
|
list(REMOVE_AT Cov_EXECUTABLE 0)
|
|
list(PREPEND Cov_EXECUTABLE "${_binary}")
|
|
endif()
|
|
|
|
# llvm-cov takes a single -ignore-filename-regex; OR our excludes together.
|
|
set(_ignore_regex "")
|
|
foreach(EXC IN LISTS Cov_EXCLUDE)
|
|
if(_ignore_regex)
|
|
string(APPEND _ignore_regex "|")
|
|
endif()
|
|
string(APPEND _ignore_regex "${EXC}")
|
|
endforeach()
|
|
set(_filter "")
|
|
if(_ignore_regex)
|
|
set(_filter "-ignore-filename-regex='${_ignore_regex}'")
|
|
endif()
|
|
|
|
# Pick llvm-cov subcommand + output file for the requested format. Each
|
|
# branch builds a single shell command string that we'll hand to bash -c.
|
|
if(Cov_FORMAT STREQUAL "lcov")
|
|
set(_output "${PROJECT_BINARY_DIR}/coverage.lcov")
|
|
set(_report_sh "${LLVM_COV_PATH} export -instr-profile='${_profdata}' -format=lcov ${_filter} '${_binary}' > '${_output}'")
|
|
elseif(Cov_FORMAT STREQUAL "json")
|
|
set(_output "${PROJECT_BINARY_DIR}/coverage.json")
|
|
set(_report_sh "${LLVM_COV_PATH} export -instr-profile='${_profdata}' -format=text ${_filter} '${_binary}' > '${_output}'")
|
|
elseif(Cov_FORMAT STREQUAL "txt" OR Cov_FORMAT STREQUAL "text")
|
|
set(_output "${PROJECT_BINARY_DIR}/coverage.txt")
|
|
set(_report_sh "${LLVM_COV_PATH} report -instr-profile='${_profdata}' ${_filter} '${_binary}' > '${_output}'")
|
|
elseif(Cov_FORMAT STREQUAL "html" OR Cov_FORMAT STREQUAL "html-details")
|
|
set(_output "${PROJECT_BINARY_DIR}/${Cov_NAME}/index.html")
|
|
set(_report_sh "${LLVM_COV_PATH} show -instr-profile='${_profdata}' -format=html -output-dir='${PROJECT_BINARY_DIR}/${Cov_NAME}' ${_filter} '${_binary}'")
|
|
else()
|
|
message(FATAL_ERROR "coverage_tool=llvm: unsupported coverage_format '${Cov_FORMAT}' (use lcov|json|txt|html)")
|
|
endif()
|
|
|
|
set(_merge_sh "${LLVM_PROFDATA_PATH} merge -sparse -o '${_profdata}' '${_profraw_dir}'/*.profraw")
|
|
|
|
if(CODE_COVERAGE_VERBOSE)
|
|
message(STATUS "[coverage:llvm] binary: ${_binary}")
|
|
message(STATUS "[coverage:llvm] profraw: ${_profraw_dir}")
|
|
message(STATUS "[coverage:llvm] profdata: ${_profdata}")
|
|
message(STATUS "[coverage:llvm] format: ${Cov_FORMAT}")
|
|
message(STATUS "[coverage:llvm] output: ${_output}")
|
|
if(_ignore_regex)
|
|
message(STATUS "[coverage:llvm] ignore: ${_ignore_regex}")
|
|
endif()
|
|
message(STATUS "[coverage:llvm] merge: ${_merge_sh}")
|
|
message(STATUS "[coverage:llvm] report: ${_report_sh}")
|
|
endif()
|
|
|
|
# %m: hash of the binary, %p: pid. Wipe the dir up front so stale profraw
|
|
# files can't leak into a fresh merge.
|
|
add_custom_target(${Cov_NAME}
|
|
COMMAND ${CMAKE_COMMAND} -E rm -rf "${_profraw_dir}"
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${_profraw_dir}"
|
|
COMMAND ${CMAKE_COMMAND} -E env
|
|
"LLVM_PROFILE_FILE=${_profraw_dir}/rippled-%m-%p.profraw"
|
|
${Cov_EXECUTABLE} ${Cov_EXECUTABLE_ARGS}
|
|
COMMAND bash -c "${_merge_sh}"
|
|
COMMAND bash -c "${_report_sh}"
|
|
BYPRODUCTS ${_output}
|
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
DEPENDS ${Cov_DEPENDENCIES}
|
|
VERBATIM
|
|
COMMENT "Running llvm-cov (${Cov_FORMAT}) -> ${_output}"
|
|
)
|
|
endfunction()
|