.. _cookbook: Cookbook ======== This section contains how-to guides on creating code coverage reports for various purposes. For an introduction on using gcovr, see the :ref:`guide` instead. Recipes in the cookbook: .. contents:: :local: :depth: 1 .. _c extensions in python: How to collect coverage for C extensions in Python -------------------------------------------------- Collecting code coverage data on the C code that makes up a Python extension module is not quite as straightforward as with a regular C program. As with a normal C project, we have to compile our code with coverage instrumentation. Here, we ``export CFLAGS="--coverage"`` and then run ``python3 -m build build_ext``. Unfortunately, ``build_ext`` can rebuild a source file even if the current object file is up to date. If multiple extension modules share the same source code file, gcov will get confused by the different timestamps and report inaccurate coverage. It is nontrivial to adapt the ``build_ext`` process to avoid this. Instead, we can use the ``ccache`` utility to make the compilation lazy (works best on Unix systems). Before we invoke the ``build_ext`` step, we first ``export CC="ccache gcc"``. Ccache works well but isn't absolutely perfect, see the `ccache manual`_ for caveats. .. _ccache manual: https://ccache.dev/manual/latest.html A shell session might look like this: .. code-block:: bash # Set required env vars export CFLAGS="--coverage" export CC="ccache gcc" # clear out build files so we get a fresh compile rm -rf build/temp.* # contains old .gcda, .gcno files rm -rf build/lib.* # rebuild extensions python3 -m build build_ext # run test command i.e. pytest # run gcovr rm -rf coverage; mkdir coverage gcovr --filter src/ --txt-summary --html-details coverage/index.html .. _oos cmake: Out-of-Source Builds with CMake ------------------------------- Tools such as ``cmake`` encourage the use of out-of-source builds, where the code is compiled in a directory other than the one which contains the sources. This is an extra complication for ``gcov``. In order to pass the correct compiler and linker flags, the following commands need to be in ``CMakeLists.txt``: .. literalinclude:: ../examples/CMakeLists.txt :language: cmake :start-after: #BEGIN cmake_cmd :end-before: #END cmake_cmd The ``--coverage`` compiler flag is an alternative to ``-fprofile-arcs -ftest-coverage`` for `recent version of gcc `__. In versions 3.13 and later of ``cmake``, the ``target_link_libraries`` command can be removed and ``add_link_options("--coverage")`` added after the ``add_compile_options`` command. We then follow a normal ``cmake`` build process: .. literalinclude:: ../examples/example_cmake.sh :language: bash :start-after: #BEGIN cmake_build :end-before: #END cmake_build and run the program: .. literalinclude:: ../examples/example_cmake.sh :language: bash :start-after: #BEGIN cmake_run :end-before: #END cmake_run However, invocation of ``gcovr`` itself has to change. The assorted ``.gcno`` and ``.gcda`` files will appear under the ``CMakeFiles`` directory in ``BLD_DIR``, rather than next to the sources. Since ``gcovr`` requires both, the command we need to run is: .. literalinclude:: ../examples/example_cmake.sh :language: bash :start-after: #BEGIN cmake_gcovr :end-before: #END cmake_gcovr .. _support keil uvision format: Support of Keil uVision format ------------------------------ .. _comment of issue 697: https://github.com/gcovr/gcovr/issues/697#issuecomment-1336255837 .. _Keil uVision documentation: https://developer.arm.com/documentation/101407/0537/Debug-Commands/COVERAGE/COVERAGE-GCOV-Export?lang=en As mentioned in `comment of issue 697`_ the format of ``gcov`` file generated by the Keil uVision compiler is not compatible with the ``gcov`` specification. To support coverage data generated by this compiler you have to create the gcov files as documented in `Keil uVision documentation`_ and process them before running ``gcov`` to get the correct format. Save the following Sed script as ``fix-gcov.sed``: .. code-block:: sed # fix markers for uncovered code: # match any of #=%$ repeated 6 times s/^\([#=%$]\)\(\1\{5\}\)/\2/ # fix branch tags /^branch/ { s/executed 0/never executed/ s/executed .*/taken 1/ s/skipped .*/never executed/ } Then, apply this Sed script to all gcov files before invoking gcovr: .. code-block:: bash find . -name '*.gcov' -exec sed -i -f fix-gcov.sed {} \; gcovr --gcov-use-existing-files .. warning:: Untested because we have no access to Keil uVision compiler .. _standalone application: How to create a standalone application -------------------------------------- To create a standalone application you need to install the test suite (see :ref:`test suite`). In this test suite you can build a standalone executable with the command ``python3 -m nox --session bundle_app``. The command creates the application ``build/gcovr`` and calls the executable with each format to check if it's working correct.