-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmake: Add Coverage
script
#191
Conversation
5989b1f
to
fb5f30a
Compare
Included changes from bitcoin#30063. |
@maflcko Want to tested this PR in your https://github.com/maflcko/b-c-cov? |
execute_process( | ||
COMMAND ${LCOV_FILTER_COMMAND} test_bitcoin.info test_bitcoin_filtered.info | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file consists mostly of such execute_process()
calls. The most natural way to execute a bunch of commands is from a shell script. I would suggest to use a shell script for this. This 77 lines cmake file would be equivalent roughly to the following:
functional_test_runner="test/functional/test_runner.py"
if [ -n "$EXTENDED_FUNCTIONAL_TESTS" ] ; then
functional_test_runner="$functional_test_runner --extended"
fi
if [ -n "$JOBS" ] ; then
CMAKE_CTEST_COMMAND="$CMAKE_CTEST_COMMAND -j $JOBS"
functional_test_runner="$functional_test_runner -j $JOBS"
fi
cd $CMAKE_CURRENT_LIST_DIR
$CMAKE_CTEST_COMMAND --build-config Coverage
$LCOV_COMMAND --capture --directory src --test-name test_bitcoin --output-file test_bitcoin.info
$LCOV_COMMAND --zerocounters --directory src
$LCOV_FILTER_COMMAND test_bitcoin.info test_bitcoin_filtered.info
$LCOV_COMMAND --add-tracefile test_bitcoin_filtered.info --output-file test_bitcoin_filtered.info
$LCOV_COMMAND --add-tracefile baseline_filtered.info --add-tracefile test_bitcoin_filtered.info --output-file test_bitcoin_coverage.info
$GENHTML_COMMAND test_bitcoin_coverage.info --output-directory test_bitcoin.coverage
$functional_test_runner
$LCOV_COMMAND --capture --directory src --test-name functional-tests --output-file functional_test.info
$LCOV_COMMAND --zerocounters --directory src
$LCOV_FILTER_COMMAND functional_test.info functional_test_filtered.info
$LCOV_COMMAND --add-tracefile functional_test_filtered.info --output-file functional_test_filtered.info
$LCOV_COMMAND --add-tracefile baseline_filtered.info --add-tracefile test_bitcoin_filtered.info --add-tracefile functional_test_filtered.info --output-file total_coverage.info | $GREP_EXECUTABLE "%" | $AWK_EXECUTABLE "{ print substr($3,2,50) \"/\" $5 }" > coverage_percent.txt
$GENHTML_COMMAND total_coverage.info --output-directory total.coverage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The most natural way to execute a bunch of commands is from a shell script. I would suggest to use a shell script for this.
From CMake's point of view, using a platform independent approach is more natural :)
However, I have to admit that it is not expected that the user will run coverage scripts on Windows.
if("@CMAKE_CXX_COMPILER_ID@" STREQUAL "Clang") | ||
find_program(LLVM_COV_EXECUTABLE llvm-cov REQUIRED) | ||
set(COV_TOOL "${LLVM_COV_EXECUTABLE} gcov") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clang has a different native workflow: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html which I guess produces better results compared to its gcc compatibility layer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. But this PR aims to mirror the master branch behaviour. Further improvements can be done later, no?
./configure --enable-lcov | ||
make | ||
make cov | ||
cmake -B build -DCMAKE_BUILD_TYPE=Coverage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think with/without coverage should be independent option from debug/release. For example one may want to gather coverage on debug builds or release builds? I do not think we need a dedicated build type "Coverage" in order to pass a few extra flags which is already supported by the build system with APPEND_..._FLAGS
.
For clang, that would be extra -fprofile-instr-generate -fcoverage-mapping
and compiling and running the tests as usual. I guess for gcc that would be --coverage
instead.
I know this would be different from how autotools works, but I would propose to have a shell script in contrib/
that compiles with coverage enabled (e.g. by running cmake -DAPPEND_..._FLAGS="-fprofile-instr-generate -fcoverage-mapping"
), then runs the tests and gathers the coverage (actually 2 shell scripts - one for clang and one for gcc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example one may want to gather coverage on debug builds or release builds?
Is this something that is commonly done? What would the purpose of this be?
I know this would be different from how autotools works, but I would propose to have a shell script
Not sure about this. I prefer to work with the build system directly without having to understand a wrapper script first if I want to tweak something.
b675988
to
8321299
Compare
|
Friendly ping code coverage connoisseurs @maflcko @dergoegge :) Your opinion will be much appreciated by all people in the CMake working group. |
@ONLY | ||
) | ||
|
||
set(LCOV_OPTS --ignore mismatch) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should be hardcoded here (it's not needed with lcov 1.x, and isn't the only ignore that might be required with 2.x)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Deleted.
Addressed the recent @fanquake's comments. The doc change has been aligned with bitcoin#30192. |
doc/developer-notes.md
Outdated
./configure --enable-lcov | ||
make | ||
make cov | ||
cmake -B build --preset coverage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is different from the examples in the PR description and also skips building the fuzz binary, is that expected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example in the PR description also does not build the fuzz binary:
Tests:
test_bitcoin ........................ ON
test_bitcoin-qt ..................... OFF
bench_bitcoin ....................... OFF
fuzz binary ......................... OFF
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR description has been updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UPD. Added --ignore-errors mismatch
Re-tested, fixed bugs. Reverted back to use of the "Coverage" build type because this guarantees that the The PR description has been updated. |
CMakeLists.txt
Outdated
@@ -484,6 +484,22 @@ else() | |||
unset(c_flags_debug_overridden) | |||
endif() | |||
|
|||
set(CMAKE_CXX_FLAGS_COVERAGE "-Og --coverage -fprofile-update=prefer-atomic") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fprofile-update=prefer-atomic
Not sure this should be in here? Don't think it's needed with Clang, and only sometimes with GCC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it hurt if applied in such cases? Or do you want me to remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this should be in here?
Deleted.
The PR description has been updated.
My lcov version is quite old (1.0), maybe that's why this fails. I've had to fiddle with the versions in the past and I'm sure this would work with the right versions etc. (everything seemed to work here besides the actual html generation). I've switched to using llvm's native coverage reporting (i.e. compiling with |
Rebased. |
In the first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
This
|
Further improvements, that would deviate from autotools:
|
Using separated scripts provides additional flexibility as there is no need to specify coverage report specific options during the build configuration stage.
Examples of usage on Ubuntu 24.04 with LCOV v2.0:
This PR supports both LCOV v1 and LCOV v2. Hence, it is possible to test it on Ubuntu 24.04.