split lcov and genhtml cmake opts for the Coverage profile#224
split lcov and genhtml cmake opts for the Coverage profile#224tevio wants to merge 9 commits intobitcoinknots:29.x-knotsfrom
Conversation
fa8fc63 to
7aa60c6
Compare
kwsantiago
left a comment
There was a problem hiding this comment.
I recommend moving lines 5-17 to after the find_program() calls (after line 40) to ensure variables exist before use.
build the Coverage profile, run the tests and generate the lcov html
reports with:
cmake -S . -B ${PWD}/cmake-build-debug -DCMAKE_BUILD_TYPE=Coverage
cmake --build ${PWD}/cmake-build-debug
LCOV_OPTS="--ignore-errors inconsistent,gcov,source,format --base-directory ${PWD}/src --rc geninfo_auto_base=1" GENHTML_OPTS="--ignore-errors unsupported,inconsistent,count,category --filter missing" cmake -P ${PWD}/cmake-build-debug/Coverage.cmake
e4b821d to
842bf4f
Compare
kwsantiago
left a comment
There was a problem hiding this comment.
Previously genhtml incorrectly received LCOV_OPTS
Now that they are properly separated, you may want to document the behavior change to confirm no one was relying on passing genhtml options via LCOV_OPTS
Also may want to rename HTML_OPTS to GENHTML_OPTS throughout for consistency and clarity.
hi @kwsantiago yes I was thinking about that yesterday in the point you make about confirming no one was relying on passing LCOV_OPTS - haven't tried it yet but could solve it by falling back to LCOV_OPTS by default and then only overriding with HTML_OPTS if it's passed and that way no ones existing setups would be affected |
…option (not envvar), update doc ref
842bf4f to
b71b968
Compare
doc/developer-notes.md
Outdated
| ``` | ||
|
|
||
| HTML_OPTS can be specified to provide an options override to genhtml from the default LCOV_OPTS, the program that generates the | ||
| html report from lcov: `HTML_OPTS="--exclude boost"`. |
There was a problem hiding this comment.
Have you tested this?
From my understanding, --exclude boost is a lcov option not a genhtml option, so this example will fail.
There was a problem hiding this comment.
it is an option for both lcov and genhtml - so I've used it as a reference, certainly tested it to filter out the boost entries in the coverage report, however, because there is currently no genhtml distribution in homebrew you need to install a custom binary which may or may not support the same options. In my case the version I'm using doesn't support the same options.
There was a problem hiding this comment.
might be better to provide a reference in the docs for a compatible genhtml implementation that would officially "work" on macOs/windows (if it exists) that would render this OPTS overriding change irrelevant, but I don't know what that is or would look like currently
kwsantiago
left a comment
There was a problem hiding this comment.
Looks good but the _HTML_OPTS_WAS_DEFINED pattern seems overly complex.
| # If HTML_OPTS is not provided at all, implicitly pass LCOV_OPTS to genhtml. | ||
| # If HTML_OPTS is provided but empty (e.g. -DHTML_OPTS=""), use an empty list | ||
| # and do NOT inherit LCOV_OPTS. | ||
| set(_HTML_OPTS_WAS_DEFINED FALSE) |
There was a problem hiding this comment.
Why track _HTML_OPTS_WAS_DEFINED separately instead of checking DEFINED HTML_OPTS directly in line 37?
There was a problem hiding this comment.
@kwsantiago I've tried removing that and it doesn't cause an obvious issue but because separate_arguments(HTML_OPTS) (called earlier) creates/modifies the HTML_OPTS variable, if you checked if(DEFINED HTML_OPTS) after that, it would always be true, losing the ability to distinguish “user didn’t provide HTML_OPTS” from “user provided it (possibly empty)”. The _HTML_OPTS_WAS_DEFINED flag captured whether it was defined before separate_arguments() ran.
There was a problem hiding this comment.
this is probably the cleanest way, setting the default to LCOV_OPTS, but I need to test:
# HTML_OPTS is optionally passed via -D flag.
-# If HTML_OPTS is not provided at all, implicitly pass LCOV_OPTS to genhtml.
-# If HTML_OPTS is provided but empty (e.g. -DHTML_OPTS=""), use an empty list
-# and do NOT inherit LCOV_OPTS.
-set(_HTML_OPTS_WAS_DEFINED FALSE)
+# Default: inherit LCOV_OPTS. If HTML_OPTS is provided (even if empty), use it instead.
+set(GENHTML_OPTS ${LCOV_OPTS})
if(DEFINED HTML_OPTS)
- set(_HTML_OPTS_WAS_DEFINED TRUE)
-endif()
-separate_arguments(HTML_OPTS)
-if(_HTML_OPTS_WAS_DEFINED)
+ separate_arguments(HTML_OPTS)
set(GENHTML_OPTS ${HTML_OPTS})
-else()
- set(GENHTML_OPTS ${LCOV_OPTS})
endif()
set(GENHTML_COMMAND ${GENHTML_EXECUTABLE} --show-details ${GENHTML_OPTS})There was a problem hiding this comment.
@kwsantiago with regards to this change b581b44 I've tested this locally and for brevity just summarised the output here: tl;dr: each mode renders a different result on my machine and the only one that succeeds is when passing the specific HTML_OPTS (not empty)
The three modes:
1) pass specific HTML_OPTS
rm -rf build
cmake -S . -B build -DCMAKE_BUILD_TYPE=Coverage
cmake --build build
TMPDIR=/tmp LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 cmake -DLCOV_OPTS="--ignore-errors inconsistent,gcov,source,format --base-directory $(pwd -P)/src --rc geninfo_auto_base=1" -DHTML_OPTS="--ignore-errors unsupported,inconsistent,count,category --filter missing" -P build/Coverage.cmake
should complete and generate coverage report:
Overall coverage rate:
source files: 762
lines.......: 87.5% (101483 of 115966 lines)
functions...: 78.2% (33941 of 43392 functions)
Message summary:
200 warning messages:
category: 100
inconsistent: 100
1361 ignore messages:
category: 351
count: 2
inconsistent: 1007
unsupported: 1
➜ bitcoin-knots git:(rcov-and-genhtml)
2) pass empty HTML_OPTS
TMPDIR=/tmp LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 cmake -DLCOV_OPTS="--ignore-errors inconsistent,gcov,source,format --base-directory $(pwd -P)/src --rc geninfo_auto_base=1" -DHTML_OPTS="" -P build/Coverage.cmake
was previously untested but now fails with a corrupt trace error:
Reading tracefile test_bitcoin_coverage.info.
genhtml: ERROR: (corrupt) unable to read trace file 'test_bitcoin_coverage.info': genhtml: ERROR: (inconsistent) "./bitcoin-knots/src/wallet/coincontrol.h":27: function '_ZN6wallet16PreselectedInputC1Ev' is hit but no contained lines are hit.
To skip consistency checks, see the 'check_data_consistency' section in man lcovrc(5).
(use "genhtml --ignore-errors inconsistent ..." to bypass this error)
(use "genhtml --ignore-errors corrupt ..." to bypass this error)
CMake Error at build/Coverage.cmake:46 (execute_process):
execute_process failed command indexes:
1: "Child return code: 1"
2) Do not pass HTML_OPTS (fall through to LCOV_OPTS)
TMPDIR=/tmp LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 cmake -DLCOV_OPTS="--ignore-errors inconsistent,gcov,source,format --base-directory $(pwd -P)/src --rc geninfo_auto_base=1" -P build/Coverage.cmake
should fail as it did, with unknown options:
lcov: WARNING: (count) max_message_count=100 reached for 'inconsistent' messages: no more will be reported.
To increase or decrease this limit use '--rc max_message_count=value'.
(use "lcov --ignore-errors count,count ..." to suppress this warning)
Combining tracefiles.
.. found 2 files to aggregate.
Combining tracefiles.
Merging baseline_filtered.info..1 remaining
Merging test_bitcoin_filtered.info..0 remaining
Writing data to test_bitcoin_coverage.info
Summary coverage rate:
source files: 762
lines.......: 69.4% (80524 of 115966 lines)
functions...: 70.1% (30439 of 43392 functions)
Message summary:
102 warning messages:
count: 1
inconsistent: 100
unsupported: 1
1544 ignore messages:
inconsistent: 1544
genhtml: WARNING: Unknown option: base-directory
Use genhtml --help to get usage information
CMake Error at build/Coverage.cmake:46 (execute_process):
execute_process failed command indexes: 1: "Child return code: 1"
| if(DEFINED HTML_OPTS) | ||
| set(_HTML_OPTS_WAS_DEFINED TRUE) | ||
| endif() | ||
| separate_arguments(HTML_OPTS) |
There was a problem hiding this comment.
Should separate_arguments(HTML_OPTS) be called after checking if it's defined to avoid modifying an undefined variable?
|
|
||
| HTML_OPTS can be specified to provide an options override to genhtml from the default LCOV_OPTS, the program that generates the | ||
| html report from lcov: `HTML_OPTS="--exclude boost"`. | ||
| HTML_OPTS can override the genhtml options (which default to LCOV_OPTS). If HTML_OPTS is omitted, LCOV_OPTS are implicitly passed to genhtml. If HTML_OPTS is provided but empty (e.g. -DHTML_OPTS=""), no options are passed to genhtml and LCOV_OPTS are not inherited. |
There was a problem hiding this comment.
May want to add an example showing combined use of both LCOV_OPTS and HTML_OPTS to clarify precedence.
055bb3e to
97a898f
Compare
|
Is there a reason not to submit this through bitcoin/bitcoin? |
|
|
||
| # HTML_OPTS is optionally passed via -D flag. | ||
| # Default: inherit LCOV_OPTS. If HTML_OPTS is provided (even if empty), use it instead. | ||
| set(GENHTML_OPTS ${LCOV_OPTS}) |
There was a problem hiding this comment.
Is there a reason why we can't be consistent with the naming, either GENHTML_OPTS or HTML_OPTS
| # Default: inherit LCOV_OPTS. If HTML_OPTS is provided (even if empty), use it instead. | ||
| set(GENHTML_OPTS ${LCOV_OPTS}) | ||
| if(DEFINED HTML_OPTS) | ||
| separate_arguments(HTML_OPTS) |
There was a problem hiding this comment.
What happens if LCOV_OPTS is not defined? Does cmake create an empty variable or error?
| cmake -DLCOV_OPTS="--rc branch_coverage=1" -P build/Coverage.cmake | ||
| ``` | ||
|
|
||
| HTML_OPTS can override the genhtml options (which default to LCOV_OPTS). If HTML_OPTS is omitted, LCOV_OPTS are implicitly passed to genhtml. If HTML_OPTS is provided but empty (e.g. -DHTML_OPTS=""), no options are passed to genhtml and LCOV_OPTS are not inherited. |
There was a problem hiding this comment.
What if LCOV_OPTS is also not set? Does it default to empty?
hi @luke-jr thanks! well, mainly a lack of motivation to contribute to that project, what would be the benefit please? |
Summary
Introduce
HTML_OPTSforgenhtmlwith a sensible default: inheritLCOV_OPTSwhenHTML_OPTSis not provided. This removes duplication for shared settings while keeping a clear escape hatch forgenhtml-specific control.Background (previous behavior)
genhtml) always receivedLCOV_OPTS.--rcflags likebranch_coverage=1) but made it awkward to pass options that apply only togenhtml.What’s changing
HTML_OPTS, forgenhtml.HTML_OPTSis omitted, passLCOV_OPTStogenhtml(maintains the historical behavior and keeps shared config in sync).HTML_OPTSis provided, use it instead ofLCOV_OPTSforgenhtml.HTML_OPTSis explicitly set to an empty string, pass no extra options togenhtmland do not inheritLCOV_OPTS.Why this change
lcovandgenhtmlare separate tools with partially overlapping options.--rc), but some aregenhtml-only (e.g.,--title).genhtmlwhen needed.User-facing behavior
genhtmlreceivesLCOV_OPTSautomatically.genhtmlreceivesHTML_OPTSinstead ofLCOV_OPTS.genhtmlreceives no options; nothing is inherited.Examples
Implementation notes
cmake/script/CoverageInclude.cmake.in:HTML_OPTSwas defined (even if empty) before splitting.GENHTML_OPTStoHTML_OPTSwhen defined; otherwise fall back toLCOV_OPTS.GENHTML_COMMANDwithGENHTML_OPTS.Key snippet:
Backward compatibility
HTML_OPTSis omitted,genhtmlstill receivesLCOV_OPTS.HTML_OPTScontinue to behave as before.genhtmloptions via-DHTML_OPTS="".Documentation
doc/developer-notes.mdto describe the default inheritance, the explicit override, and the empty override, with examples using agenhtml-only flag (--title).Impact and risk
genhtml-specific customization and intentional minimalism.