C++ compiler is pretty big and slow tool and if one needs to make full rebuilds very often waiting for build finish is very frustrating. For those guys “ccache” tool was created.
How is it working? Compiler output (*.o files) are cached under key that is computed from preprocessed source code, compiler versions, build switches. This way builds might be much faster.
Qmake is a Makefile generator that comes with QT and allows for easy build of QT-based (and other) projects. In order to join ccache and qmake one have to update so called “mkspecs” files. How to do that?
It’s easy using sed (I’m including only sh4 and mipsel crosscompiler toolchains):
# sed -i '/QMAKE_CXX .*= *[^c][^c]/s/= /= ccache /' \
`find /usr/local -name qmake.conf | grep 'linux-\(sh4\|mipsel\)'`
And how to revert:
# sed -i '/ccache/s/ccache / /' \
`find /usr/local -name qmake.conf | grep 'linux-\(sh4\|mipsel\)'`
Of course you can manually launch an editor and update those files, but a bit of sed scripting is many times faster
If you are hitting some performance problems (related to CPU) there is very powerfull tool that can help you with diagnostics: oprofile. Below I’m summarizing some hints for efficient oprofile usage (not all are very obvious). First of all: some basic commands:
- opcontrol: starts/stops statistics collection
- opreport: reporting tool

For applications that use shared libraries you have to add “–separate=lib” switch to opcontrol call:
opcontrol --start --separate=lib --vmlinux /boot/vmlinux
opcontrol --stop
Without this option you will see only main binary activities (without time spent in shared libraries).
(more…)
Supporting releases: It’s very important to know exact version used by customer. In order to reproduce the error you have to switch to codebase used for reported release and analyse the problem.
If you have fixed release cycles it’s pretty easy to embed version number on “About” page and get that information with bug report from customer. wait, but what about “continuos delivery” practices (there may be many different software versions pulled between official releases)? And what about human mistakes (one can forget to release software without version updated)?
The answer is: automation. You have to embed branch/commit ID somewhere in application (to be visible for end user). Then you can point exact software version that was installed on this particular machine.
You can find below how we retrieve branch name / commit ID with GIT/C++ environment (our Makefile fragment):
git branch -v | sed 's/no branch/no_branch/' \
| awk '/^\*/ { print "#define APP_VERSION \"" $$2 " " $$3 "\"" }' \
> headers/version.h
version.h file is regenerated automatically on every build (and is not stored under GIT), so it will be always filled properly. Based on this automatically generated files you can show version information in UI or insert it into logs (it depends on your application type).
Java does it pretty well. C++ sucks by default. What is that?: The answer: Backtraces.
Sometimes assert information (file name and line number where assertion occured is not enough to guess where the problem is. It’s useful to see the backtrace (stack trace in Java vocabulary) of calling methods/functions. You can achieve that in C++ using gdb (and analysing generated core files or run the program under debugger), but it’s not a “light” (and elegant) solution (especially for embedded systems).

I’m presenting here a method to collect as meaningful backtraces in C++ as possible. Just link to module below and you will see pretty backtraces on abort/assert/uncaught throw/…
(more…)
Last week I’ve been observing details of integrating source code coming from three different development teams (located in different countries). Each team owns some subset of modules and has R/W access only to those modules. Of course compile dependencies cross the borders in many places, so global changes usually done in one commit had to be split into at least two commits (because of missing W permission for someone).
There was one development branch and one integration branch. Development branch most of this time was in not “buildable” state (permanent build error), so no one was able to ensure changes are not breaking the build before commit until stabilisation. Integration branch was loaded using files copied from development branch when stable state was achieved (I know, lame). This integration style (allowing for non-buildable commits on development branch) blocks parallel integrations (one have to wait for stable state on development branch).
Are there better ways to organise such integration?
(more…)