Android Native Unit test Coverage for cpp via gcov and lcov - code-coverage

I am trying to run lcov and gcov on android platform for unit test coverage.
I am able to generate .gcno file and .gcda file successfully via the flags.
Android.mk
LOCAL_CFLAGS += -g -O0 --coverage
-fprofile-arcs -ftest-coverage
LDFLAGS += -fprofile-arcs -ftest-coverage
LOCAL_LDLIBS := --coverage
And I have made sure gcov and gcc are same version in my case 4.9 but I get this weird
error:file.gcno:version '402*', prefer '409*'
BR
M S Kha

Related

Specfying the search path for a framework in Xcode [duplicate]

I wrote C program that calculates the time step iterations of wavefunctions to solve the time depended Schrödinger equation.
At some step I need to do forward and backward Fast Fourier Transformations (FFT) for which I used the library kissfft.
(https://github.com/mborgerding/kissfft)
My programs structure is somewhat like this:
TDSE (working directory)
modules
include
scripts
test
inttest_analytical.c
kissfft
libkissfft-double.dylib
Now when I compile my inttest_analytical.c it works.
But when trying to run the executable afterwards I get the following error:
(base) user TDSE % ./inttest_analytical
dyld: Library not loaded: libkissfft-double.dylib
Referenced from: /Users/user/Documents/Uni/HU Berlin/Computational Physics 2/Project 3 - Time-dependet Schroedinger Equation/TDSE/./inttest_analytical
Reason: image not found
zsh: abort ./inttest_analytical
After running otool -L ./inttest_analytical I get
/inttest_analytical:
libkissfft-double.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
As far as I understand from reading about this in other questions on google searches, libkissfft-double.dylib is a static library but I don't manage to tell gcc where to find the library. And the path it was given (by the compiler or linker?) is the working directory TDSE instead of TDSE/kissfft
For compilation I ran:
gcc -g -Wall -fPIC -I include -I kissff ./modules/wavefunction.c ./modules/integrator.c ./modules/geometry.c ./modules/linearalgebra.c ./modules/assert.c ./modules/hamiltonian.c ./modules/conjugategradient.c ./test/inttest_analytical.c -Lkissfft -lkissfft-double -o inttest_analytical
So I guess I am using the flags -L and -l wrong??
Thanks for any help.
I guess I'll use this question to write a canonical answer for all "image not found" issues.
1. The issue
Let's start with a minimal setup consisting of a main binary and a library, like so:
main.c:
#include <stdio.h>
extern int f(void);
int main(void)
{
printf("%u\n", f());
return 0;
}
xyz.c:
int f(void)
{
return 42;
}
command line:
% cc -Wall -O3 -shared -o libxyz.dylib xyz.c
% cc -Wall -O3 -o main main.c -L. -lxyz
This works. You can run ./main and it will print 42.
However, if you now create a folder lib, move libxyz.dylib there and recompile main like so:
% cc -Wall -O3 -o main main.c -Llib -lxyz
Then the compilation will still succeed, however launching it will not:
% ./main
dyld: Library not loaded: libxyz.dylib
Referenced from: /private/tmp/./main
Reason: image not found
But if you go back and recompile libxyz.dylib to the lib folder directly and then rebuild main, like so:
% cc -Wall -O3 -shared -o lib/libxyz.dylib xyz.c
% cc -Wall -O3 -o main main.c -Llib -lxyz
Then it will once again work. But just to illustrate, this is the error you get if you move libxyz.dylib once more:
% ./main
dyld: Library not loaded: lib/libxyz.dylib
Referenced from: /private/tmp/./main
Reason: image not found
Just to make things worse though, you can also produce this error without even moving the library: simply cd lib and invoke ../main.
Also note the difference to before, libxyz.dylib vs lib/libxyz.dylib. This brings us to the core of the issue.
2. The reason
On macOS, each shared library has an "install name", i.e. the path at which it is expected to be found at runtime. This path can take three forms:
Absolute, e.g. /usr/lib/libxyz.dylib.
Relative, e.g. lib/libxyz.dylib.
Magic, e.g. #rpath/libxyz.dylib.
This path is embedded in the Mach-O header of the library, via the LC_ID_DYLIB load command. It can be viewed with otool like so:
% otool -l /tmp/lib/libxyz.dylib | fgrep -B1 -A5 LC_ID_DYLIB
Load command 2
cmd LC_ID_DYLIB
cmdsize 48
name lib/libxyz.dylib (offset 24)
time stamp 1 Thu Jan 1 01:00:01 1970
current version 0.0.0
compatibility version 0.0.0
This load command is created by the linker, whose man page (man ld) tells us the following:
-install_name name
Sets an internal "install path" (LC_ID_DYLIB) in a dynamic library.
Any clients linked against the library will record that path as the
way dyld should locate this library. If this option is not specified,
then the -o path will be used. This option is also called
-dylib_install_name for compatibility.
This tells us the three steps of how install names work:
The linker embeds the name when the library is built.
The linker copies the name into binaries linking against that library when those are built.
Dyld uses that name to try and load the library.
This will obviously cause issues if libraries are moved, or aren't even being compiled with the install name matching the path at which they will end up.
3. The solution
The solution is to change the install name path. Where and how depends on your setup. You can change it by two means:
Recompile the library with the correct install name (either -Wl,-install_name,... or outright -o ...), then recompile the main binary to link against that.
Use install_name_tool. This is a bit more involved.
In either case, you need to decide what form of install name you want to use:
Absolute.
This is recommended for libraries in global paths, shared by all users. You can also use this to point to your user directory, but it's a bit ugly since you can't move the binaries around or distribute them to someone else.
Relative.
Being relative to your working directory means this is entirely unreliable.
Never use this. Just don't.
Magic.
There are three "special" tokens that go beyond absolute and relative paths:
#executable_path is the runtime directory of the main binary of the process. This is the simplest form, but only works if your libraries are only used in a single main binary.
#loader_path is the runtime directory of the binary depending on the library. I recommend not using this, as it breaks if you have two binaries in different folders that want to link to the same library.
#rpath is a list of runtime directories assembled from LC_RPATH load commands. This is a bit more complex, but it's the most flexible solution, since it can itself contain #executable_path and #loader_path.
Use of those allows you to build binaries that can be moved around freely, so long as they all retain their relative position.
For a full description of them, see man dyld.
With that out of the way, let's look at implementing the possible solutions. We have:
cc -Wl,-install_name,... to specify an install name at compile time.
install_name_tool -id ... to change the path embedded in a library.
install_name_tool -change old new to change the path embedded in a binary linking against a library.
3.1 Absolute paths
If you can recompile both the library and the main binary:
% cc -Wall -O3 -shared -o /tmp/lib/libxyz.dylib xyz.c
% cc -Wall -O3 -o main main.c -L/tmp/lib -lxyz
If you can only recompile the main binary:
% install_name_tool -id '/tmp/lib/libxyz.dylib' /tmp/lib/libxyz.dylib
% cc -Wall -O3 -o main main.c -L/tmp/lib -lxyz
If you cannot recompile either:
% install_name_tool -id '/tmp/lib/libxyz.dylib' /tmp/lib/libxyz.dylib
% install_name_tool -change 'libxyz.dylib' '/tmp/lib/libxyz.dylib' main
3.2 #executable_path
If you can recompile both the library and the main binary:
% cc -Wall -O3 -shared -o lib/libxyz.dylib xyz.c -Wl,-install_name,'#executable_path/lib/libxyz.dylib'
% cc -Wall -O3 -o main main.c -Llib -lxyz
If you can only recompile the main binary:
% install_name_tool -id '#executable_path/lib/libxyz.dylib' lib/libxyz.dylib
% cc -Wall -O3 -o main main.c -Llib -lxyz
If you cannot recompile either:
% install_name_tool -id '#executable_path/lib/libxyz.dylib' lib/libxyz.dylib
% install_name_tool -change 'libxyz.dylib' '#executable_path/lib/libxyz.dylib' main
3.3 #rpath
Rpath requires manual addition of runtime paths, which requires some planning. Suppose you have the follwing file hierarchy:
a
bin/
b
libx.dylib
lib/
liby.dylib
libz.dylib
a and b are binaries that both link against libx and liby, which in turn both link against libz. For the install name of libz, you can use neither #executable_path (because a and b are in different directories) nor #loader_path (because libx and liby are in different directories). But you can use either of them inside #rpath, and here is the decision you have to make:
You can either embed an rpath of #executable_path in a and #executable_path/.. in b. Then you can use #rpath to refer to the project root from all binaries. libz would have an install name of #rpath/lib/libz.dylib.
Or you can embed an rpath of #loader_path/lib in libx and #loader_path in liby. Then you can use #rpath to refer to the directory containing each binary. libz would have an install name of #rpath/libz.dylib.
I generally find the former to be easier to deal with, but the latter may be preferable if you have a large number of binaries scattered over many directories and only a few libraries.
To actually add an rpath to a binary, you can use:
cc -Wl,-rpath,... at compile time.
install_name_tool -add_rpath ... afterwards.
So if you can recompile both the library and the main binary:
% cc -Wall -O3 -shared -o lib/libxyz.dylib xyz.c -Wl,-install_name,'#rpath/lib/libxyz.dylib'
% cc -Wall -O3 -o main main.c -Llib -lxyz -Wl,-rpath,'#executable_path'
If you can only recompile the main binary:
% install_name_tool -id '#rpath/lib/libxyz.dylib' lib/libxyz.dylib
% cc -Wall -O3 -o main main.c -Llib -lxyz -Wl,-rpath,'#executable_path'
If you cannot recompile either:
% install_name_tool -id '#rpath/lib/libxyz.dylib' lib/libxyz.dylib
% install_name_tool -change 'libxyz.dylib' '#rpath/lib/libxyz.dylib' main
% install_name_tool -add_rpath '#executable_path' main
Note that if any of your binaries are signed, this will of course invalidate that signature. Use codesign -f ... to replace the existing signature(s).

Clang Cross Compiling with Yocto SDK

Is it possible to use the toolchain and sysroot from the Yocto SDK to cross compile with Clang/LLVM for ARM?
The environment-setup script within the Yocto SDK has the following compiler options:
export CC="arm-poky-linux-gnueabi-gcc -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a7 --sysroot=$SDKTARGETSYSROOT"
I would like to cross compile this simple userspace application
testapp.c:
#include <stdio.h>
int main()
{
printf("Hello World\n");
return(0);
}
Following the guide http://clang.llvm.org/docs/CrossCompilation.html, I am trying to cross compile the app with
$ GCCFLAGS="-mcpu=cortex-a7 -mfpu=neon -mfloat-abi=hard"
$ GCCINCLUDE="/opt/poky/2.0.1/sysroots/cortexa7hf-vfp-neon-poky-linux-gnueabi/usr/include/c++/5.2.0/arm-poky-linux-gnueabi/
$ /usr/bin/clang -target arm-poky-linux-gnueabi $GCCFLAGS -I$GCCINCLUDE -ccc-gcc-name arm-poky-linux-gnueabi-gcc testapp.c -o testapp -v
However, this fails with
Ubuntu clang version 3.4.2-3ubuntu2~xedgers (tags/RELEASE_34/dot2-final) (based on LLVM 3.4.2)
Target: arm-poky-linux-gnueabi
Thread model: posix
Selected GCC installation:
"/usr/lib/llvm-3.4/bin/clang" -cc1 -triple armv7-poky-linux-gnueabi -S -disable-free -disable-llvm-verifier -main-file-name testapp.c -mrelocation-model static -mdisable-fp-elim -fmath-errno -mconstructor-aliases -target-cpu cortex-a7 -target-feature +neon -target-abi aapcs-linux -mfloat-abi hard -target-linker-version 2.24 -v -resource-dir /usr/lib/llvm-3.4/bin/../lib/clang/3.4.2 -I /opt/poky/2.0.1/sysroots/cortexa7hf-vfp-neon-poky-linux-gnueabi/usr/include/c++/5.2.0/arm-poky-linux-gnueabi/ -internal-isystem /usr/include/clang/3.4.2/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-3.4/bin/../lib/clang/3.4.2/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fno-dwarf-directory-asm -fdebug-compilation-dir /home/adtec/workspace/yocto/testapp -ferror-limit 19 -fmessage-length 207 -mstackrealign -fno-signed-char -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -vectorize-slp -o /tmp/testapp-8517af.s -x c testapp.c
clang -cc1 version 3.4.2 based upon LLVM 3.4.2 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/include"
ignoring duplicate directory "/usr/include/clang/3.4.2/include"
#include "..." search starts here:
#include <...> search starts here:
/opt/poky/2.0.1/sysroots/cortexa7hf-vfp-neon-poky-linux-gnueabi/usr/include/c++/5.2.0/arm-poky-linux-gnueabi
/usr/include/clang/3.4.2/include
/usr/local/include
/usr/include
End of search list.
'cortex-a7' is not a recognized processor for this target (ignoring processor)
'cortex-a7' is not a recognized processor for this target (ignoring processor)
'cortex-a7' is not a recognized processor for this target (ignoring processor)
'cortex-a7' is not a recognized processor for this target (ignoring processor)
'cortex-a7' is not a recognized processor for this target (ignoring processor)
'cortex-a7' is not a recognized processor for this target (ignoring processor)
"/usr/bin/as" -mfloat-abi=hard -mcpu=cortex-a7 -mfpu=neon -o /tmp/testapp-f4f688.o /tmp/testapp-8517af.s
/usr/bin/as: unrecognized option '-mfloat-abi=hard'
clang: error: assembler command failed with exit code 1 (use -v to see invocation)
What would be the appropriate Clang flags necessary to cross compile this simple application for ARM?
If you have access to a full build rather than just the SDK, you could try using the clang layer, https://github.com/kraj/meta-clang. Whilst it should be possible eventually to build an SDK containing clang I don't think anyone has done that yet.
you can use meta-clang and also generate a SDK which contains both gcc and clang based cross compilers, once SDK is installed there are CLANGCC and CLANGCXX environment variables available to invoke clang instead of gcc. if you want to use it as default you can do
export CC=${CLANGCC}
export CXX=${CLANGCXX}
export CPP=${CLANGCPP}
There is also a writeup for Clang SDK here

Gcov is not generating *.gcda file

I am using gcov for analyzing coverage of .c file. on compilation it is generation .gcna but on execution it is not generating gcda file.
I already applied -fprofile-arcs -ftest-coverage flags in my run.sh script. And using library -lgcov -coverage.
I am running it on arm compiled environment

./configure parameters to build C library for iOS

I'm writing an iOS application that runs an xml-rpc server. I'm using the C library for xml-rpc available here : http://xmlrpc-c.sourceforge.net/ . The library uses ./configure to generate the makefile according to the host architecture, and make, make install to build/install the library.
I need to use this library with my iOS application. I understand that XCode uses a completely different build system, and I'm new to iOS development, so I'm not quite sure how to tie in the library with my application. What options do I need to pass in with ./configure to compile the library for iOS architectures (I understand there are three targets, armv7, armv7s and i386)?
Thanks in advance.
Here are the configure script options for the simulator and device platforms.
Simulator (i386) :
$ ./configure --host=i386-apple-darwin --prefix <path_to_binaries> CFLAGS="-arch i386 -isysroot /Applications/XCode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.1.sdk/ -miphoneos-version-min=4.0 --disable-cplusplus
$ make
$ make install
iOS device (arm) : this is a bit trickier, and there's an unresolved issue with this, but here are the general steps:
$ ./configure --host=arm-apple-darwin --prefix <path_to_binaries> CFLAGS="-arch armv7s -isysroot /Applications/XCode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk -miphoneos-version-min=4.0" --disable-curl-client --disable-cplusplus LDFLAGS='-arch armv7s -miphoneos-version-min=4.0 -isysroot /Applications/XCode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk’
$ make
Notes specific to this library : We need to build gennmtab against x86, since it defines the symbol table and is to be run on the machine compiling the program - run the following commands (starting from the base xmlrpc-xx.xxx directory)
$ cd lib/expat/gennmtab/
$ rm gennmtab gennmtab.o
$ gcc -c gennmtab.c -o gennmtab.o -DNDEBUG -Wall -W -Wno-uninitialized -Wundef -Wimplicit -Winline -Wno-unknown-pragmas -Wmissing-declarations -Wstrict-prototypes -Wmissing-prototypes -fno-common -g -O3 -D_THREAD -I/Users/sradhakrishnan/dev/xmlrpc-c-1.25.28 -Isrcdir/lib/util/include -I/Users/sradhakrishnan/dev/xmlrpc-c-1.25.28 -Isrcdir/lib/util/include
Now that gennmtab has been built against x86, continue with previous make, by running the following:
$ cd ../../../ (you are back in the base xmlrpc-xx.xxx directory)
$ make
$ make install

Makefile to Compile OpenCV Code in C++ on Ubuntu/Linux

I am learning OpenCV using Learning OpenCV book.
One problem I am facing while compiling the code is that I have to write a long command to compile and get the executable.
This is the command I am using
g++ `pkg-config –cflags opencv` file_name.cpp -o output_file `pkg-config –libs opencv`
I am no Make expert but I think I can eliminate writing that long command using make.
Before that I should explain my work flow. I have created a directory called opencv in my home directory (~/opencv/). I am reading the book section by section and coding the examples or exercises into new cpp source code files in that directory. So I don't know the names of the files before hand.
Now what I want make to do is,
Suppose I have coded a new file named facedetect.cpp in my opencv directory, and if I call make like this
make facedetect
then I want make to execute the following command for me
g++ `pkg-config --cflags opencv` facedetect.cpp -o facedetect `pkg-config --libs opencv`
so that whenever I make a new file named abc.cpp, I will execute make abc
so that I can run
$ ./abc
at my command line to test my abc.cpp
Please give that make file so that I can save the frustration of typing that long command each time.
PS: I have Googled for help on this and found this on using CMake but I could not understand what that does. Kindly also explain how can I use CMake for the same task.
You can create a file called Makefile in you working directory like this:
CFLAGS = `pkg-config --cflags opencv`
LIBS = `pkg-config --libs opencv`
% : %.cpp
g++ $(CFLAGS) $(LIBS) -o $# $<
then you can use this file for all your single-file programms. Just call make with the basename of the file you want to compile. For facedetect.cpp that would be
make facedetect
Here some more details:
The general format of a makefile is like this:
target : dependecy1 dependenc2 ...
command that generates the target
So for your example you could write:
facedetect : facedetect.cpp
g++ $(CFLAGS) $(LIBS) -o facedetect facedetect.cpp
For each new example you can now create a new target. But you can also make it more general:
% : %.cpp
g++ $(CFLAGS) $(LIBS) -o $# $<
Here % matches any nonempty substring. The automatic variables $# and $< substitute the names of the target file and the source file.
For more information you can consult the make documentation.
GNU Make is pretty smart and the Makefile you need for this doesn't need to be as verbose as in the other answers given so far. Here is a simple Makefile which you can use to compile the OpenCV examples:
CPPFLAGS = $(shell pkg-config --cflags opencv)
LDLIBS = $(shell pkg-config --libs opencv)
That's it. The Makefile can be this short thanks to Make's implicit rules.
Then run make as usual:
make facedetect
This assumes there is a facedetect.c or facedetect.cpp in the same directory.
I recommend the following (free!) book if you want to learn Make: http://oreilly.com/catalog/make3/book/index.csp
Create a file named makefile in your working directory that contains the following:
CFLAGS = $SHELL(pkg-config --cflags opencv)
LIBS = $SHELL(pkg-config --libs opencv)
facedetect : facedetect.cpp
g++ $(CFLAGS) $(LIBS) -o $# $<
Then when you want to compile you just type:
$ make
(To answer your PS - note that CMake is very different from make - for now you should probaby just use make.)

Resources