#!/bin/sh # # $Id$ # ######################################################################## # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed # with this work for additional information regarding copyright # ownership. The ASF licenses this file to you 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. # # Copyright 2007 - 2008 Rogue Wave Software, Inc. # ######################################################################## # # NAME # xbuildgen - Generate build results across multiple platforms. # # SYNOPSIS # xbuildgen [option(s)...] [log-file(s)...] # # DESCRIPTION # The xbuildgen utility generates a build result in HTML format # across multiple platforms or tests with builds in columns and # components such as examples, locales, and tests in rows by # default. # # OPTIONS # -n No clean. Avoid removing temporary files. # # -s Stylesheet. Create a style sheet named resultstyle.css in # the same directory as the output file when the -o option # is specified, or in the current working directory otherwise. # # -v Verbose. Produce verbose output on stdout. # # -e # Generate a report for the specified list of example programs # with examples listed in columns and builds in rows. # # -h Print help. # # -l # Generate a report for the specified list of locales with # locales listed in columns and builds in rows. # # -o # Specify the pathname of the output file. The utility will # use stdout when no output file is specified. # # -T # Specify the title for the page. # # -t # Generate a report for the specified list of tests with # tests listed in columns and builds in rows. # # -V # Stdcxx version (branch) to generate results for. # When omitted, trunk is assumed. # ######################################################################## if [ "$BASH" = "" ]; then # this is not Bash; try to invoke it if [ -x /usr/local/bin/bash ]; then /usr/local/bin/bash $0 "$@" exit $? fi fi ###################################################################### # global constants # the directory where the script is located to get a hold of other # files at locations relative to this one (assumes the script resides # within the stdcxx source tree) readonly mydir=`dirname $0` readonly rootdir=$mydir/.. readonly today=`LC_ALL="C" date` # URL to the ViewVC directory readonly viewvc="http://svn.apache.org/viewvc" # URL to the revision number (use: "$revurl=$revno") readonly revurl="$viewvc?view=rev&rev" # URL to the trunk of the source repository readonly svnpath="$viewvc/stdcxx/trunk" # expected failures readonly xfailfile=$rootdir/etc/config/xfail.txt # xcross-component awk script readonly xcomp=$mydir/xcomp.awk ###################################################################### # global variables # by default, display one component (example, locale, or test) per row components_in_rows=1 # no verbosity by default verbose=0 # default page title (unless overridden on the command line) title="Multi-platform Test Result View" # extract the script's revision number myrev='$Revision$' myrev=${myrev#'$Revision: '} # strip leading text myrev=${myrev%' $'} # strip trailing text # form the URL to this version of the script in the repository myurl='$HeadURL$' myurl=${myurl#'$HeadURL: '} # strip leading text myurl=${myurl##*asf/} # strip svn prefix myurl=${myurl%' $'} # strip trailing text # prepend ViewVC prefix myurl="http://svn.apache.org/viewvc/$myurl" # extract program name from the url (used in diagnostic messages) readonly myname=${myurl##*/} myurl="$myurl?view=markup&rev=$myrev" ###################################################################### print_help () { echo "NAME" echo " $myname - generate a cross-build result page" echo echo "SYNOPSIS" echo " $myname [option(s)...] [log-file(s)...]" echo echo "DESCRIPTION" echo " The $myname utility generates a build result in HTML format" echo " across multiple platforms or tests with builds in columns and" echo " components such as examples, locales, and tests in rows by" echo " default." echo echo "OPTIONS" echo " -n No clean. Avoid removing temporary files." echo echo " -s Stylesheet. Create a style sheet named resultstyle.css in" echo " the same directory as the output file when the -o option" echo " is specified, or in the current working directory otherwise." echo echo " -v Verbose. Produce verbose output on stdout." echo echo " -e " echo " Generate a report for the specified list of example programs" echo " with examples listed in columns and builds in rows." echo echo " -h Print help." echo echo " -l " echo " Generate a report for the specified list of locales with" echo " locales listed in columns and builds in rows." echo echo " -o " echo " Specify the pathname of the output file. The utility will" echo " use stdout when no output file is specified." echo echo " -T " echo " Specify the title for the page." echo echo " -t " echo " Generate a report for the specified list of tests with" echo " tests listed in columns and builds in rows." echo echo " -V " echo " Stdcxx version (branch) to generate results for." echo " When omitted, trunk is assumed." } ###################################################################### # extracts the real, user and system times for a specified stage # of the build process from the file given by the second argument # and writes them out to stdout get_times () { stage=$1 file=$2 pattern="^### real, user, system time ($stage):" # extract the real, user and system times for the children # of the shell that executed the commands from the log # the format of the output is: # # # with looking like: # [1-9][0-9]*m[1-9][0-9]s # and with being the output of the POSIX standard # times built-in utility, i.e., the first line giving the system # and user times for the shell and the second line giving the # system and user times for its children in the format: # "%dm%fs %dm%fs" # we don't care about the shell times, just the times for its # children, so we skip that line stage_times=` sed -n "/$pattern/{n;p;n;n;p;}" $file` # strip newlines and fractional parts of seconds and replace # 'm' with ':' stage_times=` echo $stage_times \ | sed -e "s/\.[0-9][0-9]*s//g" \ -e "s/s//" \ -e "s/m/:/g"` # extract the real time (first) real_time=${stage_times%% *} # append a leading '0' to single-digit seconds sec=${real_time##*:} if [ ${#sec} -eq 1 ]; then real_time=${real_time%:*}":0$sec" fi # extract the user time (middle) user_time=${stage_times#* } user_time=${user_time%% *} # append a leading '0' to single-digit seconds sec=${user_time##*:} if [ ${#sec} -eq 1 ]; then user_time=${user_time%:*}":0$sec" fi # extract the system time (last) sys_time=${stage_times##* } # append a leading '0' to single-digit seconds sec=${sys_time##*:} if [ ${#sec} -eq 1 ]; then sys_time=${sys_time%:*}":0$sec" fi # output the three times cat <$real_time $user_time $sys_time EOF } ###################################################################### # extracts the date and time the build started from the file # given by the second argument get_build_date () { file=$1 # extract the date and time the build started # the date is expected to be introduced by a line like this: # ### date: date=`sed -n "/^##* *date *: *$/{n;p;q;}" $file` if [ "$date" = "" ]; then echo "$myname: warning: unable to extract date from $l" >&2 unset date fi # strip the year from the date echo ${date% [1-9][0-9][0-9][0-9]} } ###################################################################### # formats a size value in an easy-to-read way format_size () { size=$1 if [ "$size" = "" ]; then : elif [ $size -ge 1000000000 ]; then # over billion bytes, get size in gigabytes up to 2 decimal places gbsize="$((size / 1073741824)).$(((size % 1073741) / 100000))" size="
$gbsize GB
" elif [ $size -ge 1000000 ]; then # over million bytes, get size in megabytes up to 2 decimal places mbsize="$((size / 1048576)).$(((size % 1048576) / 100000))" size="
$mbsize MB
" elif [ $size -ge 10000 ]; then # over ten thoudand bytes, get even size in kilobytes kbsize="$((size / 1024))" size="
$kbsize kB
" elif [ $size -ge 1000 ]; then # over thoudand bytes, get size in kilobytes up to 2 decimal places kbsize="$((size / 1024)).$(((size % 1024) / 100))" size="
$kbsize kB
" fi echo $size } ###################################################################### # extracts the size of the library binary from the build log # being careful to avoid the symlink (in the case of a .so) get_lib_size () { file=$1 libsize=`awk '/build\/lib\/libstd[^ ]*\$/{ print $5 }' $file` if [ "$libsize" = "" ]; then # avoid warning for missing library size to reduce the noise # in cases when it fails to build # echo "$myname: warning: unable to extract library size from $l" >&2 unset libsize fi echo $libsize } ###################################################################### # extracts the build type from the string specified by the argument # (the name of the log) get_buildtype () { str=$1 # extract the build type from the name of the log, removing # the name of thread library buildtype=` echo $str \ | sed "s/\(.*-[18][125]*[aAdDsS]\)-dce-\(.*\)/\1-\2/" \ | sed "s/\(.*-[18][125]*[aAdDsS]\)-solaris-\(.*\)/\1-\2/" \ | sed "s/\(.*-[18][125]*[aAdDsS]\)-win32-\(.*\)/\1-\2/" \ | sed "s/.*-\([18][125]*[aAdDsS]\)-[1-9][0-9]*-log.*/\1/"` if [ "$buildtype" = "" ]; then echo "$myname: warning: unable to extract build type from $str" >&2 unset buildtype fi echo $buildtype } ###################################################################### # extracts the operating system name and version from the log file get_os () { file=$1 uname=`sed -n "/^##* uname *-a.*:$/{n;p;q;}" $file` case "$uname" in "AIX "*) osname="AIX" # extract the version number from AIX uname -a output: # "AIX ... osver=${uname#* } # remove AIX osver=${osver#* } # remove hostname minor=${osver%% *} # extract minor version osver=${osver% *} # remove gibberish at the end osver=${osver#* }"."$minor ;; CYGWIN*) osname="Cygwin" osver=${uname#* } # remove CYGWIN osver=${osver#* } # remove hostname osver=${osver%%(*} # extract version ;; *"FreeBSD "*) osname="FreeBSD" ;; "HP-UX "*) # for example # HP-UX hostname B.11.23 U ia64 0025699549 unlimited-user license osname="HP-UX" osver=${uname#* } # remove HP-UX osver=${osver#* } # remove hostname osver=${osver%% *} # extract full version osver=${osver#[A-Z].} # remove letter prefix ;; "IRIX64 "*) ;; "Linux "*) # extract the Linux distron name from the contents # of the /etc/*-release files osname=` sed -n "/^##* * cat *\/etc\/.*-release /{n;p;n;p;}" \ $file \ | sed -e "/^ *LSB_VERSION *=/d" -e "/^ *VERSION *= */d"` rhel="Red Hat Enterprise Linux" # SuSE Linux 10 suse_Linux="SUSE Linux Enterprise Server" # SuSE Linux 9 (sigh...) suse_LINUX="SUSE LINUX Enterprise Server" pfx="
" sfx="
" case "$osname" in "$rhel "*) # remove the Red Hat code name including the release # and keep the distribution code name and update info: # RHEL 5: Tikanga (Update 1 through 2) # RHEL 4: Nahant (Update 1 through 6) # RHEL 3: Taroon (Update 1 through 9) # RHEL 2.1 AS: Pensacola # RHEL 2.1 ES: Panama oscode=${osname##* (} # append space (important below) oscode="${oscode%)} " update=${oscode#* } # strip code name update=${update#* } # strip the word "Update" osver=${osname#$rhel } # strip the distro name ostype=${osver%% *} # extract OS type (AS or Server) osver=${osver#* release } # strip OS type osver=${osver%% (*} # osver="[osver=$osver][oscode=$oscode][update=$update]" osname="RHEL" if [ "$update" != "" ]; then osver="$osver.$update" fi ;; "$suse_Linux "*) osver=${osname#$suse_Linux } osver=${osver%% *} osname="SLES" ;; "$suse_LINUX "*) osver=${osname#$suse_LINUX } osver=${osver%% *} osname="SLES" ;; *) ;; esac ;; "SunOS "*) osname="SunOS" osver=${uname#* } # remove SunOS osver=${osver#* } # remove hostname osver=${osver%% *} # strip averything past version ;; *) osname=$uname ;; esac echo "$pfx$osname $osver$sfx" } ###################################################################### # extracts the hardware architecture from the log file get_arch () { file=$1 uname=`sed -n "/^##* uname *-a.*:$/{n;p;}" $file` if [ "$uname" = "" -o "${uname%%_*}" = "CYGWIN" ]; then # Windows or CygWin id=`sed -n "s/^ *PROCESSOR_IDENTIFIER *= *\(.*\)/\1/p" $file` arch=${id%% *} arch="
$arch
" else case "$uname" in # recent HP-UX machines always return 9000/800 "HP-UX "*" 9000/8"??" "*) arch="PA-RISC";; *" i686 "*) arch="i686";; *" i586 "*) arch="i586";; *" i486 "*) arch="i486";; *" i386 "*) arch="i386";; *" i286 "*) arch="i286";; *" ia64 "*) arch="IA64";; *" sparc "*) arch="SPARC";; *" x86_64 "*) arch="x86_64" model=` sed -n "s/^model name.*: *\(.*\)/\1/p" $file \ | sed 's/ */ /g' | head -n 1` if [ ${model%% *} = "Intel(R)" ]; then arch="
EM64T
" else arch="
AMD64
" fi ;; esac fi echo $arch } ###################################################################### # extracts the compiler and version from the log file get_compiler () { file=$1 compiler=` sed -n "/^configuring stdcxx /{p;q;}" $file \ | sed "s/.* for \([^ ][^ ]*\) .*/\1/"` if [ "${compiler%%[-_]*}" = "xlCcore" ]; then # replace xlCcore with XLC++ for IBM XLC/C++ compiler="XLC++ "${compiler#*-} elif [ "${compiler%%-*}" = "aCC" ]; then # remove the "A.0" version prefix from HP aCC version compiler="aCC ${compiler#aCC-[A-Z].0}" elif [ "$compiler" = "" ]; then # this must be a Windoze compiler... compiler=` sed -n "/^ *CXX *=.*/{p;q;}" $file \ | sed "s/^.*= *\(.*\)/\1/"` if [ "$compiler" = "cl" ]; then vs="Microsoft Visual Studio" compiler=` sed -n "/^ *Variables *: *$/{n;p;}" $file\ | sed "s/ *VERSION= *\(.*\)/\1/"` compiler="MSVC $compiler" elif [ "$compiler" = "icl" ]; then true fi fi echo $compiler | sed "s/-/ /g" } ###################################################################### # process command line options while getopts ":hnsv:e:l:o:T:t:V:" opt_name; do case $opt_name in # options with no arguments h) # print help and exit print_help exit ;; n) # avoid cleaning up temporary files no_clean=1 ;; s) # create a style sheet create_stylesheet=1 ;; v) # output all components (including passing ones) verbose=1 ;; # options with arguments e) # argument is a list of examples to process example_list=$OPTARG components_in_rows=0 ;; l) # argument is a list of locales to process locale_list=$OPTARG components_in_rows=0 ;; o) # argument is the name of output file (stdout by default) outfile=$OPTARG ;; T) # argument is the title of the page title=$OPTARG ;; t) # argument is a list of tests to process test_list=$OPTARG components_in_rows=0 ;; V) # specify stdcxx branch/version to generate cross-build # result views for (trunk by default) version=$OPTARG ;; *) echo "$myname: unknown option : -$opt_name" >&2; echo print_help exit 1;; esac; done # remove command line options and their arguments from the command line shift $(($OPTIND - 1)) # take the remaining command line arguments as the names of logs # to process gzlogs=$* # set the TMPDIR variable to /tmp if not set [ -z $TMPDIR ] && TMPDIR=/tmp ###################################################################### # output to output file when specified or to stdout output () { if [ $# -eq 0 ]; then # no arguments provided, copy its own stdin to outfile if [ -z $outfile ]; then cat else cat >>$outfile fi elif [ -z $outfile ]; then echo "$*" else echo "$*" >>$outfile fi } ###################################################################### # remove output file if specified if [ ! -z $outfile ]; then rm -f $outfile fi # overwrite style sheet if [ "$create_stylesheet" = "1" ]; then if [ -z $outfile ]; then dir=. else dir=`dirname $outfile` fi cat <$dir/resultstyle.css table { background:lightslategray; font-family:courier; font-size: 80%; } caption { background:lightslategray; color:lightgray; font-weight:bold; font-family:lucida mono; font-size: 120%; } th { background:lightgray; text-align:center; font-family:lucida mono; } td { padding: 2px; text-align: center; } tr { background:powderblue; } td.rowno { text-align: right; background:lightgray; } td.name { text-align: left; background:lightblue; } td.number { text-align: center; background:lightblue; } td.na { background:white; text-align:left; } .header { background:#cccccc; text-align:center; font-weight:bold; font-family:lucida mono; } td.total { text-align:center; font-weight:bold; } td.OK { background:forestgreen; text-align:center; font-weight:bold; } td.XPASS { color:yellow; background:forestgreen; text-align:center; font-weight:bold; } td.BASE { background:lightgreen; text-align:center; font-weight:bold; } td.NOUT { background:lightgreen; text-align:center; font-weight:bold; } td.OUTPUT { background:lightgreen; text-align:center; font-weight:bold; } td.MISS { color:white; background:lightgray; text-align:center; font-weight:bold; } td.WARN { color:red; background:#ffff99; text-align:center; font-weight:bold; } td.XWARN { color:tomato; background:lightgreen; text-align:center; font-weight:bold; } td.EXIT { color:red; background:gold; text-align:center; font-weight:bold; } td.XEXIT { color:tomato; background:lightgreen; text-align:center; font-weight:bold; } td.FORMAT { background:#ffffcc; text-align:center; } td.RUNWARN { color:black; background:#ffff99; text-align:center; font-weight:bold; } td.XRUNWARN { color:dimgray; background:lightgreen; text-align:center; font-weight:bold; } td.DIFF { color:red; background:#ffff99; font-weight:bold; text-align:center; } td.XDIFF { color:tomato; background:lightgreen; font-weight:bold; text-align:center; } td.ASSERT { color:red; background:#ffff99; font-weight:bold; text-align:center; } td.XASSERT { color:tomato; background:lightgreen; font-weight:bold; text-align:center; } td.SIGNAL { color:yellow; background:red; font-weight:bold; text-align:center; } td.XSIGNAL { color:tomato; background:lightgreen; font-weight:bold; text-align:center; } td.COMP { background:violet; font-weight:bold; text-align:center; } td.XCOMP { color:violet; background:lightgreen; font-weight:bold; text-align:center; } td.LINK { color:yellow; background:mediumpurple; font-weight:bold; text-align:center; } td.XLINK { color:mediumpurple; background:lightgreen; font-weight:bold; text-align:center; } td.EXEC { color:white; background:mediumslateblue; font-weight:bold; text-align:center; } td.xdep { color:yellow; background:gray; font-weight:bold; text-align:center; } tr.LIB { background:pink; color:black; } EOF fi ###################################################################### readonly scripturl="$myname" # output the initial portion of the HTML file cat < $title

$title

Generated $today by $scripturl on `hostname` running `uname -sr`

Index


EOF ###################################################################### # the name of a temporary file containing the build timings timings_file=$TMPDIR/.stdcxx-timings.$$ # remove the temporary file rm -f timings_file if [ $? -ne 0 ]; then exit 2 fi ###################################################################### # expand gzipped logs and extract the relevant portion from each into # a smaller text file for fast and easy processing; the names of all # the text files are stored in the textlogs variable # number of logs processed in loop below logcount=0 # space-separated list of names of text logs processed in loop below textlogs="" logdir="" for l in $gzlogs; do logcount=$((logcount + 1)) fname=`basename $l` if [ $verbose -eq 1 ]; then echo "$myname: processing $l" fi # set temporary variables (valid only within the loop) txtlog=$TMPDIR/`basename $l .gz.txt`.txt.$$ if [ "$logdir" = "" ]; then logdir=`dirname $l` elif [ $logdir != `dirname $l` ]; then echo "$myname: not implemented: logs in multiple directories" >&2 fi # append the name of the log to the list textlogs="$textlogs $txtlog" # unzip the log into a temporary text file gunzip -c $l > $txtlog if [ $? -ne 0 ]; then echo "$myname: error unzipping $l" >&2 # continue processing the empty log below fi done ###################################################################### # check to see if [ -r $xfailfile ]; then xfails=$xfailfile else xfails="" fi $xcomp bodyonly=1 logdir=$logdir version=$version $xfails $textlogs | output ###################################################################### # output the rest of the HTML file cat <Codes and Colors
Status Meaning
Unexpected Severity Expected Severity
XPASS Success OK Success Component completed successfully and produced the expected output.
Not Applicable
NOUT Success Component completed successfully and produced no output.
Not Applicable
BASE Success Component completed successfully and matched the baseline.
Not Applicable
FORMAT Success Component completed successfully but produced unexpected output.
N/A Success
Not Applicable
Component was not tested.
XDEP Failure
Not Applicable
Component was not attempted due to a missing (or failed) dependency.
COMP Failure XCOMP Success Component failed to compile.
Failure Success Component compiled successfully but failed to link.
EXEC Failure
Not Applicable
Component compiled and linked successfully but failed to execute (possibly due to a linker error).
WARN Success XWARN Success Component compiled and linked successfully but with warnings.
(N) Success (N) Success Component compiled and linked successfully, exited with a status of 0, but produced N warnings at runtime.
N Failure N Success Component compiled and linked successfully but exited with a non-zero status of N.
DIFF Failure XDIFF Success Component compiled and linked successfully, exited with a status of 0, but produced unexpected output.
[SIG]<name> Failure X[SIG]<name> Success Component compiled and linked successfully, but exited with the named signal (for example, SIGABRT).
(N) Failure (N) Success Component compiled and linked successfully, exited with a status of 0, but failed N assertions at runtime.

Build Types

Library: Archive Library Shared Library Shared Archive (AIX)
Number/Symbol s
(32-bit)
S
(64-bit)
d
(32-bit)
D
(64-bit)
a
(32-bit)
A
(64-bit)
8
(optimized)
8s: Debugging off, optimized, not reentrant. 8S: Debugging off, optimized, not reentrant. 8d: Debugging off, optimized, not reentrant. 8D: Debugging off, optimized, not reentrant. 8a: Debugging off, optimized, not reentrant. 8A: Debugging off, optimized, not reentrant.
11
(debug)
11s: Debug, not optimized, not reentrant. 11S: Debug, not optimized, not reentrant. 11d: Debug, not optimized, not reentrant. 11D: Debug, not optimized, not reentrant. 11a: Debug, not optimized, not reentrant. 11A: Debug, not optimized, not reentrant.
12
(optimized)
12s: Debugging off, optimized, reentrant. 12S: Debugging off, optimized, reentrant. 12d: Debugging off, optimized, reentrant. 12D: Debugging off, optimized, reentrant. 12a: Debugging off, optimized, reentrant. 12A: Debugging off, optimized, reentrant.
15
(debug)
15s: Debug, not optimized, reentrant. 15S: Debug, not optimized, reentrant. 15d: Debug, not optimized, reentrant. 15D: Debug, not optimized, reentrant. 15a: Debug, not optimized, reentrant. 15A: Debug, not optimized, reentrant.
EOF ###################################################################### if [ -z $no_clean ]; then # clean up if [ $verbose -eq 1 ]; then echo "$myname: rm $textlogs $timings_file" fi rm -f $textlogs $timings_file fi