Index: source-builder/sb/build.py
===================================================================
--- source-builder/sb/build.py	(revision 2a6acc72678d8af730efea47806de28e710c94a7)
+++ source-builder/sb/build.py	(revision 74da24cb61ef4478ca499c029a732cdba13ee668)
@@ -37,4 +37,5 @@
     import download
     import error
+    import ereport
     import execute
     import log
@@ -263,5 +264,6 @@
         exit_code, proc, output = e.shell(cmd, cwd = path.host(cwd))
         if exit_code != 0:
-            raise error.general('shell cmd failed: %s' % (cmd))
+            log.output('shell cmd failed: %s' % (cmd))
+            raise error.general('building %s' % (self.macros['buildname']))
 
     def builddir(self):
@@ -432,4 +434,8 @@
 
 def run(args):
+    ec = 0
+    opts = None
+    b = None
+    erheader = None
     try:
         optargs = { '--list-configs': 'List available configurations' }
@@ -452,19 +458,27 @@
                 b = build(config_file, True, opts)
                 b.make()
-                del b
+                b = None
     except error.general, gerr:
-        print gerr
-        print >> sys.stderr, 'Build FAILED'
-        sys.exit(1)
+        erheader = 'Build: %s' % (gerr)
+        log.notice(str(gerr))
+        log.stderr('Build FAILED')
+        ec = 1
     except error.internal, ierr:
-        print ierr
-        print >> sys.stderr, 'Build FAILED'
-        sys.exit(1)
+        erheader = 'Build: %s' % (ierr)
+        log.notice(str(ierr))
+        log.stderr('Internal Build FAILED')
+        ec = 1
     except error.exit, eerr:
         pass
     except KeyboardInterrupt:
         log.notice('abort: user terminated')
-        sys.exit(1)
-    sys.exit(0)
+        ec = 1
+    if (ec != 0 and erheader and opts and b) or (opts and opts.dry_run()):
+        if opts.dry_run():
+            bname = 'dry-run'
+        else:
+            bname = b.name()
+        ereport.generate('rsb-report-%s.txt' % (bname), opts, erheader)
+    sys.exit(ec)
 
 if __name__ == "__main__":
Index: source-builder/sb/ereport.py
===================================================================
--- source-builder/sb/ereport.py	(revision 74da24cb61ef4478ca499c029a732cdba13ee668)
+++ source-builder/sb/ereport.py	(revision 74da24cb61ef4478ca499c029a732cdba13ee668)
@@ -0,0 +1,53 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2014 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-testing'.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# Create an error log.
+#
+
+import os
+
+import error
+import log
+
+def generate(name, opts, header = None, footer = None):
+    r = ['RTEMS Tools Project - Source Builder Error Report'] + []
+    if header:
+        r += [' %s' % (header)]
+    r += [opts.info()]
+    if opts.defaults.get_value('%{_sbgit_valid}') == '1':
+        r += [' %s/%s' % (opts.defaults.get_value('%{_sbgit_remotes}'),
+                          opts.defaults.get_value('%{_sbgit_id}'))]
+    else:
+        r += [' RSB: not a valid repo']
+    r += [' %s' % (' '.join(os.uname()))]
+    r += []
+    r += ['Tail of the build log:']
+    r += log.tail()
+    if footer:
+        r += [footer]
+    try:
+        name = name.replace('/', '-')
+        l = open(name, 'w')
+        l.write(os.linesep.join(r))
+        l.close()
+        log.notice('  See error report: %s' % (name))
+    except:
+        log.stderr('error: failure to create error report')
+        raise
Index: source-builder/sb/freebsd.py
===================================================================
--- source-builder/sb/freebsd.py	(revision 2a6acc72678d8af730efea47806de28e710c94a7)
+++ source-builder/sb/freebsd.py	(revision 74da24cb61ef4478ca499c029a732cdba13ee668)
@@ -84,5 +84,5 @@
         if check.check_exe(cxx, cxx):
             defines['__cxx'] = cxx
-            defines['optflags_build'] = '-O2 -pipe -fbracket-depth=1024'
+            #defines['optflags_build'] = '-O2 -pipe -fbracket-depth=1024'
         cvs = 'cvs'
         if check.check_exe(cvs, cvs):
Index: source-builder/sb/git.py
===================================================================
--- source-builder/sb/git.py	(revision 2a6acc72678d8af730efea47806de28e710c94a7)
+++ source-builder/sb/git.py	(revision 74da24cb61ef4478ca499c029a732cdba13ee668)
@@ -51,8 +51,8 @@
         return exit_code, output
 
