Make generate-automatic-patches your friend instead of your enemy. In particular:
authorBenjamin Smedberg <benjamin@smedbergs.us>
Mon, 14 Jul 2008 15:30:24 -0400
changeset 155 236864c4d239
parent 154 7b66eb66ba95
child 156 1ad802eb2712
push id31
push userbsmedberg@mozilla.com
push dateMon, 14 Jul 2008 19:40:13 +0000
Make generate-automatic-patches your friend instead of your enemy. In particular: * Allow configuration of local paths without having to hack this file * If there's an error, allow restarting in the middle of a repack. Also allow non-clobber behavior (this is untested, though)
.hgignore
generate-automatic-patches.py
generate-automatic-patches.sh
new file mode 100644
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,3 @@
+~$
+\.pyc$
+^status$
new file mode 100644
--- /dev/null
+++ b/generate-automatic-patches.py
@@ -0,0 +1,214 @@
+#!/usr/bin/env python
+
+"""Generate automatic patches and add them to your tree.
+
+You will need to set up a separate xpcomgclocalpaths.py file with the following contents:
+
+garburator = '/path/to/oink'
+porkbarrel = '/path/to/pork-barrel'
+configureporkanalysis = '/path/to/configure-pork-analysis'
+configuregccanalysis = '/path/to/configure-gcc-analysis'
+parallel = 8 # number of parallel processes to use for make -j and pork-barrel
+
+For an example of configure-pork-analysis and configure-gcc-analysis, see http://hg.mozilla.org/users/bsmedberg_mozilla.com/configure-scripts
+"""
+
+from __future__ import with_statement
+
+import sys, getopt
+from os.path import exists, realpath, normpath, dirname
+from os import mkdir, symlink, unlink
+from subprocess import call, check_call, Popen
+from shutil import rmtree
+
+from xpcomgclocalpaths import garburator, porkbarrel, configureporkanalysis, configuregccanalysis, parallel
+
+thisfile = realpath(__file__)
+thisdir = dirname(thisfile)
+rootdir = normpath('%s/../../..' % thisdir)
+srcdir = '%s/src' % rootdir
+porkobjdir = '%s/ff-pork' % rootdir
+analysisobjdir = '%s/ff-gcobject-analysis' % rootdir
+clobber = True
+
+def setup_srcdir(log):
+    """Remove old automatic patches, if any"""
+
+    check_call(['hg', 'qpop', '-a'], cwd=srcdir, stdout=log, stderr=log)
+    call(['hg', 'qrm', 'automatic-gcobject'], cwd=srcdir, stdout=log, stderr=log)
+    call(['hg', 'qrm', 'automatic-garburator'], cwd=srcdir, stdout=log, stderr=log)
+    call(['hg', 'qrm', 'automatic-remove-addrefs'], cwd=srcdir, stdout=log, stderr=log)
+    check_call(['hg', 'qpush', '-a'], cwd=srcdir, stdout=log, stderr=log)
+    check_call(['autoconf-2.13'], cwd=srcdir, stdout=log, stderr=log)
+
+def build_pork(log):
+    """Build pork objdir"""
+
+    if exists(porkobjdir) and clobber:
+            rmtree(porkobjdir)
+    if not exists(porkobjdir):
+        mkdir(porkobjdir)
+
+    with open('%s/pork-build.log' % rootdir, 'w') as errlog:
+        check_call([configureporkanalysis], cwd=porkobjdir,
+                   stdout=errlog, stderr=errlog)
+
+        if exists('%s/config/myrules.mk' % porkobjdir):
+            unlink('%s/config/myrules.mk' % porkobjdir)
+        symlink('%s/pork-rules.mk' % thisdir, '%s/config/myrules.mk' % porkobjdir)
+
+        check_call(['make', '-j%i' % parallel, 'WARNINGS_AS_ERRORS='],
+                   cwd=porkobjdir,
+                   stdout=errlog, stderr=errlog)
+        check_call(['make', 'echo-iifiles', 'IIFILES_LIST=%s/iifiles.list' % rootdir],
+                   cwd=porkobjdir, stdout=errlog, stderr=errlog)
+
+def run_garburator(log):
+    """Run garburator"""
+
+    with open('%s/automatic-garburator.errlog' % rootdir, 'w') as garburator_log:
+        with open('%s/automatic-garburator.patch' % rootdir, 'w+') as garburator_patch:
+            check_call([porkbarrel, '%i' % parallel, '%s/iifiles.list' % rootdir, garburator],
+                       cwd=porkobjdir,
+                       stdout=garburator_patch,
+                       stderr=garburator_log)
+
+            garburator_patch.seek(0)
+
+            with open('%s/automatic-garburator-filtered.patch' % rootdir, 'w') as garburator_filtered_patch:
+                check_call(['filterdiff', '-x', '**nsCOMPtr.h'],
+                           stdin=garburator_patch,
+                           stdout=garburator_filtered_patch,
+                           stderr=garburator_log)
+
+def apply_garburator(log):
+    """Apply the garburator patch"""
+
+    check_call(['hg', 'qnew', 'automatic-garburator'],
+               cwd=srcdir, stdout=log, stderr=log)
+    with open('%s/automatic-garburator-filtered.patch' % rootdir) as garburator_filtered_patch:
+        check_call(['patch', '-p0'], cwd=porkobjdir,
+                   stdin=garburator_filtered_patch,
+                   stdout=log, stderr=log)
+    check_call(['hg', 'qrefresh', '-m', 'Automatically generated patch: convert stack nsCOMPtrs to raw pointers'],
+               cwd=srcdir, stdout=log, stderr=log)
+
+def build_gcobject(log):
+    """Build the GCObject analysis"""
+
+    if exists(analysisobjdir) and clobber:
+            rmtree(analysisobjdir)
+    if not exists(analysisobjdir):
+        mkdir(analysisobjdir)
+
+    with open('%s/analysis-build.log' % rootdir, 'w') as errlog:
+        check_call([configuregccanalysis], cwd=analysisobjdir,
+                   stdout=errlog, stderr=errlog)
+
+        if exists('%s/config/myconfig.mk' % analysisobjdir):
+            unlink('%s/config/myconfig.mk')
+        symlink ('%s/gcobject-config.mk' % thisdir,
+                 '%s/config/myconfig.mk' % analysisobjdir)
+
+        check_call(['make', '-j%i' % parallel, 'WARNINGS_AS_ERRORS='],
+                   cwd=analysisobjdir,
+                   stdout=errlog, stderr=errlog)
+
+def run_gcobject(log):
+    """Generate the GCObject patch"""
+
+    # Turn this into a module instead of a subprocess
+    with open('%s/automatic-gcobject.errlog' % rootdir, 'w') as errlog:
+        with open('%s/automatic-gcobject.patch' % rootdir, 'w') as patch:
+            check_call(['python', '%s/add-gcobject-inheritance.py' % thisdir,
+                        analysisobjdir],
+                       stdout=patch,
+                       stderr=errlog)
+
+def apply_gcobject(log):
+    """Apply the GCObject patch"""
+
+    check_call(['hg', 'qnew', 'automatic-gcobject'],
+               cwd=srcdir, stdout=log, stderr=log)
+    with open('%s/automatic-gcobject.patch' % rootdir) as gcobject_patch:
+        check_call(['patch', '-p0'],
+                   cwd=srcdir,
+                   stdin=gcobject_patch,
+                   stdout=log, stderr=log)
+    check_call(['hg', 'qrefresh', '-m', 'Automatically generated patch: make all XPCOM objects inherit from XPCOMGCFinalizedObject'],
+               cwd=srcdir, stdout=log, stderr=log)
+
+def run_removeaddrefs(log):
+    """Remove NS_ADDREF and similar macro-junk"""
+
+    # Turn this into a module instead of a subprocess
+    with open('%s/automatic-remove-addrefs.patch' % rootdir, 'w') as patch:
+        check_call(['python', '%s/remove-addrefs.py' % thisdir, srcdir],
+                   stdout=patch,
+                   stderr=log)
+
+def apply_removeaddrefs(log):
+    """Apply the addref removal patch"""
+    check_call(['hg', 'qnew', 'automatic-remove-addrefs'],
+               cwd=srcdir, stdout=log, stderr=log)
+    with open('%s/automatic-remove-addrefs.patch' % rootdir) as addrefs_patch:
+        check_call(['patch', '-p0'],
+                   cwd=srcdir,
+                   stdin=addrefs_patch,
+                   stdout=log, stderr=log)
+    check_call(['hg', 'qrefresh', '-m', 'Automatically generated patch: remove no-op calls to NS_ADDREF and NS_IF_ADDREF'],
+               cwd=srcdir, stdout=log, stderr=log)
+
+steps = (('setup_srcdir', setup_srcdir),
+         ('build_pork', build_pork),
+         ('run_garburator', run_garburator),
+         ('apply_garburator', apply_garburator),
+         ('build_gcobject', build_gcobject),
+         ('run_gcobject', run_gcobject),
+         ('apply_gcobject', apply_gcobject),
+         ('run_removeaddrefs', run_removeaddrefs),
+         ('apply_removeaddrefs', apply_removeaddrefs),
+         )
+
+# I would use optionparser, but I can't get it to format this
+# usage the way I want
+
+steplist = "".join("\n    %-20s %.50s" % (key, f.__doc__)
+                   for key, f in steps)
+
+usage = """python generated-patches.py [options]
+  -h, --help       show this help message and exit
+  --start=stepname Start at a particular step:%s
+  --no-clobber     Rebuild objdirs without clobbering""" % steplist
+
+options, arguments = getopt.getopt(sys.argv[1:], 'h',
+                                   ('start=', 'no-clobber', 'help'))
+
+startstep = 0
+for name, value in options:
+    if name in ('-h', '--help'):
+        print usage
+        sys.exit(0)
+
+    if name == '--start':
+        found = False
+        for i in xrange(0, len(steps)):
+            if steps[i][0] == value:
+                startstep = i
+                found = True
+                break
+        if not found:
+            print >>sys.stderr, "'%s' is not a step" % value
+            sys.exit(1)
+
+    if name == '--no-clobber':
+        clobber = False
+
+with open('%s/generate-patches.log' % rootdir, 'w') as general_log:
+    for i in xrange(startstep, len(steps)):
+        key, f = steps[i]
+        print "%s: %s..." % (key, f.__doc__),
+        sys.stdout.flush()
+        f(general_log)
+        print "OK"
+        sys.stdout.flush()
deleted file mode 100755
--- a/generate-automatic-patches.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/bin/bash
-
-# Generate all the automatic patches and put them next to this script
-# (in the .hg/patches directory probably)
-
-set -e;
-
-this=$0
-thisreldir=`dirname $this`
-thisdir=`cd $thisreldir && pwd`
-rootdir=`cd "$thisdir/../../.." && pwd`
-srcdir="$rootdir/src"
-porkobjdir="$rootdir/ff-pork"
-analysisobjdir="$rootdir/ff-gcobject-analysis"
-oinkdir=/builds/oink-stack/oink
-porkbarrel=/builds/pork-barrel/pork-barrel
-gccdehydra=/builds/gcc-dehydra/installed/bin/g++
-dehydra=/builds/gcc-dehydra/dehydra/gcc_dehydra.so
-
-printf "Removing old automatic patches, if any\n"
-
-hg -R "$srcdir" qpop -a;
-hg -R "$srcdir" qrm empty-patch-before-automatic || true;
-hg -R "$srcdir" qrm automatic-gcobject || true;
-hg -R "$srcdir" qrm automatic-garburator || true;
-hg -R "$srcdir" qrm automatic-remove-addrefs || true;
-hg -R "$srcdir" qrm empty-patch-after-automatic || true;
-hg -R "$srcdir" qpush -a;
-(cd "$srcdir" && autoconf-2.13);
-
-printf "Building ff-pork\n"
-
-rm -rf "$porkobjdir";
-mkdir -p "$porkobjdir/config";
-install "$thisdir/pork-rules.mk" "$porkobjdir/config/myrules.mk";
-(cd "$porkobjdir" && /builds/configure-scripts/configure-pork-analysis && make -j8 WARNINGS_AS_ERRORS= >"$rootdir/pork-build.log" 2>&1 ) || exit 1;
-
-rm -f "$rootdir/iifiles.list";
-(cd "$porkobjdir" && make echo-iifiles IIFILES_LIST="$rootdir/iifiles.list") || exit 1;
-
-printf "Running garburator\n"
-
-(cd "$porkobjdir" && "$porkbarrel" 8 "$rootdir/iifiles.list" "$oinkdir/garburator") >"$rootdir/automatic-garburator.patch" 2>"$rootdir/automatic-garburator.errlog" || exit 1;
-
-filterdiff -x "**nsCOMPtr.h" < "$rootdir/automatic-garburator.patch" > "$rootdir/automatic-garburator-filtered.patch"
-
-printf "Applying automatic-garburator\n"
-
-hg -R "$srcdir" qnew empty-patch-before-automatic
-hg -R "$srcdir" qnew automatic-garburator
-(cd "$porkobjdir" && patch -p0 <"$rootdir/automatic-garburator-filtered.patch") || exit 1
-hg -R "$srcdir" qrefresh -m "Automatically generated patch: convert stack nsCOMPtrs to raw pointers"
-
-printf "Building ff-gcobject-analysis\n"
-
-rm -rf "$analysisobjdir"
-mkdir -p "$analysisobjdir/config"
-install "$thisdir/gcobject-config.mk" "$analysisobjdir/config/myconfig.mk"
-(cd "$analysisobjdir" && /builds/configure-scripts/configure-gcc-analysis && make -j8 WARNINGS_AS_ERRORS= >"$rootdir/analysis-build.log" 2>&1 ) || exit 1;
-
-printf "Generating gcobject patch\n"
-
-python "$thisdir/add-gcobject-inheritance.py" "$analysisobjdir" >"$rootdir/automatic-gcobject.patch" 2>"$rootdir/automatic-gcobject.errlog"
-
-printf "Applying gcobject patch\n"
-
-hg -R "$srcdir" qnew automatic-gcobject
-patch -p0 <"$rootdir/automatic-gcobject.patch"
-hg -R "$srcdir" qrefresh -m "Automatically generated patch: make all XPCOM objects inherit from XPCOMGCFinalizedObject"
-
-printf "Generating remove-addrefs patch\n"
-
-python "$thisdir/remove-addrefs.py" "$srcdir" >"$rootdir/automatic-remove-addrefs.patch" 2>"$rootdir/automatic-remove-addrefs.errlog"
-
-printf "Applying remove-addrefs patch\n"
-
-hg -R "$srcdir" qnew automatic-remove-addrefs
-patch -p0 < "$rootdir/automatic-remove-addrefs.patch"
-hg -R "$srcdir" qrefresh -m "Automatically generated patch: remove no-op calls to NS_ADDREF and NS_IF_ADDREF"
-
-hg -R "$srcdir" qnew empty-patch-after-automatic
-
-printf "Done"