#!/bin/bash # # Copyright 2011 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # A helper for running gcov on all of the project sources. # Usage: # gcov-all.sh (--prepare | --summarize) path # # where path is the same location where one runs make # # There are two modes: # --prepare cleans up all the .gcda files. This should be done # before running the test, as we need an accurate set of these # to know which object files to include in the executable. # It also effectively zeroes all the measurements, preventing # different runs from getting added together. # # --summarize goes through the produced files, runs gcov on # them, producing the gcov-summary.html and the gcov/ directory # with individual dumps # # Glossary: # .gcno file: produced by gcc during compilation, along with the # corresponding .o file # .gcda file: produced when an instrumented application is run # (or .so is loaded), and then at its exit. Contains # the actual measurements. # # To invoke gcov, we need to pass it in a list of all the source # files we want coverage information for, as well as the directory # to look into for the corresponding .gcno/.gcda files. The # summarize mode collects these based on the .gcda files that exist. # # TODO(morlovich): evaluate lcov as an option? Its output looks nice. function summarize { WORKDIR=`mktemp -d` SRCDIR=`pwd` OUTNAME=gcov-summary.html echo "Collecting all object and profile data into:" $WORKDIR # Here, we look for the .gcda files, and the .o and .gcno that go with them. # This is because they get generated for any object files that gets linked in, # as soon as the executable/module are initialized, giving us an accurate # picture of what should be checked GCDAS=`find ./out/Debug_Coverage -name '*.gcda'` DATA= for F in $GCDAS do BASE=${F%.gcda} GCNO=$BASE.gcno O=$BASE.o if [ ! -f $GCNO ]; then echo "WARNING: can't find " $GCNO continue fi if [ ! -f $O ]; then echo "WARNING: can't find " $O continue fi DATA+=" $F $GCNO $O" done cp $DATA $WORKDIR/ echo "Generating gcov summary into file://"$PWD/$OUTNAME # Collect relevant sources. For each one, we check if we have the # gcda (which means we have gcno, too). We want this for two reasons: # # 1) We only want coverage for a file if the gcda is there # 2) gcov has a bug that screws up output if some files' .gcno # does not exist (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35568) # # TODO(morlovich): worry about duplicate names! SOURCES=`find -L $SRCDIR/net $SRCDIR/pagespeed -name '*.cc' -or -name '*.c'` FILTERED_SOURCES= for F in $SOURCES do GCDA=`basename $F .c` GCDA=$WORKDIR/`basename $GCDA .cc`.gcda if [ -f $GCDA ]; then if [ $F == ${F/.svn/marker/} ]; then FILTERED_SOURCES="$FILTERED_SOURCES $GCDA" fi fi done htmlDriver > $OUTNAME echo "" >> $OUTNAME echo "Moving all the .gcov files to gcov subdir (after wiping it)" rm -rf $SRCDIR/gcov mkdir $SRCDIR/gcov mv *.gcov $SRCDIR/gcov echo "Cleaning up..." rm -r $WORKDIR } # This outputs the html driver that visualizes the results function htmlDriver { cat <
File nameCoverage percentage
TEMPLATE_END } function usage { echo "Usage:" $0 "(--prepare | --summarize) path" } if [ -z $2 ]; then usage exit fi cd $2 case $1 in --prepare) echo "Removing old .gcda files" find $2/out/Debug_Coverage -name '*.gcda' -delete;; --summarize) summarize;; *) usage;; esac