-    def __init__(self, _path, opts, macros = None):
+    def __init__(self, _path, opts = None, macros = None):
         self.path = _path
         self.opts = opts
-        if macros is None:
+        if macros is None and opts is not None:
             self.macros = opts.defaults
         else:
Index: source-builder/sb/log.py
===================================================================
--- source-builder/sb/log.py	(revision 2a6acc72678d8af730efea47806de28e710c94a7)
+++ source-builder/sb/log.py	(revision 74da24cb61ef4478ca499c029a732cdba13ee668)
@@ -87,7 +87,14 @@
         default.flush()
 
+def tail(log = None):
+    if log is not None:
+        return log.tail
+    if default is not None:
+        return default.tail
+    return 'No log output'
+
 class log:
     """Log output to stdout or a file."""
-    def __init__(self, streams = None, tail_size = 100):
+    def __init__(self, streams = None, tail_size = 200):
         self.tail = []
         self.tail_size = tail_size
Index: source-builder/sb/options.py
===================================================================
--- source-builder/sb/options.py	(revision 2a6acc72678d8af730efea47806de28e710c94a7)
+++ source-builder/sb/options.py	(revision 74da24cb61ef4478ca499c029a732cdba13ee668)
@@ -304,4 +304,8 @@
             repo_head = repo.head()
             repo_clean = not repo.dirty()
+            repo_remotes = '%{nil}'
+            remotes = repo.remotes()
+            if 'origin' in remotes:
+                repo_remotes = '%s/origin' % (remotes['origin']['url'])
             repo_id = repo_head
             if not repo_clean:
@@ -312,4 +316,5 @@
             repo_head = '%{nil}'
             repo_clean = '%{nil}'
+            repo_remotes = '%{nil}'
             repo_id = 'no-repo'
             repo_mail = None
@@ -317,4 +322,5 @@
         self.defaults['_sbgit_head']  = repo_head
         self.defaults['_sbgit_clean'] = str(repo_clean)
+        self.defaults['_sbgit_remotes'] = str(repo_remotes)
         self.defaults['_sbgit_id']    = repo_id
         if repo_mail is not None:
@@ -463,7 +469,11 @@
         return self.opts['no-download'] != '0'
 
+    def info(self):
+        s = ' Command Line: %s%s' % (' '.join(self.argv), os.linesep)
+        s += ' Python: %s' % (sys.version.replace('\n', ''))
+        return s
+
     def log_info(self):
-        log.output(' Command Line: %s' % (' '.join(self.argv)))
-        log.output(' Python: %s' % (sys.version.replace('\n', '')))
+        log.output(self.info())
 
 def load(args, optargs = None, defaults = '%{_sbdir}/defaults.mc'):
Index: source-builder/sb/setbuilder.py
===================================================================
--- source-builder/sb/setbuilder.py	(revision 2a6acc72678d8af730efea47806de28e710c94a7)
+++ source-builder/sb/setbuilder.py	(revision 74da24cb61ef4478ca499c029a732cdba13ee668)
@@ -34,4 +34,5 @@
     import check
     import error
+    import ereport
     import log
     import mailer
@@ -424,4 +425,8 @@
 def run():
     import sys
+    ec = 0
+    opts = None
+    b = None
+    erheader = None
     try:
         optargs = { '--list-configs':  'List available configurations',
@@ -451,5 +456,5 @@
                 b = buildset(bset, configs, opts)
                 b.build(deps)
-                del b
+                b = None
         if deps is not None:
             c = 0
@@ -458,16 +463,25 @@
                 print 'dep[%d]: %s' % (c, d)
     except error.general, gerr:
+        erheader = 'Build: %s' % (gerr)
         log.notice(str(gerr))
-        print >> sys.stderr, 'Build FAILED'
-        sys.exit(1)
+        log.stderr('Build FAILED')
+        ec = 1
     except error.internal, ierr:
+        erheader = 'Build: %s' % (ierr)
         log.notice(str(ierr))
-        sys.exit(1)
+        log.stderr('Internal Build FAILED')
+        ec = 1
     except error.exit, eerr:
         pass
     except KeyboardInterrupt:
         log.notice('abort: user terminated')
-        sys.exit(1)
-    sys.exit(0)
+        ec = 1
+    if (ec != 0 and erheader and opts and b) or (opts and opts.dry_run()):
+        if opts.dry_run():
+            bset = 'dry-run'
+        else:
+            bset = b.bset
+        ereport.generate('rsb-report-%s.txt' % (bset), opts, erheader)
+    sys.exit(ec)
 
 if __name__ == "__main__":
