Add coverage and coverage-gcov features

Features enable code coverage collecting using the gcov tool. The
resulting reports can then be post-processed by lcov or similar tools.

[ChangeLog][CMake][Coverage] Added the coverage configuration argument.
The only supported coverage tool at the moment is gcov. The argument
requires Qt is built in Debug otherwise setting the argument leads to
the configuration error. Typical usage:
  <...>/configure -developer-build -coverage gcov

Task-number: QTBUG-86223
Change-Id: I39b2061f544997a7c4fe6f4d135c0ab447f15a17
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Alexey Edelev 2023-09-13 16:31:52 +02:00
parent f2ec221bd6
commit 42d2944191
6 changed files with 63 additions and 1 deletions

View File

@ -361,6 +361,15 @@ if(QT_FEATURE_enable_new_dtags)
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,--enable-new-dtags") qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,--enable-new-dtags")
endif() endif()
function(qt_internal_apply_coverage_flags)
if(QT_FEATURE_coverage_gcov)
target_compile_options(PlatformCommonInternal INTERFACE
"$<$<CONFIG:Debug>:-fprofile-arcs;-ftest-coverage>")
target_link_options(PlatformCommonInternal INTERFACE "$<$<CONFIG:Debug>:-lgcov;--coverage>")
endif()
endfunction()
qt_internal_apply_coverage_flags()
function(qt_get_implicit_sse2_genex_condition out_var) function(qt_get_implicit_sse2_genex_condition out_var)
set(is_shared_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>") set(is_shared_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>")
set(is_static_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>") set(is_static_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>")

View File

@ -934,6 +934,29 @@ if(INPUT_force_debug_info)
list(TRANSFORM build_configs REPLACE "^Release$" "RelWithDebInfo") list(TRANSFORM build_configs REPLACE "^Release$" "RelWithDebInfo")
endif() endif()
# Code coverage handling
drop_input(gcov)
if(INPUT_gcov)
if(NOT "${INPUT_coverage}" STREQUAL "")
if(NOT "${INPUT_coverage}" STREQUAL "gcov")
qtConfAddError("The -gcov argument is provided, but -coverage is set"
" to ${INPUT_coverage}")
endif()
else()
set(INPUT_coverage "gcov")
list(APPEND config_inputs coverage)
endif()
endif()
if(NOT "${INPUT_coverage}" STREQUAL "")
if(build_configs)
if(NOT "Debug" IN_LIST build_configs)
qtConfAddError("The -coverage argument requires Qt configured with 'Debug' config.")
endif()
else()
set(build_configs "Debug")
endif()
endif()
list(LENGTH build_configs nr_of_build_configs) list(LENGTH build_configs nr_of_build_configs)
if(nr_of_build_configs EQUAL 1 AND NOT multi_config) if(nr_of_build_configs EQUAL 1 AND NOT multi_config)
push("-DCMAKE_BUILD_TYPE=${build_configs}") push("-DCMAKE_BUILD_TYPE=${build_configs}")

View File

@ -46,7 +46,8 @@ The following table describes the mapping of configure options to CMake argument
| -appstore-compliant | -DFEATURE_appstore_compliant=ON | | | -appstore-compliant | -DFEATURE_appstore_compliant=ON | |
| -qtnamespace <name> | -DQT_NAMESPACE=<name> | | | -qtnamespace <name> | -DQT_NAMESPACE=<name> | |
| -qtlibinfix <infix> | -DQT_LIBINFIX=<infix> | | | -qtlibinfix <infix> | -DQT_LIBINFIX=<infix> | |
| -gcov | | | | -coverage <tool> | -DINPUT_coverage=<tool> | Enables code coverage using the specified tool. |
| -gcov | -DINPUT_coverage=gcov | Enables code coverage using the gcov tool. |
| -trace [backend] | -DINPUT_trace=yes or -DINPUT_trace=<backend> | | | -trace [backend] | -DINPUT_trace=yes or -DINPUT_trace=<backend> | |
| | or -DFEATURE_<backend> | | | | or -DFEATURE_<backend> | |
| -sanitize address -sanitize undefined | -DFEATURE_sanitize_address=ON | Directly setting -DECM_ENABLE_SANITIZERS=foo is not supported | | -sanitize address -sanitize undefined | -DFEATURE_sanitize_address=ON | Directly setting -DECM_ENABLE_SANITIZERS=foo is not supported |

View File

@ -103,6 +103,7 @@ Build options:
-qtnamespace <name> .. Wrap all Qt library code in 'namespace <name> {...}'. -qtnamespace <name> .. Wrap all Qt library code in 'namespace <name> {...}'.
-qtlibinfix <infix> .. Rename all libQt6*.so to libQt6*<infix>.so. -qtlibinfix <infix> .. Rename all libQt6*.so to libQt6*<infix>.so.
-coverage <tool> ..... Instrument with the code coverage tool.
-gcov ................ Instrument with the GCov code coverage tool [no] -gcov ................ Instrument with the GCov code coverage tool [no]
-trace [backend] ..... Enable instrumentation with tracepoints. -trace [backend] ..... Enable instrumentation with tracepoints.

View File

@ -1049,6 +1049,33 @@ qt_feature("intelcet" PRIVATE
LABEL "Using Intel CET" LABEL "Using Intel CET"
CONDITION ( INPUT_intelcet STREQUAL yes ) OR TEST_intelcet CONDITION ( INPUT_intelcet STREQUAL yes ) OR TEST_intelcet
) )
if("${INPUT_coverage}" STREQUAL "gcov")
qt_config_compile_test(gcov
LABEL "gcov compiler flags"
COMPILE_OPTIONS "-fprofile-arcs -ftest-coverage"
CODE
"int main(void)
{
/* BEGIN TEST: */
/* END TEST: */
return 0;
}
")
endif()
qt_feature("coverage-gcov"
LABEL "Gcov"
ENABLE INPUT_coverage STREQUAL "gcov"
CONDITION TEST_gcov AND
( QT_FEATURE_debug OR QT_FEATURE_debug_and_release )
)
qt_feature("coverage"
LABEL "Coverage"
CONDITION QT_FEATURE_coverage_gcov
)
qt_configure_add_summary_build_type_and_config() qt_configure_add_summary_build_type_and_config()
qt_configure_add_summary_section(NAME "Build options") qt_configure_add_summary_section(NAME "Build options")
qt_configure_add_summary_build_mode(Mode) qt_configure_add_summary_build_mode(Mode)

View File

@ -122,6 +122,7 @@ qt_commandline_option(widgets TYPE boolean)
qt_commandline_option(xplatform TYPE string) qt_commandline_option(xplatform TYPE string)
qt_commandline_option(zlib TYPE enum NAME system-zlib MAPPING system yes qt no) qt_commandline_option(zlib TYPE enum NAME system-zlib MAPPING system yes qt no)
qt_commandline_option(zstd TYPE boolean) qt_commandline_option(zstd TYPE boolean)
qt_commandline_option(coverage TYPE optionalString VALUES gcov)
qt_commandline_prefix(D defines) qt_commandline_prefix(D defines)
qt_commandline_prefix(F fpaths) qt_commandline_prefix(F fpaths)
qt_commandline_prefix(I includes) qt_commandline_prefix(I includes)