I'm trying to collect code coverage for the project that has c++ and c code both on Ubuntu.
I use '-fprofile-arcs' and '-ftest-coverage' values as CXXFLAGS and CFLAGS; '-lgcov' as LINKFLAGS.
Common C project structure is:
c_code\
src
unit_tests
src contains sources of static library.
unit_tests dir contain tests written with googletest framework e. g. tests of kind
TEST_F(test_case_name, test_name) {
some_gtest_assertions;
}
After the build googletest binary that should contain static library to test inside of it is launched.
Building and running of the project binaries results in generating of *.gcno and *.gcda files. However my C coverage results are empty (C++ is generated well).
lcov command has the folloiwng format:
lcov --capture --directory my_c_gcda_location --output-file c_coverage.info
Logs of lcov show the following for C-related gcda files:
gcov did not create any files for "my_c_gcda_location/*.gcda"`
There are also errors of kind:
*.gcda:stamp mismatch with notes file
Should I specify some additional parameters or perform some additional actions to get coverage results for C? Or what can be the reason of these issues?
You may get "stamp mismatch" when the .gcda files are newer than the .gcno files.
It can happen mostly for 2 reasons:
1. You might have re-build the code after running the test and before trace file generation.
2. The binary might be built in one machine and test was ran in other machine, whose time is ahead of the build machine.
For these two cases you have to just make sure the file creation time of .gcda is greater than .gcno and .c* files.
You can do that by just doing "touch *.gcda" and then run the lcov command.
Related
I have two executables that are build from the same source (a client and a server) and they're built with the compile options -D CLIENT=0 -D SERVER=1 for the server and -D CLIENT=1 -D SERVER=0 for the client. If I do something like
if (CLIENT) {
// Client specific code
}
clangd complains that CLIENT is not defined. Is there a way to make clangd aware of those macros? (The code compiles just fine, the errors are from clangd, not the compiler)
Is there a way to make clangd aware of those macros?
From getting started with clangd:
Project setup
To understand source code in your project, clangd needs to know the
build flags. (This is just a fact of life in C++, source files are not
self-contained.)
By default, clangd will assume that source code is built as clang
some_file.cc, and you’ll probably get spurious errors about missing
#included files, etc. There are a couple of ways to fix this.
compile_commands.json
compile_commands.json file provides compile commands for all source
files in the project. This file is usually generated by the build
system, or tools integrated with the build system. Clangd will look
for this file in the parent directories of the files you edit. Other
tools can also generate this file. See the compile_commands.json
specification.
compile_commands.json is typically generated with CMake build system, but more build systems try to generate it.
I would suggest moving your project to CMake, in the process you will learn this tool that will definitely help you in further C-ish development.
compile_flags.txt
If all files in a project use the same build flags, you can put those
flags, one flag per line, in compile_flags.txt in your source root.
Clangd will assume the compile command is clang $FLAGS some_file.cc.
Creating this file by hand is a reasonable place to start if your
project is quite simple.
If not moving to cmake, create a compile_flags.txt file with the content for example like the following, and clangd should pick this file up:
-DCLIENT=1
-DSERVER=1
I am here with the problem, not getting an cpp files in gcovr output. Actually my main project consist of many sub cpp files but, they are located in different directory paths.
Directory layout:
D:\selv_ar\GCovTest\ado\cic\rc_actuator_switch\ulf\src (source directory)
test\devices\puu_driver\sw (main project directory)
core\devices\puu_driver (sub files)
test\testtools (sub files)
test\devices\puu_driver (workspace)
I have a simple hello world program with the files main.cpp, helloworld.h, and helloworld.cpp in the same directory.
Notes:
I am compiling to the embedded target debgcov_qnx660_qcc_x86 and copy the gcda files into the same directory as the source files.
I am running gcovr from the main project directory.
Questions:
When I create a coverage report for the hello world program, why doesn't it show the helloworld.h file?
When I create a coverage report for my actual software, it shows coverage for files in the main project directory. Why doesn't it show coverage for the sub files?
From which directory should I run gcvor? The main directory? The source directory? The workspace?
Where should I put the gcda files? Into the main project directory? Into the sub file directories?
When I create a coverage report for the hello world program, why doesn't it show the helloworld.h file?
Gcovr only reports a file if it contains executable code. Header files usually only contain declarations, but not function definitions. You can check whether that file was seen by running gcovr in `--verbose`` mode.
Some GCC versions have a bug so that files with zero coverage are not reported, even if they contain executable code. See the gcvor FAQ[1] for compiler versions that fix this.
[1]: sorry, the main gcovr.com website is down at the moment.
When I create a coverage report for my actual software, it shows coverage for files in the main project directory. Why doesn't it show coverage for the sub files?
Gcovr tries to filter out coverage data that is irrelevant for your project, for example coverage data for the standard library.
Gcovr only keeps the coverage data if the file path is matched by a -f/--filter.
If no filters are given, the path must be within the -r/--root directory.
If no --root is explicitly provided, the current working directory is used.
So when you run gcovr without arguments like --filter or --root, gcovr will only show coverage for files within the current working directory.
To fix this, give a root path that contains all the directories for which you want coverage, like --root ../ or --root D:/selv_ar/GCovTest/ado/cicrc_actuator_switch/ulf/src.
Or, you can provide filters that match all files where you are interested in coverage. Note that filters are regexes, so you need to escape special characters like .. Also, use forward slashes for paths in the regex. Example in shell syntax:
$ gcovr --root . \
-f 'D:/selv_ar/GCovTest/ado/cicrc_actuator_switch/ulf/src/(test|core)/devices/puu_driver/' \
-f 'D:/selv_ar/GCovTest/ado/cicrc_actuator_switch/ulf/src/test/testtools/'
Make sure that you are using gcovr version 4 or later for filters to work correctly on Windows. If you want to use --root ../ style paths, you should use gcovr 4.2 (not yet released, install the development version from GitHub in the meanwhile).
From which directory should I run gcvor? The main directory? The source directory? The workspace?
Where possible, gcovr should be run in the same directory where GCC runs. This typically means your build directory. If GCC runs in multiple directories, try to use a parent directory of all of these. Use the --root, --filter, and search path arguments to provide suitable paths to the source code and to the gcda files.
Where should I put the gcda files? Into the main project directory? Into the sub file directories?
The .gcda files must be placed next to the corresponding .o object files and .gcno files that the compiler generates. This is important so that the correct source files can be found.
If you're using cross-compilation, collecting coverage data that works can be more complicated. If you encounter problems read about GCOV_PREFIX in the “Cross-Profiling” chapter of the GCC docs and gcovr issue #259.
Gcovr searches for the gcda files in the search paths: any (unnamed) parameters you pass to gcovr. For example, gcovr --root foo bar qux specifies two search paths bar and qux. By default, gcovr searches all subdirectories of the current working directory.
I am trying to generate the coverage for C files (Yocto project).
So, I have added gcov flags "-g -O0 --coverage" in the Makefile.am of most of the available modules.
It generated ".gcno" files during the compilation of each module with coverage flags.
I have generated an image from all these modules and loaded it in the test device and ran functional test cases.
I am able to find the path of the "gcda" files using strings command from the process that is running the test device.
So I have used gdb mode to flush the coverage using the "__gcov_flush" command after attaching the process id to gdb.
This throws an error "No symbol __gcov_flush in current context". Please suggest me what may be the cause for this error.
As per the comments it is not directly possible to just build the Linux Kernel with the Coverage Compiler flags and assume to get meaningful coverage metrics.
The Code Coverage metrics actually require some file systems to be available to write the run-time coverage data(i.e. *.gcda files).
If you want to enable Code Coverage for Linux Kernel here is a documentation on how to go about enabling the support using a GCOV virtual filesystem to collect coverage metrics.
Also, assuming you are cross compiling for a different architecture then probably you will have to use a cross-gcov tool to collect the coverage metrics, after you have captured the *.gcno files after execution.
I have successfully set up gcov in my project to generate HTML files with code coverage data using lcov. However, as I often work via SSH with a text console only, I'm looking for a way to generate annotated source files like git-blame does with the history:
covered source_line();
not covered other_source_line();
Is it possible somehow?
I'm going to assume you are referring to gcovr when you say gcov, since gcov does not output to HTML format. gcovr does output to HTML though. gcovr is basically just a wrapper for gcov.
In order to get the annotated source files, you need to simply use gcov.
gcov, by default, annotates source files.
To run with gcov, you just need to compile with -fprofile-arcs -ftest-coverage -fPIC -O0, and link in the gcov library(-lgcov).
Then run your program.
Then issue the following command:
gcov main.c
Where main.c is whatever file you want your annotated analysis on.
After that, you will notice a new file created(main.c.gcov). This is the file you are looking for.
Here's a link on gcov usage
I compile my code using gcc and gfortran. To generate coverage information, I used to add --coverage to both compiler flags (FFLAGS and CFLAGS), the compiler would generate .gcno files and upon running the program I would get .gcda files containing the coverage information.
After separating source and object directory (src/*.c and out/obj/*.o) the gcda files are not generated any more. At least I suppose it is due to that separation.
Is this fixable?