]> git.saurik.com Git - wxWidgets.git/commitdiff
Add buildbot tools and config include files.
authorMichael Wetherell <mike.wetherell@ntlworld.com>
Thu, 4 Oct 2007 15:55:18 +0000 (15:55 +0000)
committerMichael Wetherell <mike.wetherell@ntlworld.com>
Thu, 4 Oct 2007 15:55:18 +0000 (15:55 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49042 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

build/buildbot/config/common.xml
build/buildbot/config/example.xml
build/buildbot/config/include.xml [new file with mode: 0644]
build/buildbot/config/run-tests.sh [new file with mode: 0755]
build/buildbot/config/testdrive-inc.xml [new file with mode: 0644]
build/buildbot/tools/bot.xsd [new file with mode: 0644]
build/buildbot/tools/embedded.xsl [new file with mode: 0644]
build/buildbot/tools/preprocess.sh [new file with mode: 0755]
build/buildbot/tools/validate.sh [new file with mode: 0755]

index 2e2f0daa9e87636566d1e9a803fed6051d2ef9bb..3a8c77787fc84a7d6b223cd8c8f2f6e87c53f24c 100644 (file)
 <!--
     Quick schedulers. Builds using these are triggered after each change to
     the sources on the given branch.
-    
-    name:               unique 
-    branch:             branch to watch 
+
+    name:               unique
+    branch:             branch to watch
     treeStableTimer:    wait until the tree has stopped changing for the
                         given number of seconds before firing
-    fileNotImportant:   files matching these patterns do not trigger a build 
+    fileNotImportant:   files matching these patterns do not trigger a build
 -->
 
 <scheduler>
index 5c79147ba5c41c4bf3f510f6778d4cb9b98264e1..e7bde42b32d2c67375079274d1c51c8f9d4fedb0 100644 (file)
@@ -11,6 +11,9 @@
     There is one xml file such as this per build slave containing a <build>
     element for each build the slave runs. Each <build> corresponds to a
     column in the waterfall display.
+
+    For full documentation see:
+    http://www.wxwidgets.org/wiki/index.php/Development:_Buildbot
 -->
 
 <bot xmlns:xi="http://www.w3.org/2001/XInclude"
@@ -51,7 +54,7 @@
         The name of a scheduler that will trigger this build. The schedulers
         are usually defined in common.xml, look in there to see if there is
         already one you can use, and add a new one if not.
+
         The 'trunk_quick' and 'stable_quick' schedulers currently in
         common.xml trigger a build after every source change on the trunk
         and stable branches respectively. There are also daily and weekly
diff --git a/build/buildbot/config/include.xml b/build/buildbot/config/include.xml
new file mode 100644 (file)
index 0000000..6c1e726
--- /dev/null
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+    Name:       include.xml
+    Purpose:    Common declarations for buildbot
+    Author:     Mike Wetherell
+    RCS-ID:     $Id$
+    Copyright:  (c) 2007 Mike Wetherell
+    Licence:    wxWidgets licence
+-->
+
+<bot xmlns:xi="http://www.w3.org/2001/XInclude"
+     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+     xmlns:exsl="http://exslt.org/common"
+     xsl:version="1.0">
+
+<!--
+    Constants
+-->
+<xsl:template name="SVN_URL">http://svn.wxwidgets.org/svn/wx/wxWidgets/</xsl:template>
+<xsl:template name="STABLE_BRANCH">branches/WX_2_8_BRANCH</xsl:template>
+<xsl:variable name="STABLE_BRANCH"><STABLE_BRANCH/></xsl:variable>
+
+<!--
+    checkout - build step for source checkout.
+
+    Usage: as <svn> with defaults for <baseURL> and <defaultBranch>
+
+    Typically just:
+        <checkout/>
+    for the trunk, or:
+        <checkout branch="branches/WX_2_8_BRANCH"/>
+    to checkout a branch.
+-->
+<xsl:template name="checkout">
+    <xsl:param name="content"/>
+    <xsl:param name="branch" select="'trunk'"/>
+    <xsl:variable name="nodes" select="exsl:node-set($content)"/>
+    <svn>
+        <xsl:if test="not($nodes/svnurl)">
+            <xsl:if test="not($nodes/baseURL)">
+                <baseURL><SVN_URL/></baseURL>
+            </xsl:if>
+            <xsl:if test="not($nodes/defaultBranch)">
+                <defaultBranch><xsl:value-of select="$branch"/></defaultBranch>
+            </xsl:if>
+        </xsl:if>
+        <xsl:copy-of select="$content"/>
+    </svn>
+</xsl:template>
+
+<!--
+    configure - add the options attribute to <configure>
+
+    Usage: <configure options="-with-foobar"/>
+-->
+<xsl:template name="configure">
+    <xsl:param name="content"/>
+    <xsl:param name="options"/>
+    <configure>
+        <copy-with-defaults content="{$content}">
+            <command>./configure <xsl:value-of select="$options"/></command>
+        </copy-with-defaults>
+    </configure>
+</xsl:template>
+
+<!--
+    make - specify the make command.
+
+    Usage: <make>nmake -f makefile.vc SHARED=1</make>
+
+    Used as a child of <build> to specify the make command used by the
+    <compile> elements below, if omitted 'make' is used.
+-->
+<xsl:template name="make"/>
+
+<!--
+    compile - modifiy <compile> to default to the command given by <make>
+
+    Usage: as <compile>
+
+    The <make> element of <build> spcecifies the make command used by all
+    compile build steps in the build. If <make> is not given 'make' is used.
+
+    The command for a particular compile build step can be further overridden
+    using its <command> element:
+        <compile>
+            <command>myscript</command>
+        </compile>
+-->
+<xsl:template name="compile">
+    <xsl:param name="content"/>
+    <compile>
+        <copy-with-defaults content="{$content}">
+            <command><get name="make" default="make"/></command>
+        </copy-with-defaults>
+    </compile>
+</xsl:template>
+
+<!--
+    Compile build steps for the usual subdirectories.
+
+    Usage: as <compile>
+
+    Typically just:
+        <compile-msw/>
+        <compile-samples/>
+        <compile-utils/>
+        <compile-contrib/>
+        <compile-tests/>
+
+    By default the compile command produced is:
+        cd foobar && make
+    As above, the 'make' part can be overridden using the <make> element or
+    the whole command line can be replaced using <command>.
+
+    <compile-msw> and <compile-tests> halt the build on failure, the others
+    continue with the next step (can be overridden by <haltOnFailure>).
+-->
+<xsl:template name="compile-msw">
+    <xsl:param name="content"/>
+    <compile-subdir dir="build\msw" halt="true">
+        <xsl:copy-of select="$content"/>
+    </compile-subdir>
+</xsl:template>
+
+<xsl:template name="compile-samples">
+    <xsl:param name="content"/>
+    <compile-subdir dir="samples">
+        <xsl:copy-of select="$content"/>
+    </compile-subdir>
+</xsl:template>
+
+<xsl:template name="compile-utils">
+    <xsl:param name="content"/>
+    <compile-subdir dir="utils">
+        <xsl:copy-of select="$content"/>
+    </compile-subdir>
+</xsl:template>
+
+<xsl:template name="compile-contrib">
+    <xsl:param name="content"/>
+    <compile-subdir dir="contrib">
+        <xsl:copy-of select="$content"/>
+    </compile-subdir>
+</xsl:template>
+
+<xsl:template name="compile-tests">
+    <xsl:param name="content"/>
+    <compile-subdir dir="tests" halt="true">
+        <xsl:copy-of select="$content"/>
+    </compile-subdir>
+</xsl:template>
+
+<!--
+    compile-subdir - build step to compile a subdirectory.
+
+    Usage: as <compile> plus the following attributes,
+           <compile-subdir dir="foobar" [ halt="true" ]/>
+
+    Compiles the named subdirectory 'foobar'. Continues with the next build
+    step on failure, unless the optional attibute 'halt="true"' is given.
+    The make command used is as described for the compile steps above.
+-->
+<xsl:template name="compile-subdir">
+    <xsl:param name="content"/>
+    <xsl:param name="dir"/>
+    <xsl:param name="halt" select="'false'"/>
+    <compile>
+        <defaults content="{$content}">
+            <description>
+                compiling <xsl:value-of select="$dir"/>
+            </description>
+            <descriptionDone>
+                compile <xsl:value-of select="$dir"/>
+            </descriptionDone>
+            <haltOnFailure>
+                <xsl:value-of select="$halt"/>
+            </haltOnFailure>
+            <warnOnFailure/>
+        </defaults>
+        <copy-with-defaults content="{$content}">
+            <command>cd <xsl:value-of select="$dir"/> &amp;&amp; <get name="make" default="make"/></command>
+        </copy-with-defaults>
+    </compile>
+</xsl:template>
+
+<!--
+    run-tests - build step to run the test suites.
+
+    Usage: as <test>
+
+    For unix builds typically just:
+        <run-tests/>
+    or for Windows builds, e.g.:
+        <run-tests>
+            <command>PATH=..\lib\vc_lib;%PATH%</command>
+            <command>cd tests &amp;&amp; vc_msw\test</command>
+        </run-tests>
+-->
+<xsl:template name="run-tests">
+    <xsl:param name="content"/>
+    <test>
+        <defaults content="{$content}">
+            <description>running tests</description>
+            <descriptionDone>run tests</descriptionDone>
+            <warnOnFailure/>
+        </defaults>
+        <copy-with-defaults content="{$content}">
+            <command><xi:include href="run-tests.sh" parse="text"/></command>
+        </copy-with-defaults>
+    </test>
+</xsl:template>
+
+<!--
+    defaults - supply default content for an element.
+
+    Usage: <defaults content="{$content}">
+               <foo>foo</foo>
+               <bar>bar</bar>
+           </defaults>
+
+    Copies those child elements that do not already exist in $content.
+-->
+<xsl:template name="defaults">
+    <xsl:param name="defaults"/>
+    <xsl:param name="content"/>
+
+    <xsl:variable name="def-nodes" select="exsl:node-set($defaults)"/>
+    <xsl:variable name="cont-nodes" select="exsl:node-set($content)"/>
+
+    <xsl:for-each select="$def-nodes/*">
+        <xsl:if test="not($cont-nodes/*[name() = name(current())])">
+            <xsl:copy-of select="."/>
+        </xsl:if>
+    </xsl:for-each>
+</xsl:template>
+
+<!--
+    copy-with-defaults - copy elements supplying defaults for any that are
+                         missing or empty.
+
+    Usage: <copy-with-defaults content="{$content}">
+               <foo>foo</foo>
+               <bar>bar</bar>
+           </copy-with-defaults>
+
+    Copies $content plus any child elements that do not exist in $content,
+    substituting empty elements in $content with any child elements of the
+    same name.
+-->
+<xsl:template name="copy-with-defaults">
+    <xsl:param name="defaults"/>
+    <xsl:param name="content"/>
+
+    <xsl:variable name="def-nodes" select="exsl:node-set($defaults)"/>
+    <xsl:variable name="cont-nodes" select="exsl:node-set($content)"/>
+
+    <xsl:for-each select="$def-nodes/*">
+        <xsl:if test="not($cont-nodes/*[name() = name(current())])">
+            <xsl:copy-of select="."/>
+        </xsl:if>
+    </xsl:for-each>
+
+    <xsl:for-each select="$cont-nodes/*">
+        <xsl:choose>
+            <xsl:when test="not(node())">
+                <xsl:copy-of select="$def-nodes/*[name() = name(current())]"/>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:copy-of select="."/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:for-each>
+</xsl:template>
+
+<!--
+    get - gets the value of a named element inside a <build>.
+
+    Usage: <get name="foobar" [ default="value" ]/>
+
+    Used inside a <build> evaluates to the value of the build's <foobar>
+    element, or to the value of the optional 'default' attribute if there is
+    no such element.
+-->
+<xsl:template name="get">
+    <xsl:param name="content"/>
+    <xsl:param name="name"/>
+    <xsl:param name="default"/>
+    <strip>
+        <xsl:choose>
+            <xsl:when test="ancestor-or-self::build/*[name() = $name]">
+                <xsl:apply-templates select="ancestor-or-self::build/*[name() = $name]/node()"/>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:value-of select="$default"/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </strip>
+</xsl:template>
+
+<!--
+    strip - strips leading and trailing whitespace
+
+    Usage: <strip>
+               foobar
+           </strip>
+
+    Strips leading and trailing whitespace if the content is text only,
+    otherwise copies the content unchanged.
+-->
+<xsl:template name="strip">
+    <xsl:param name="content"/>
+    <xsl:variable name="len" select="string-length($content)"/>
+    <xsl:variable name="norm" select="normalize-space($content)"/>
+    <xsl:variable name="normlen" select="string-length($norm)"/>
+    <xsl:choose>
+        <xsl:when test="exsl:node-set($content)/*">
+            <xsl:copy-of select="$content"/>
+        </xsl:when>
+        <xsl:when test="substring($content, 1, 1) != substring($norm, 1, 1)">
+            <xsl:call-template name="strip">
+                <xsl:with-param name="content" select="substring($content, 2)"/>
+            </xsl:call-template>
+        </xsl:when>
+        <xsl:when test="substring($content, $len, 1) != substring($norm, $normlen, 1)">
+            <xsl:call-template name="strip">
+                <xsl:with-param name="content" select="substring($content, 1, $len - 1)"/>
+            </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:value-of select="$content"/>
+        </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+
+</bot>
diff --git a/build/buildbot/config/run-tests.sh b/build/buildbot/config/run-tests.sh
new file mode 100755 (executable)
index 0000000..eb22eae
--- /dev/null
@@ -0,0 +1,29 @@
+# Run the test suites
+# Running them one at a time gives more readable results and shows up errors
+# in the suite names.
+set -e
+cd tests
+
+case `uname -sm` in
+    CYGWIN*|MINGW32*)   PATH=../lib:$PATH ;;
+    Darwin*)            DYLD_LIBRARY_PATH=../lib:$DYLD_LIBRARY_PATH ;;
+    *)                  LD_LIBRARY_PATH=../lib:$LD_LIBRARY_PATH ;;
+esac
+
+test -x test_gui && TEST_GUI=./test_gui
+ERR=0
+
+for prog in ./test $TEST_GUI; do
+    if [ -x $prog ]; then
+        SUITES=`$prog -l | grep '^  [^ ]'`
+        for SUITE in $SUITES; do
+            echo
+            echo $SUITE
+            echo $SUITE | sed 's/./-/g'
+            $prog $SUITE || ERR=1
+            echo
+        done
+    fi
+done
+
+exit $ERR
diff --git a/build/buildbot/config/testdrive-inc.xml b/build/buildbot/config/testdrive-inc.xml
new file mode 100644 (file)
index 0000000..71242d4
--- /dev/null
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+    Name:       testdrive-inc.xml
+    Purpose:    Declarations for the testdrive build slave
+    Author:     Mike Wetherell
+    RCS-ID:     $Id$
+    Copyright:  (c) 2007 Mike Wetherell
+    Licence:    wxWidgets licence
+-->
+
+<bot xmlns:xi="http://www.w3.org/2001/XInclude"
+     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+     xmlns:exsl="http://exslt.org/common"
+     xsl:version="1.0">
+
+<xi:include href="include.xml" xpointer="xpointer(*/*)"/>
+
+<!--
+    checkout - build step for source checkout.
+
+    Usage: as <svn> with additional <command> element and defaults for
+           <baseURL> and <defaultBranch>
+
+    Typically just:
+        <checkout/>
+    for the trunk, or:
+        <checkout branch="branches/WX_2_8_BRANCH"/>
+    to checkout a branch.
+-->
+<xsl:template name="checkout">
+    <xsl:param name="content"/>
+    <xsl:param name="branch" select="'trunk'"/>
+    <xsl:variable name="nodes" select="exsl:node-set($content)"/>
+    <testdrive-svn>
+        <xsl:if test="not($nodes/svnurl)">
+            <xsl:if test="not($nodes/baseURL)">
+                <baseURL><SVN_URL/></baseURL>
+            </xsl:if>
+            <xsl:if test="not($nodes/defaultBranch)">
+                <defaultBranch><xsl:value-of select="$branch"/></defaultBranch>
+            </xsl:if>
+        </xsl:if>
+        <xsl:if test="not($nodes/command)">
+            <profile/>
+            <post-checkout/>
+        </xsl:if>
+        <xsl:copy-of select="$content"/>
+    </testdrive-svn>
+</xsl:template>
+
+<xsl:template name="post-checkout">
+<command>
+mkdir -p $TOPDIR
+chown $USER $TOPDIR
+rm -rf $BUILDDIR
+cp -pR . $BUILDDIR || { cd; rm -rf $BUILDDIR; exit 1; }
+</command>
+</xsl:template>
+
+<!--
+    configure - make disable-precomp-headers a default configure option for
+                the testdrive, and post process the Makefiles to use ccache.
+
+    Usage: <configure options="-with-foobar"/>
+-->
+<xsl:template name="configure">
+    <xsl:param name="content"/>
+    <xsl:param name="options"/>
+    <configure>
+        <copy-with-defaults content="{$content}">
+            <command>./configure --disable-precomp-headers <xsl:value-of select="$options"/></command>
+        </copy-with-defaults>
+        <command>find . -name Makefile | xargs perl -pi -e 's/^(?:CC|CXX) = /$&amp;ccache /'</command>
+    </configure>
+</xsl:template>
+
+<!--
+    setup - a build step that makes sure any prerequisites are set up for
+            the current testdrive build.
+
+    Usage: <setup/>
+           <setup cppunit-options="-host=i686-apple-darwin8"/>
+
+    One of the things it sets up is cppunit. There is more than one compiler
+    available on some of the testdrive machines, and generally speaking
+    cppuint needs to be compiled by the same one that will be used for the
+    build.
+-->
+<xsl:template name="setup">
+<xsl:param name="content"/>
+<xsl:param name="options"/>
+<xsl:param name="ccache-configure" select="'./configure INSTALL=./install-sh\ -c --prefix=$HOME --bindir=$OPTDIR/bin'"/>
+<xsl:param name="ccache-options"/>
+<xsl:param name="cppunit-configure" select="'./configure INSTALL=config/install-sh\ -c --prefix=$HOME --bindir=$OPTDIR/bin --libdir=$OPTDIR/lib --disable-static'"/>
+<xsl:param name="cppunit-options"/>
+<shellcommand>
+<description>setting up</description>
+<descriptionDone>set up</descriptionDone>
+<haltOnFailure/>
+<command>
+MINSPACE=1000000
+DSPACE=`df -Pk $BUILDDIR | tail -1 | awk '{ print $4 }'`
+if [ $DSPACE -lt $MINSPACE ]; then
+    echo "Disk space low, skipping build"
+    exit 1
+fi
+if [ -z "$CCACHE_DIR" ]; then
+    gunzip -c $HOME/src/ccache-*.tar.gz | tar xf -
+    cd ccache-*
+    <xsl:value-of select="concat($ccache-configure, ' ', $ccache-options, ' ', $options)"/>
+    make
+    strip ccache
+    make install
+    cd $BUILDDIR
+    rm -r ccache-*
+fi
+if { cppunit-config --version || "$CPPUNIT_CONFIG" --version; } 2>/dev/null; then
+    HAVE_CPPUNIT=1
+fi
+if [ -z "$HAVE_CPPUNIT" ]; then
+    gunzip -c $HOME/src/cppunit-*.tar.gz | tar xf -
+    cd cppunit-*
+    <xsl:value-of select="concat($cppunit-configure, ' ', $cppunit-options, ' ', $options)"/>
+    make install-strip
+    chmod +x $OPTDIR/bin/cppunit-config
+    cd $BUILDDIR
+    rm -rf cppunit-*
+fi
+</command>
+</shellcommand>
+</xsl:template>
+
+<!--
+    builddir - override <builddir> to accept a full path
+
+    Usage: <builddir>/tmp/wx/foobar</builddir>
+
+    Normally builddir is a single directory name not a full path. Override
+    to allow a working directory to be selected on the remote testdrive
+    machine.
+
+    The actual builddir (i.e. last part 'foobar') as usual must be unique
+    across all the builds of all the slaves.
+-->
+<xsl:template name="builddir">
+    <xsl:param name="content"/>
+    <builddir>
+        <basename><xsl:copy-of select="$content"/></basename>
+    </builddir>
+</xsl:template>
+
+<!--
+    steps - overrides <steps> to prepend <profile/> and <prologue/> and
+            append <epilogue/> to the <command/> of each build step.
+
+    Usage: as <steps>
+
+    The differences between <profile/> and <prologue/> are:
+    1. <profile/> is also used by <checkout> for its post checkout command,
+       <proglogue/> isn't.
+    2. <profile/> has access to the build's fields, for example it can
+       use <get name="builddir"/>, while <prologue/> can't.
+-->
+<xsl:template name="steps">
+    <xsl:param name="content"/>
+    <xsl:variable name="profile"><profile/></xsl:variable>
+    <steps>
+        <xsl:for-each select="exsl:node-set($content)/*">
+            <xsl:choose>
+                <xsl:when test="contains(name(), 'svn')">
+                    <xsl:copy-of select="."/>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:copy>
+                        <xsl:copy-of select="@*"/>
+                        <xsl:copy-of select="$profile"/>
+                        <prologue/>
+                        <xsl:copy-of select="node()"/>
+                        <xsl:if test="not(command)">
+                            <command/>
+                        </xsl:if>
+                        <epilogue/>
+                    </xsl:copy>
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:for-each>
+    </steps>
+</xsl:template>
+
+<!--
+    profile - see <steps> above.
+-->
+<xsl:template name="profile">
+<command>
+set -e
+uname -smnr
+umask 022
+LANG=C
+TOPDIR=<get name="builddir"/>
+BUILDDIR=$TOPDIR/build
+OPTDIR=$HOME/opt/<basename><get name="builddir"/></basename>
+</command>
+</xsl:template>
+
+<!--
+    prologue - see <steps> above.
+-->
+<xsl:template name="prologue">
+<command>
+INSTALLDIR=$TOPDIR/install
+case `uname -sm` in
+    Linux*86*) PATH=$HOME/linux-x86/bin:$PATH ;;
+esac
+PATH=$OPTDIR/bin:$PATH
+LD_LIBRARY_PATH=$BUILDDIR/lib:$OPTDIR/lib:$LD_LIBRARY_PATH
+export LD_LIBRARY_PATH
+if { ccache -V; } >/dev/null 2>&amp;1; then
+    CCACHE_DIR=$TOPDIR/ccache
+    export CCACHE_DIR
+    ccache -M 90M
+fi
+cd $BUILDDIR
+<if-del-on-fail>trap 'cd; rm -rf $BUILDDIR' EXIT</if-del-on-fail>
+</command>
+</xsl:template>
+
+<!--
+    epilogue - see <steps> above.
+-->
+<xsl:template name="epilogue">
+    <xsl:if test="position() != last()">
+        <if-del-on-fail>
+            <command>trap '' EXIT</command>
+        </if-del-on-fail>
+    </xsl:if>
+</xsl:template>
+
+<!--
+    if-del-on-fail - used in the context of a build step, copies its content
+                     if the build step should cleanup on failure.
+
+    Usage: <if-del-on-fail>foobar</if-del-on-fail>
+
+    On the testdrive the working directory is deleted after a build to save
+    space. If the step has <haltOnFailure/> (which is the default or
+    <configure> and <compile> steps) then this cleanup needs to happen
+    whenever the step fails.
+-->
+<xsl:template name="if-del-on-fail">
+    <xsl:param name="content"/>
+    <xsl:if test = "position() = last() or
+                    haltOnFailure = '' or
+                    haltOnFailure = 'true' or
+                    (not(haltOnFailure) and
+                        (name() = 'configure' or name() = 'compile'))">
+        <xsl:copy-of select="$content"/>
+    </xsl:if>
+</xsl:template>
+
+<!--
+    Add slave locks so that each testdrive machine only runs one bulid at a
+    time
+-->
+<xsl:for-each select="../build/sandbox">
+    <xsl:if test="not(../preceding-sibling::build[sandbox = current()])">
+        <slavelock>
+            <name><xsl:apply-templates select="node()"/></name>
+        </slavelock>
+    </xsl:if>
+</xsl:for-each>
+
+<xsl:template name="sandbox">
+    <xsl:param name="content"/>
+    <sandbox><xsl:copy-of select="$content"/></sandbox>
+    <lock><xsl:copy-of select="$content"/></lock>
+</xsl:template>
+
+<!--
+    basename - returns the final component of a path
+
+    Usage: <basename>/foo/bar</basename>
+
+    Evaluates to 'bar'.
+-->
+<xsl:template name="basename">
+    <xsl:param name="path"/>
+    <xsl:choose>
+        <xsl:when test="contains($path, '/')">
+            <xsl:call-template name="basename">
+                <xsl:with-param name="path" select="substring-after($path, '/')"/>
+            </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:value-of select="$path"/>
+        </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+
+</bot>
diff --git a/build/buildbot/tools/bot.xsd b/build/buildbot/tools/bot.xsd
new file mode 100644 (file)
index 0000000..f19fbc1
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema">
+    <element name="bot">
+        <!-- todo -->
+    </element>
+</schema>
diff --git a/build/buildbot/tools/embedded.xsl b/build/buildbot/tools/embedded.xsl
new file mode 100644 (file)
index 0000000..ee429f0
--- /dev/null
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+    Name:       embedded.xsl
+    Purpose:    Embedded XSLT
+    Author:     Mike Wetherell
+    RCS-ID:     $Id$
+    Copyright:  (c) 2007 Mike Wetherell
+    Licence:    wxWidgets licence
+-->
+
+<transform xmlns="http://www.w3.org/1999/XSL/Transform"
+           xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+           xmlns:XSL="XSL"
+           version="1.0">
+
+<namespace-alias stylesheet-prefix="XSL" result-prefix="xsl"/>
+
+<output indent="yes"/>
+
+<variable
+    name="top-level-base"
+    select="/*/xsl:import |
+            /*/xsl:include |
+            /*/xsl:attribute-set |
+            /*/xsl:character-map |
+            /*/xsl:decimal-format |
+            /*/xsl:function |
+            /*/xsl:import-schema |
+            /*/xsl:key |
+            /*/xsl:namespace-alias |
+            /*/xsl:output |
+            /*/xsl:param |
+            /*/xsl:preserve-space |
+            /*/xsl:strip-space |
+            /*/xsl:variable"/>
+
+<variable
+    name="top-level"
+    select="$top-level-base |
+            /*/xsl:template"/>
+
+<variable
+    name="top-level-copy"
+    select="$top-level-base |
+            /*/xsl:template
+                [not(following-sibling::xsl:template/@name = @name)]"/>
+
+<template match="/">
+    <XSL:transform>
+        <copy-of select="/*/namespace::*"/>
+
+        <for-each select="/*/@xsl:*">
+            <attribute name="{local-name()}">
+                <value-of select="."/>
+            </attribute>
+        </for-each>
+
+        <apply-templates mode="copy-xsl" select="$top-level-copy"/>
+        <apply-templates select="*"/>
+    </XSL:transform>
+</template>
+
+<template match="*">
+    <variable name="pattern">
+        <call-template name="coord-pattern"/>
+    </variable>
+
+    <XSL:template match="*[generate-id() = generate-id(document('', /){$pattern})]">
+        <copy-of select="namespace::*"/>
+        <choose>
+            <when test="/*/xsl:template[@name = name(current())]">
+                <call-template name="expand"/>
+            </when>
+            <when test="count($top-level | .) != count($top-level)">
+                <call-template name="create-context"/>
+            </when>
+        </choose>
+    </XSL:template>
+
+    <if test="not(self::xsl:*)">
+        <apply-templates select="node()"/>
+    </if>
+</template>
+
+<template match="text()"/>
+
+<template match="@*">
+    <copy/>
+</template>
+
+<template mode="copy-xsl" match="*[/*/xsl:template/@name = name()]">
+    <choose>
+        <when test="ancestor::xsl:template[@name = name(current())]">
+            <XSL:choose>
+                <XSL:when test="name() = '{name()}'">
+                    <XSL:copy>
+                        <call-template name="copy-xsl-children"/>
+                    </XSL:copy>
+                </XSL:when>
+                <XSL:otherwise>
+                    <copy>
+                        <call-template name="copy-xsl-children"/>
+                    </copy>
+                </XSL:otherwise>
+            </XSL:choose>
+        </when>
+        <otherwise>
+            <call-template name="expand"/>
+        </otherwise>
+    </choose>
+</template>
+
+<template mode="copy-xsl" match="@*|node()">
+    <copy>
+        <call-template name="copy-xsl-children"/>
+    </copy>
+</template>
+
+<template name="copy-xsl-children">
+    <copy-of select="namespace::*"/>
+    <apply-templates mode="copy-xsl" select="@*|node()"/>
+</template>
+
+<template name="coord-pattern">
+    <param name="element" select="."/>
+
+    <for-each select="$element/ancestor-or-self::*">
+        <text>/*[</text>
+        <value-of select="count(preceding-sibling::*) + 1"/>
+        <text>]</text>
+    </for-each>
+</template>
+
+<template name="expand">
+    <variable name="params" select="/*/xsl:template[@name = name(current())]/xsl:param"/>
+
+    <XSL:call-template name="{name()}">
+        <if test="$params">
+            <XSL:with-param name="{$params[1]/@name}">
+                <choose>
+                    <when test="ancestor-or-self::xsl:*">
+                        <apply-templates mode="copy-xsl" select="node()"/>
+                    </when>
+                    <otherwise>
+                        <variable name="pattern">
+                            <call-template name="coord-pattern"/>
+                        </variable>
+                        <XSL:apply-templates select="{$pattern}/node()"/>
+                    </otherwise>
+                </choose>
+            </XSL:with-param>
+        </if>
+
+        <for-each select="@*">
+            <XSL:with-param name="{name()}">
+                <call-template name="avt">
+                    <with-param name="string" select="."/>
+                </call-template>
+            </XSL:with-param>
+        </for-each>
+    </XSL:call-template>
+</template>
+
+<template name="create-context">
+    <param name="elements" select="ancestor-or-self::*
+                                   [last() - 1 > position()]
+                                   /preceding-sibling::xsl:variable | ."/>
+
+    <variable name="pattern">
+        <call-template name="coord-pattern">
+            <with-param name="element" select="$elements[1]"/>
+        </call-template>
+    </variable>
+
+    <variable name="parent-pattern">
+        <call-template name="coord-pattern">
+            <with-param name="element" select="$elements[1]/.."/>
+        </call-template>
+    </variable>
+
+    <XSL:for-each select="{$parent-pattern}/*">
+        <XSL:if test="count({$pattern} | .) = 1">
+            <choose>
+                <when test="$elements[1]/self::xsl:*">
+                    <apply-templates mode="copy-xsl" select="$elements[1]"/>
+                    <if test="$elements[2]">
+                        <call-template name="create-context">
+                            <with-param name="elements" select="$elements[position() > 1]"/>
+                        </call-template>
+                    </if>
+                </when>
+                <otherwise>
+                    <copy>
+                        <apply-templates select="@*"/>
+                        <if test="node()">
+                            <XSL:apply-templates select="node()"/>
+                        </if>
+                    </copy>
+                </otherwise>
+            </choose>
+        </XSL:if>
+    </XSL:for-each>
+</template>
+
+<template name="before">
+    <param name="string"/>
+    <param name="target"/>
+
+    <variable name="apos">'</variable>
+    <variable name="quot">"</variable>
+
+    <variable name="posapos" select="string-length(substring-before(
+                                        concat($string, $apos), $apos))"/>
+    <variable name="posquot" select="string-length(substring-before(
+                                        concat($string, $quot), $quot))"/>
+    <variable name="postarg" select="string-length(substring-before(
+                                        concat($string, $target), $target))"/>
+
+    <choose>
+        <when test="$posapos = $postarg and $posquot = $postarg">
+            <value-of select="$string"/>
+        </when>
+        <when test="$posapos > $postarg and $posquot > $postarg">
+            <value-of select="substring($string, 1, $postarg)"/>
+        </when>
+        <otherwise>
+            <variable name="delim">
+                <choose>
+                    <when test="$posquot > $posapos">'</when>
+                    <otherwise>"</otherwise>
+                </choose>
+            </variable>
+
+            <value-of select="substring-before($string, $delim)"/>
+            <value-of select="$delim"/>
+
+            <variable name="mid" select="substring-after($string, $delim)"/>
+
+            <choose>
+                <when test="contains($mid, $delim)">
+                    <value-of select="substring-before($mid, $delim)"/>
+                    <value-of select="$delim"/>
+
+                    <call-template name="before">
+                        <with-param name="string"
+                                    select="substring-after($mid, $delim)"/>
+                        <with-param name="target"
+                                    select="$target"/>
+                    </call-template>
+                </when>
+                <otherwise>
+                    <value-of select="$mid"/>
+                </otherwise>
+            </choose>
+        </otherwise>
+    </choose>
+</template>
+
+<template name="avt">
+    <param name="string"/>
+
+    <variable name="before1" select="substring-before(concat($string, '{'), '{')"/>
+    <variable name="len1" select="string-length($before1)"/>
+
+    <variable name="before2" select="substring-before(concat($string, '}}'), '}}')"/>
+    <variable name="len2" select="string-length($before2)"/>
+
+    <choose>
+        <when test="$before1 = $string and $before2 = $string">
+            <value-of select="$string"/>
+        </when>
+        <when test="$len2 &lt; $len1">
+            <value-of select="$before2"/>
+            <text>}</text>
+            <call-template name="avt">
+                <with-param name="string" select="substring($string, $len2 + 3)"/>
+            </call-template>
+        </when>
+        <when test="substring($string, $len1 + 2, 1) = '{'">
+            <value-of select="$before1"/>
+            <text>{</text>
+            <call-template name="avt">
+                <with-param name="string" select="substring($string, $len1 + 3)"/>
+            </call-template>
+        </when>
+        <otherwise>
+            <variable name="mid" select="substring($string, $len1 + 2)"/>
+            <variable name="expr">
+                <call-template name="before">
+                    <with-param name="string" select="$mid"/>
+                    <with-param name="target">}</with-param>
+                </call-template>
+            </variable>
+            <value-of select="$before1"/>
+            <XSL:copy-of select="{$expr}"/>
+            <call-template name="avt">
+                <with-param name="string" select="substring($mid, string-length($expr) + 2)"/>
+            </call-template>
+        </otherwise>
+    </choose>
+</template>
+
+</transform>
diff --git a/build/buildbot/tools/preprocess.sh b/build/buildbot/tools/preprocess.sh
new file mode 100755 (executable)
index 0000000..f6a9009
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh
+#############################################################################
+# Name:        preprocess
+# Purpose:     Expand embedded xslt
+# Author:      Mike Wetherell
+# RCS-ID:      $Id$
+# Copyright:   (c) 2007 Mike Wetherell
+# Licence:     wxWidgets licence
+#############################################################################
+
+if [ $# -eq 0 -o ! -f "$1" ]; then
+    echo "Usage: $0 FILE..."
+    echo "Expands embedded xslt"
+    exit 1
+fi >&2
+
+DIR="`dirname $0`"
+
+while [ $# -gt 0 ]; do
+    xsltproc --xinclude $DIR/embedded.xsl "$1" 2>/dev/null |
+        xsltproc --xinclude - "$1"
+    shift
+done
diff --git a/build/buildbot/tools/validate.sh b/build/buildbot/tools/validate.sh
new file mode 100755 (executable)
index 0000000..09a091e
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/sh
+#############################################################################
+# Name:        validate
+# Purpose:     Reports errors in wxWidgets buildbot configuration files
+# Author:      Mike Wetherell
+# RCS-ID:      $Id$
+# Copyright:   (c) 2007 Mike Wetherell
+# Licence:     wxWidgets licence
+#############################################################################
+
+if [ $# -eq 0 -o ! -f "$1" ]; then
+    echo "Usage: $0 FILE..."
+    echo "Reports errors in wxWidgets buildbot configuration files"
+    exit 1
+fi >&2
+
+DIR="`dirname $0`"
+WORKDIR="${TMPDIR:-/tmp}/wx.$$"
+mkdir "$WORKDIR" || exit
+trap 'rm -rf "$WORKDIR"' EXIT
+WORKPAT=`echo "$WORKDIR" | sed 's|[^A-Za-z0-9/]|.|g'`
+
+# Change the names of the temporary files in an error message to something
+# to something more informative
+#
+error()
+{
+    if [ -n "$1" ]; then
+        echo "$1" |
+            sed "s|file ${WORKPAT}|${WORKPAT}|g;\
+                 s|${WORKPAT}/XSLT|generated XSLT (from $NAME)|g;\
+                 s|${WORKPAT}/prep|$NAME (preprocessed)|g"
+    fi
+}
+
+# This is pretty ugly, sorry. It tries not to print the same error more than
+# once, and it tries to send success message to stdout and errors to stderr.
+# It still doesn't return a meaningful exit code.
+#
+while [ $# -gt 0 ]
+do
+    INPUT="$1"
+    NAME="`echo \"$INPUT\" | sed 's/[|\]/\\\&/g'`"
+    XSLT="$WORKDIR/XSLT"
+    OUTPUT="$WORKDIR/prep"
+
+    if STDERR=`xsltproc --xinclude -o "$XSLT" $DIR/embedded.xsl "$INPUT" 2>&1`
+    then
+        STDERR=`xsltproc --xinclude -o "$OUTPUT" "$XSLT" "$INPUT" 2>&1` \
+            && OK=true || OK=false
+        error "$STDERR" >&2
+
+        if $OK; then
+            STDERR=`xmllint --noout --schema $DIR/bot.xsd "$OUTPUT" 2>&1` \
+                && OUT=1 || OUT=2
+            error "$STDERR" >&$OUT
+        fi
+    else
+        error "$STDERR" >&2
+    fi
+
+    rm -f "$XSLT" "$OUTPUT"
+
+    shift
+done