Monthly Archives: December 2009

Non-recursive automake

A while back, I was toying with the idea of adding gcov support to libgdata, to give metrics on the code coverage of the test suite. I played around with adding it, but my attempts were thwarted by the fact that I couldn't easily get a list of all C files which were to be compiled, in all source directories, to use in the top-level Makefile.

I recently found a little time to work on this some more and, as usually happens, it ballooned into something bigger, and I ended up redoing the entire build system for libgdata. It now uses non-recursive automake, which makes things a lot simpler in many respects. The diffstat was favourable ("21 files changed, 641 insertions(+), 833 deletions(-)"), and it has made the autogen/clean/build cycle about 20 seconds faster (on average, from some very rough tests). Accomplishing this was largely possible due to the (fairly) recent literature on the subject from Murray Cumming and Daniel Elstner, which proved rather useful; so many thanks to them.

As a result of all this, I now know that only just over 50% of libgdata's code was actually being exercised before by the test suite. I've now pushed this up to 60%, and uncovered a few buglets in the process. I dread to think what other problems lie in the remaining 40%; there's certainly lots of work left to be done.

Anyway, since all the snippets of automake magic I could find were subtly incompatible with non-recursive automake, I ended up with a slightly different one (based on gobject-introspection's gcov support). Hopefully it's useful to someone, though it could probably do with some tidying up:

gcov-report.txt: gcov-clean all check
	$(AM_V_GEN)(rm -f $@; \
	echo -e "Test coverage for libgdata:\n" >> $@; \
	total_covered=0; total_actual=0; \
	for file in $(filter %.c,$(gdata_libgdata_la_SOURCES)); do \
	  file2=\({file##*/}; \
	  cd $(abs_srcdir)/\){file%/*}; \
	  gcov -o `find -newer \(file2 -name "*-\){file2/.c/.gcda}" -print0 | sed -e 's/\.gcda/\.o/'` \(file2 > /dev/null; \
	  if test -f \)file2.gcov; then \
	    actual=`grep -v '        -:' \(file2.gcov  | wc -l`; \
	    uncovered=`grep '#####:' \)file2.gcov | wc -l`; \
	    covered=\(((actual - uncovered)); \
	    total_covered=\)((total_covered + covered)); \
	    total_actual=\(((total_actual + actual)); \
	    echo -e "\)file:\t\(covered / \)actual\t(\((((\)covered * 100) / \(actual))%)"; \
	  fi \
	done >> $@; \
	cd $(abs_srcdir); \
	echo -e "\nSource lines: \)total_actual\nCovered statements: \(total_covered\nTotal coverage: \)(((\(total_covered * 100) / \)total_actual))%" >> $@)

gcov: gcov-report.txt
	@cat gcov-report.txt

clean: gcov-clean
	@find . -name "*.gcda" -o -name "*.gcov" -delete


.PHONY: gcov gcov-clean gcov-report.txt
	@echo "Need to reconfigure with --enable-gcov"

It will output a code coverage report of the test suite (`make check`) when `make gcov` is called, and will also save it as "gcov-report.txt" in the root source directory.

Introspectable libgdata

Now that full term at university has finished, I have a little free time (inbetween sleeping, doing all the holiday work, and that celebration thing that people seem to do) to spend on projects. Today, I got round to adding GObject introspection support to libgdata. I think some of the Makefile changes I made were a little hacky, but they seem to work. If anyone wants to use libgdata from an interpreted language which has GIR support, it should now be possible.

In university news, things have gone well this term, and I managed to (precariously) stay on top of the rolling mountain of work. I've now got two weeks' stay in Cambridge to help shepherd interviewees around for their application interviews before I go home and do Christmassy things.

It took me until about half way through the term to notice that I was actually walking past Collabora's UK office every morning (opposite King's College). It was quite a shock when I noticed. It was also a shock to see they weren't at the computer lab's recent careers fair. Perhaps missing a trick there?