Merge branch 'move_gcov_to_component_registry' into 'master'

Move gcov to component registry

Closes IDF-13404 and DOC-11978

See merge request espressif/esp-idf!40752
This commit is contained in:
Erhan Kurubas
2025-08-13 19:29:34 +02:00
20 changed files with 109 additions and 603 deletions

View File

@@ -464,130 +464,7 @@ Start 子命令语法:
.. _app_trace-gcov-source-code-coverage:
Gcov源代码覆盖
Gcov源代码覆盖
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Gcov 和 Gcovr 简介
""""""""""""""""""""""""
源代码覆盖率显示程序运行时间内执行的每一条程序执行路径的数量和频率。`Gcov <https://en.wikipedia.org/wiki/Gcov>`_ 是一款 GCC 工具,与编译器协同使用时,可生成日志文件,显示源文件每行的执行次数。`Gcovr <https://gcovr.com/>`_ 是管理 Gcov 和生成代码覆盖率总结的工具。
一般来说,使用 Gcov 在主机上编译和运行程序会经过以下步骤:
1. 使用 GCC 以及 ``--coverage`` 选项编译源代码。编译器会在编译过程中生成一个 ``.gcno`` 注释文件,该文件包含重建执行路径块图以及将每个块映射到源代码行号等信息。每个用 ``--coverage`` 选项编译的源文件都会生成自己的同名 ``.gcno`` 文件(如 ``main.c`` 在编译时会生成 ``main.gcno``)。
2. 执行程序。在执行过程中,程序会生成 ``.gcda`` 数据文件。这些数据文件包含了执行路径的次数统计。程序将为每个用 ``--coverage`` 选项编译的源文件生成一个 ``.gcda`` 文件(如 ``main.c`` 将生成 ``main.gcda``)。
3. Gcov 或 Gcovr 可用于生成基于 ``.gcno````.gcda`` 和源文件的代码覆盖。Gcov 将以 ``.gcov`` 文件的形式为每个源文件生成基于文本的覆盖报告,而 Gcovr 将以 HTML 格式生成覆盖报告。
ESP-IDF 中的 Gcov 和 Gcovr 应用
"""""""""""""""""""""""""""""""""
在 ESP-IDF 中使用 Gcov 的过程比较复杂,因为程序不在主机上运行,而在目标机上运行。代码覆盖率数据(即 ``.gcda`` 文件最初存储在目标机上OpenOCD 在运行时通过 JTAG 将代码覆盖数据从目标机转储到主机上。在 ESP-IDF 中使用 Gcov 可以分为以下几个步骤:
1. :ref:`app_trace-gcov-setup-project`
2. :ref:`app_trace-gcov-dumping-data`
3. :ref:`app_trace-gcov-generate-report`
.. _app_trace-gcov-setup-project:
为 Gcov 设置项目
"""""""""""""""""""""""""""""""
编译器选项
~~~~~~~~~~~~~~~
为了获取项目中的代码覆盖率数据,必须用 ``--coverage`` 选项编译项目中的一个或多个源文件。在 ESP-IDF 中,这可以在组件级或单个源文件级实现:
- 在组件的 ``CMakeLists.txt`` 文件中添加 ``target_compile_options(${COMPONENT_LIB} PRIVATE --coverage)`` 可确保使用 ``--coverage`` 选项编译组件中的所有源文件。
- 在组件的 ``CMakeLists.txt`` 文件中添加 ``set_source_files_properties(source1.c source2.c PROPERTIES COMPILE_FLAGS --coverage)`` 可确保使用 ``--coverage`` 选项编译同一组件中选定的一些源文件(如 ``source1.c````source2.c``)。
当一个源文件用 ``--coverage`` 选项编译时(例如 ``gcov_example.c``),编译器会在项目的构建目录下生成 ``gcov_example.gcno`` 文件。
项目配置
~~~~~~~~~~~~~~~~~
在构建有源代码覆盖的项目之前,请运行 ``idf.py menuconfig`` 以启用以下项目配置选项。
- 通过 :ref:`CONFIG_APPTRACE_DESTINATION1` 选项选择 ``Trace Memory`` 来启用应用程序跟踪模块。
- 通过 :ref:`CONFIG_APPTRACE_GCOV_ENABLE` 选项启用 Gcov 主机。
.. _app_trace-gcov-dumping-data:
转储代码覆盖数据
""""""""""""""""""""""""""
一旦项目使用 ``--coverage`` 选项编译并烧录到目标机上,在应用程序运行时,代码覆盖数据将存储在目标机内部(即在跟踪存储器中)。将代码覆盖率数据从目标机转移到主机上的过程称为转储。
覆盖率数据的转储通过 OpenOCD 进行(关于如何设置和运行 OpenOCD请参考 :doc:`JTAG 调试 <../api-guides/jtag-debugging/index>`)。由于该过程需要通过向 OpenOCD 发出命令来触发转储,因此必须打开 telnet 会话,以向 OpenOCD 发出这些命令(运行 ``telnet localhost 4444``。GDB 也可以代替 telnet 来向 OpenOCD 发出命令,但是所有从 GDB 发出的命令都需要以 ``mon <oocd_command>`` 为前缀。
当目标机转储代码覆盖数据时,``.gcda`` 文件存储在项目的构建目录中。例如,如果 ``main`` 组件的 ``gcov_example_main.c`` 在编译时使用了 ``--coverage`` 选项,那么转储代码覆盖数据将在 ``build/esp-idf/main/CMakeFiles/__idf_main.dir/gcov_example_main.c.gcda`` 中生成 ``gcov_example_main.gcda`` 文件。注意,编译过程中产生的 ``.gcno`` 文件也放在同一目录下。
代码覆盖数据的转储可以在应用程序的整个生命周期内多次进行。每次转储都会用最新的代码覆盖信息更新 ``.gcda`` 文件。代码覆盖数据是累积的,因此最新的数据将包含应用程序整个生命周期中每个代码路径的总执行次数。
ESP-IDF 支持两种将代码覆盖数据从目标机转储到主机的方法:
* 运行中实时转储
* 硬编码转储
运行中实时转储
~~~~~~~~~~~~~~~~~~~~~
通过 telnet 会话调用 OpenOCD 命令 ``{IDF_TARGET_NAME} gcov`` 来触发运行时的实时转储。一旦被调用OpenOCD 将立即抢占 {IDF_TARGET_NAME} 的当前状态,并执行内置的 ESP-IDF Gcov 调试存根函数。调试存根函数将数据转储到主机。完成后,{IDF_TARGET_NAME} 将恢复当前状态。
硬编码转储
~~~~~~~~~~~~~~~
硬编码转储是由应用程序本身从程序内部调用 :cpp:func:`esp_gcov_dump` 函数触发的。在调用时,应用程序将停止并等待 OpenOCD 连接,同时检索代码覆盖数据。一旦 :cpp:func:`esp_gcov_dump` 函数被调用,主机将通过 telnet 会话执行 ``esp gcov dump`` OpenOCD 命令,该命令会将 OpenOCD 连接到 {IDF_TARGET_NAME},检索代码覆盖数据,然后断开与 {IDF_TARGET_NAME} 的连接,从而恢复应用程序。在应用程序的生命周期中可多次触发硬编码转储。
在必要时(如应用程序初始化后或是应用程序主循环的每次迭代期间)放置 :cpp:func:`esp_gcov_dump`,当应用程序在生命周期的某刻需要代码覆盖率数据时,硬编码转储会非常有用。
GDB 可以用来在 :cpp:func:`esp_gcov_dump` 上设置断点,然后使用 ``gdbinit`` 脚本自动调用 ``mon esp gcov dump`` (关于 GDB 的使用可参考 :ref:`jtag-debugging-using-debugger-command-line`)。
以下 GDB 脚本将在 :cpp:func:`esp_gcov_dump` 处添加一个断点,然后调用 ``mon esp gcov dump`` OpenOCD 命令。
.. code-block:: none
b esp_gcov_dump
commands
mon esp gcov dump
end
.. note::
注意,所有的 OpenOCD 命令都应该在 GDB 中以 ``mon <oocd_command>`` 方式调用。
.. _app_trace-gcov-generate-report:
生成代码覆盖报告
""""""""""""""""""""""""""
一旦代码覆盖数据被转储,``.gcno````.gcda`` 和源文件可以用来生成代码覆盖报告。该报告会显示源文件中每行被执行的次数。
Gcov 和 Gcovr 都可以用来生成代码覆盖报告。安装 Xtensa 工具链时会一起安装 Gcov但 Gcovr 可能需要单独安装。关于如何使用 Gcov 或 Gcovr请参考 `Gcov 文档 <https://gcc.gnu.org/onlinedocs/gcc/Gcov.html>`_ 和 `Gcovr 文档 <https://gcovr.com/>`_。
在工程中添加 Gcovr 构建目标
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
用户可以在自己的工程中定义额外的构建目标,从而通过一个简单的构建命令即可更方便地生成报告。
请在工程的 ``CMakeLists.txt`` 文件中添加以下内容:
.. code-block:: none
include($ENV{IDF_PATH}/tools/cmake/gcov.cmake)
idf_create_coverage_report(${CMAKE_CURRENT_BINARY_DIR}/coverage_report)
idf_clean_coverage_report(${CMAKE_CURRENT_BINARY_DIR}/coverage_report)
可使用以下命令:
* ``cmake --build build/ --target gcovr-report``:在 ``$(BUILD_DIR_BASE)/coverage_report/html`` 目录下生成 HTML 格式代码覆盖报告。
* ``cmake --build build/ --target cov-data-clean``:删除所有代码覆盖数据文件。
在 ESP-IDF 项目中,可以借助 `espressif/esp_gcov <https://components.espressif.com/components/espressif/esp_gcov>`_ 托管组件使用 gcov 进行代码覆盖率分析。