My source and build tree looks like this (see Makefile to put object files from source files different directories into a single, separate directory?) after a make (which builds and runs FooAndBarTests):
src
- Foo.cpp
- Bar.cpp
inc
- Foo.h
- Bar.h
test
- FooTest.cpp
- BarTest.cpp
- Main.cpp
- Makefile
- obj
- Foo.gcda
- Foo.gcno
- Bar.gcda
- Bar.gcno
- FooAndBarTests
UnitTest++
- libUnitTest++.a
- src
- ...
I can then produce .gcov files in the test directory by running gcov -o obj/ ../src/Foo.cpp and gcov -o obj/ ../src/Bar.cpp.
But if I run lcov -d obj/ -c -o FooAndBarTests.lcov I get:
Capturing coverage data from obj/
Found gcov version: 4.2.1
Scanning obj/ for .gcda files ...
Found 4 data files in obj/
Processing Foo.gcda
../src/Foo.cpp:cannot open source file
Processing FooTest.gcda
FooTest.cpp:cannot open source file
../inc/Foo.h:cannot open source file
../UnitTest++/src/Checks.h:cannot open source file
...
And then when I run genhtml FooAndBarTests.lcov I get:
Reading data file FooAndBarTests.lcov
Found 45 entries.
Found common filename prefix "/Users/dspitzer/FooAndBar/test"
Writing .css and .png files.
Generating output.
Processing file UnitTest++/src/Checks.h
genhtml: ERROR: cannot open /Users/dspitzer/FooAndBar/test/UnitTest++/src/Checks.h for reading!
How do I tell lcov and genhtml where the .cpp and .h files are?
Use the -b option to lcov. The -b option specifies code base.
Related
I have successfully generated the .gcda and .gcno files and they are in the same folder.
The flags in the make file looks as below :
CPPFLAGS += -std=c++11 --coverage -isystem $(GTEST_DIR)/include
CXXFLAGS += -std=c++11 --coverage -g -Wall -Wextra -pthread -I$(PULSE_DIR)/inc
CFLAGS += -std=c++11 --coverage -g -Wall -Wextra -pthread -I$(PULSE_DIR)/inc
I am using the googleTest (Gtest) to write the unitTests. The executable files generated for the unitTests are working fine. I just want to generate the code coverage.
I am successfully able to generate .gcno and .gcda files and both of them are in the same obj folder.
Then, I used the following lcov command from obj directory :
lcov -t "result" -o testcoverage.info -c -d .
This was supposed to generate testcoverag.info file but it gives me error as follows :
Capturing coverage data from .
Found gcov version: 5.4.0
Scanning . for .gcda files ...
Found 4 data files in .
Processing GeneratorObj_unittests.gcda
Cannot open source file deps/googletest/googletest/include/gtest/internal/gtest-internal.h
Cannot open source file deps/googletest/googletest/include/gtest/gtest-printers.h
Cannot open source file deps/googletest/googletest/include/gtest/gtest.h
Cannot open source file deps/googletest/googletest/include/gtest/internal/gtest-port.h
Cannot open source file deps/googletest/googletest/include/gtest/gtest-message.h
Processing GeneratorObj.gcda
Processing gtest-all.gcda
Cannot open source file deps/googletest/googletest/src/gtest-typed-test.cc
Cannot open source file deps/googletest/googletest/include/gtest/internal/gtest-port.h
Cannot open source file deps/googletest/googletest/src/gtest.cc
Cannot open source file deps/googletest/googletest/src/gtest-death-test.cc
Cannot open source file deps/googletest/googletest/include/gtest/internal/gtest-internal.h
Cannot open source file deps/googletest/googletest/src/gtest-internal-inl.h
Cannot open source file deps/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h
Cannot open source file deps/googletest/googletest/include/gtest/gtest-printers.h
Cannot open source file deps/googletest/googletest/include/gtest/gtest.h
Cannot open source file deps/googletest/googletest/include/gtest/gtest-message.h
Cannot open source file deps/googletest/googletest/include/gtest/gtest-test-part.h
Cannot open source file deps/googletest/googletest/src/gtest-printers.cc
Cannot open source file deps/googletest/googletest/src/gtest-port.cc
Cannot open source file deps/googletest/googletest/src/gtest-test-part.cc
Cannot open source file deps/googletest/googletest/src/gtest-filepath.cc
Cannot open source file deps/googletest/googletest/include/gtest/internal/gtest-filepath.h
Cannot open source file deps/googletest/googletest/include/gtest/internal/gtest-param-util.h
Processing gtest_main.gcda
Cannot open source file deps/googletest/googletest/src/gtest_main.cc
Cannot open source file deps/googletest/googletest/include/gtest/gtest.h
Finished .info-file creation
GeneratorObj_unittests is the unittest file that I have written. It some how is not able to open all the files associated with gtest folder.
If I could only generate testcoverage.info file then I would be able to generate the html coverage file using the genhtml.
I tried checking the permission of the gtest files and they are all read and write. I dont know what is going on wrong here.
I have a project directory structure of:
Root
Source
Common
MyFolder
++ My 3 source files and header
When I am building my project it generates 3 to 4 shared libraries. Lib1 compiled using c++98 and others using c++11. Flags are added in CmakeList.txt which is at root.
I need my 3 source files to be compiled for Lib1 and for other Libs as as well. but here what happens is compiler is first compiling my source file for lib using c++11 and then it is trying to use same .o file for Lib1 as well. So for .o file which is generated using c++11 is throwing exception when same is used for c++98 compiled library.
So how do write this in CmakeList.txt such that compiler rather than trying to use same .o file will compile source file again for Lib1(c++98 compiled library)
Is there any flag I can specify so that it won't take precompiled .o file and will compile it again ?
Here flags are not being overridden for different shared libraries but actually same object file by make file is being used for different flags
This is sort of counter to how makefiles and cmake usually work.
Most users consider it really important that make performs an incremental build.
The usual way with makefiles is to do make clean which is supposed to remove any binaries and object files that were created.
However, sometimes I write cmake scripts that use globbing over the source directory to assemble the project. (That means, it says "just grab all *.cpp files in the /src folder and make an executable from them".) A makefile cannot check what files in a directory, so the make build will be broken after I add a new file, and make clean won't fix it -- the whole makefile will need to be regenerated by cmake.
Usually what I do is, I write a simple bash script, named rebuild.sh or something,
#!/bin/bash
rm -rf build
mkdir build
cd build
cmake ..
make -j3
./tests
And I put that in the root of my repository, and add /build to my .gitignore. I call that when I want to do a full rebuild -- it nukes the build directory, so its foolproof. When I want an incremental rebuild, I just type make again in the /build directory.
The rebuild.sh script can also serve a double purpose if you use travis-ci for continuous integration.
Most build system assume the compiled objects remain the same within the same pass. To avoid shooting your foot I would suggest telling the build system they were actually different objects, while still compiled from same source files.
I'm not familiar with cmake but this is how you do with make:
For example you have a a.cpp which you want to compile 2 times for different compiler options:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf ("Hello %d\n", TOKEN);
return 0;
}
And the Makefile would looks like:
SRC := $(wildcard *.cpp)
OBJ_1 := $(patsubst %.cpp,%_1.o,$(SRC))
OBJ_2 := $(patsubst %.cpp,%_2.o,$(SRC))
all: pass1 pass2
pass1: $(OBJ_1)
gcc -o $# $(OBJ_1) -lstdc++
pass2: $(OBJ_2)
gcc -o $# $(OBJ_2) -lstdc++
%_1.o: %.cpp
gcc -DTOKEN=1 -c $< -o $#
%_2.o: %.cpp
gcc -DTOKEN=2 -c $< -o $#
clean:
rm -f $(OBJ_1) $(OBJ_2)
What I do here is generate two different list of object from the same source files, which you can even do the same for dependency(-MMD -MP flags).
I have a CMakeLists.txt file in which I added:
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage -pthread -std=c++11 -O0 ${CMAKE_CXX_FLAGS}")
It is generating the report files in:
project_root/build/CMakeFiles/project.dir/
BUT the files it generates have extentions .cpp.gcno, .cpp.gcda and .cpp.o.
Also, they are not in the same folder as the src files, which are at:
project_root/src/
When I move the report files to the src/ folder and execute
$ gcov main.cpp
main.gcno:cannot open notes file
But I get that error message. So I change the .cpp.gcno, .cpp.cdna and cpp.o to .gcno, .gcda and .o and finally I get the following:
gcov main.cpp
Lines executed:86.67% of 15
Creating 'main.cpp.gcov'
I have over 50 files and can't do this manually for each one.
I need to be able to run gcov once for all files and generate report for all files. I don't care where the files are generated.
It is generating the report files in: project_root/build/CMakeFiles/project.dir/
This is directory where all additional files are built for 'project' executable.
BUT the files it generates have extentions '.cpp.gcno', '.cpp.gcda' and '.cpp.o'
This is because CMake creates .cpp.o object file from .cpp source (you may see that running make VERBOSE=1. In accordance to -fprofile-arcs option's description, data file has suffix .cpp.gcno.
Also, they are not in the same folder as the src files
Data files are created in the same directory with object file.
Actually, created files are still work, if you call
gcov main.cpp.gcno
from the directory with .gcno files.
Apparently the standard CMake behavior to add an extension to give .cpp.o can be changed to replace an extension to give .o by using:
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE ON)
I have some .cpp and .h files residing in path
~/NetBeansProjects/myApplication
main.cpp
person.cpp
person.h
and I have my cppunit .cpp and .h files residing in path
~/NetBeansProjects/myApplication/tests
TestCase.cpp
TestCase.h
finalresults.cpp
assuming that I am at ~ and I have cd to directory
/NetBeansProjects/myApplication in my terminal
I want to do a g++ along with my cppunit files TO GENERATE A XML REPORT of the results on cppunit test.
I add the XmlOutputter in my finalresults.cpp
std::ofstream xmlFileOut("testResults.xml");
XmlOutputter xmlOut(&collectedresults, xmlFileOut);
xmlOut.write();
the command to use(as suggested) g++ -o finaltestresults person.cpp main.cpp tests/TestCase.cpp tests/finalresults.cpp -lcppunit
My program runs successfully but no xml is being created.
what additional steps do I need to do?
g++ -o finalresults main.cpp person.cpp tests/TestCase.cpp tests/finalresults.cpp -lcppunit
I'm working on larger project which has the following directory layout:
Source
MyA
aa.cpp
ab.cpp
ac.cpp
MyB
ba.cpp
bb.cpp
bc.cpp
MyTest
testaa.cpp
testab.cpp
testac.cpp
testba.cpp
testbb.cpp
testbc.cpp
main.cpp
Build
MyA
aa.o
ab.o
ac.o
libMyA.a (static library)
MyB
ba.o
bb.o
bc.o
libMyB.a (static library)
MyTest
testaa.o
testab.o
testac.o
testba.o
testbb.o
testbc.o
MyTest (executable)
After compiling with -fprofile-arcs -ftest-coverage I execute the MyTest application inside the Build/MyTest directory. As expected there are *.gcno and *.gcda files inside the Build directory. After running gcov inside the MyTest directory different *.gcov files are produced but unfortunately not for everything inside MyA and MyB, although every function is called inside this two libraries. Tried different options but somehow I'm unable to create useful (means correct) *.gcov files with this layout.
If I copy every cpp inside one directory and repeat the steps everything works as expected and the coverage analysis is perfect.
You must specify source files as absolute paths to g++/gcc. Don't use relative paths with ".." or like "foo/bar.cpp", else you'll get errors like "geninfo: WARNING: no data found for XXXX".
Don't include any header files on the command line to g++/gcc. Else you'll get "stamp mismatch with graph file" errors.
So, following should work when having multiple directories:
g++ --coverage -DDEBUG -g3 heyo.cpp /app/helper/blah.cpp /app/libfoo/foo.cpp -o program
./program
lcov --directory . --capture --output-file app.info
genhtml --output-directory cov_htmp app.info
Or, if you're in a Makefile that uses relative paths already, it's convenient to use:
g++ --coverage -DDEBUG -g3 $(abspath heyo.cpp helper/blah.cpp ../foo/bar/baz.cpp) -o program
To be able to keep your directory structure, you need to run gcov once inside each source file folder, but use the -o option to tell gcov where the data files are.
I think it should be like this:
gcov -o ../../Build/MyA *.cpp
I have a project with a similar source file structure, but I let the compiler dump object files etc into the source folders. I then run gcov multiple times from the root folder, once for each source file, but I specify the relative path of the source file and use the -o option to specify the relative folder like this:
gcov -o Source/MyA Source/MyA/aa.cpp
If you performed your product or application testing thoroughly and manually and spent lot of effort on it. If your objective is to get code coverage report using lcov and gcov but by mistake deleted gcno files. You can regenerate gcno files by recompiling the code but it will be generated with new timestamp and gcov reports error saying "stamp mismatch with graph file" and no code coverage report will be generated. This will result in all your testing effort getting wasted.
There is a shortcut to still generate the code coverage report. This is just a workaround and should not be relied upon all the time. Its recommended to preserve *.gcno files till your testing completes.
Note down your gcc version(gcc -v) and download its source code from one of the mirror sites
Eg - ftp://gd.tuwien.ac.at/gnu/sourceware/gcc/releases/gcc-4.4.6/gcc-4.4.6.tar.bz2
After extracting downloaded file, gcc the folder structure will be as follows
gcc-4.4.6
gcc-4.4.6/gcc
If you directly go inside gcc-4.4.6/gcc and try to do ./configure and compile(make) from there then you will encounter below problem
build/genmodes -h > tmp-modes.h
/bin/sh: build/genmodes: No such file or directory
Solution is do ./configure and make from gcc-4.4.6 and no errors will be shown related to genmodes. This will compile all modules including gcc. You may have to install mpfr and gmp modules which are needed by gcc if any error shown by ./configure
goto gcc-4.4.6/gcc/gcov.c and comment below lines and then recompile with above command
/* if (tag != bbg_stamp)
{
fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
goto cleanup;
}*/
Example path of new gcov binary after compilation is gcc-4.4.6/host-x86_64-unknown-linux-gnu/gcc/gcov
Place this binary in /usr/bin and regenerate code coverage report with command as shown in below example
lcov --capture --directory ./ --output-file coverage.info ; genhtml coverage.info --output-directory /var/www/html/coverage
Now you should not get "stamp mismatch with graph file" error and you will get code coverage report properly