From 42d29441914da263a160d631f56c6d95f85eac70 Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Wed, 13 Sep 2023 16:31:52 +0200 Subject: [PATCH] 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 --- cmake/QtInternalTargets.cmake | 9 +++++++++ cmake/QtProcessConfigureArgs.cmake | 23 +++++++++++++++++++++++ cmake/configure-cmake-mapping.md | 3 ++- config_help.txt | 1 + configure.cmake | 27 +++++++++++++++++++++++++++ qt_cmdline.cmake | 1 + 6 files changed, 63 insertions(+), 1 deletion(-) diff --git a/cmake/QtInternalTargets.cmake b/cmake/QtInternalTargets.cmake index 043d2ca4960..ec71ded3590 100644 --- a/cmake/QtInternalTargets.cmake +++ b/cmake/QtInternalTargets.cmake @@ -361,6 +361,15 @@ if(QT_FEATURE_enable_new_dtags) qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,--enable-new-dtags") endif() +function(qt_internal_apply_coverage_flags) + if(QT_FEATURE_coverage_gcov) + target_compile_options(PlatformCommonInternal INTERFACE + "$<$:-fprofile-arcs;-ftest-coverage>") + target_link_options(PlatformCommonInternal INTERFACE "$<$:-lgcov;--coverage>") + endif() +endfunction() +qt_internal_apply_coverage_flags() + function(qt_get_implicit_sse2_genex_condition out_var) set(is_shared_lib "$,SHARED_LIBRARY>") set(is_static_lib "$,STATIC_LIBRARY>") diff --git a/cmake/QtProcessConfigureArgs.cmake b/cmake/QtProcessConfigureArgs.cmake index b5ea3707524..ccae19e5921 100644 --- a/cmake/QtProcessConfigureArgs.cmake +++ b/cmake/QtProcessConfigureArgs.cmake @@ -934,6 +934,29 @@ if(INPUT_force_debug_info) list(TRANSFORM build_configs REPLACE "^Release$" "RelWithDebInfo") 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) if(nr_of_build_configs EQUAL 1 AND NOT multi_config) push("-DCMAKE_BUILD_TYPE=${build_configs}") diff --git a/cmake/configure-cmake-mapping.md b/cmake/configure-cmake-mapping.md index 75c7fd3b2cf..5ccd4964def 100644 --- a/cmake/configure-cmake-mapping.md +++ b/cmake/configure-cmake-mapping.md @@ -46,7 +46,8 @@ The following table describes the mapping of configure options to CMake argument | -appstore-compliant | -DFEATURE_appstore_compliant=ON | | | -qtnamespace | -DQT_NAMESPACE= | | | -qtlibinfix | -DQT_LIBINFIX= | | -| -gcov | | | +| -coverage | -DINPUT_coverage= | 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= | | | | or -DFEATURE_ | | | -sanitize address -sanitize undefined | -DFEATURE_sanitize_address=ON | Directly setting -DECM_ENABLE_SANITIZERS=foo is not supported | diff --git a/config_help.txt b/config_help.txt index 7681b5f79f8..c360c8fdd1b 100644 --- a/config_help.txt +++ b/config_help.txt @@ -103,6 +103,7 @@ Build options: -qtnamespace .. Wrap all Qt library code in 'namespace {...}'. -qtlibinfix .. Rename all libQt6*.so to libQt6*.so. + -coverage ..... Instrument with the code coverage tool. -gcov ................ Instrument with the GCov code coverage tool [no] -trace [backend] ..... Enable instrumentation with tracepoints. diff --git a/configure.cmake b/configure.cmake index 508aa7782ec..43fa7d4812b 100644 --- a/configure.cmake +++ b/configure.cmake @@ -1049,6 +1049,33 @@ qt_feature("intelcet" PRIVATE LABEL "Using Intel CET" 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_section(NAME "Build options") qt_configure_add_summary_build_mode(Mode) diff --git a/qt_cmdline.cmake b/qt_cmdline.cmake index b655bdcc5ed..14df26e0a26 100644 --- a/qt_cmdline.cmake +++ b/qt_cmdline.cmake @@ -122,6 +122,7 @@ qt_commandline_option(widgets TYPE boolean) qt_commandline_option(xplatform TYPE string) qt_commandline_option(zlib TYPE enum NAME system-zlib MAPPING system yes qt no) qt_commandline_option(zstd TYPE boolean) +qt_commandline_option(coverage TYPE optionalString VALUES gcov) qt_commandline_prefix(D defines) qt_commandline_prefix(F fpaths) qt_commandline_prefix(I includes)