Index: source-builder/defaults.mc
===================================================================
--- source-builder/defaults.mc	(revision 0d59530b2f3d8cc65c43fbf3b739750dfa9e066e)
+++ source-builder/defaults.mc	(revision e8f511157c396e19308a6cbed2de2dc8258f275d)
@@ -45,4 +45,7 @@
 release:             none,    none,     ''
 buildname:           none,    none,     '%{name}'
+
+# The default is not release.
+is_rsb_release:      none,    none,     '0'
 
 # GNU triples needed to build packages
Index: source-builder/sb/bootstrap.py
===================================================================
--- source-builder/sb/bootstrap.py	(revision 0d59530b2f3d8cc65c43fbf3b739750dfa9e066e)
+++ source-builder/sb/bootstrap.py	(revision e8f511157c396e19308a6cbed2de2dc8258f275d)
@@ -243,5 +243,5 @@
         optargs = { '--rtems':       'The RTEMS source directory',
                     '--preinstall':  'Preinstall AM generation' }
-        log.notice('RTEMS Source Builder - RTEMS Bootstrap, v%s' % (version.str()))
+        log.notice('RTEMS Source Builder - RTEMS Bootstrap, %s' % (version.str()))
         opts = options.load(sys.argv, optargs)
         if opts.get_arg('--rtems'):
Index: source-builder/sb/build.py
===================================================================
--- source-builder/sb/build.py	(revision 0d59530b2f3d8cc65c43fbf3b739750dfa9e066e)
+++ source-builder/sb/build.py	(revision e8f511157c396e19308a6cbed2de2dc8258f275d)
@@ -535,5 +535,5 @@
         optargs = { '--list-configs': 'List available configurations' }
         opts = options.load(args, optargs)
-        log.notice('RTEMS Source Builder, Package Builder v%s' % (version.str()))
+        log.notice('RTEMS Source Builder, Package Builder, %s' % (version.str()))
         if not check.host_setup(opts):
             if not opts.force():
Index: source-builder/sb/check.py
===================================================================
--- source-builder/sb/check.py	(revision 0d59530b2f3d8cc65c43fbf3b739750dfa9e066e)
+++ source-builder/sb/check.py	(revision e8f511157c396e19308a6cbed2de2dc8258f275d)
@@ -163,5 +163,5 @@
     try:
         _opts = options.load(args = sys.argv)
-        log.notice('RTEMS Source Builder - Check, v%s' % (version.str()))
+        log.notice('RTEMS Source Builder - Check, %s' % (version.str()))
         if host_setup(_opts):
             print 'Environment is ok'
Index: source-builder/sb/options.py
===================================================================
--- source-builder/sb/options.py	(revision 0d59530b2f3d8cc65c43fbf3b739750dfa9e066e)
+++ source-builder/sb/options.py	(revision e8f511157c396e19308a6cbed2de2dc8258f275d)
@@ -302,4 +302,10 @@
                 self.defaults.load(rsb_macros)
 
+    def sb_released(self):
+        if version.released():
+            self.defaults['is_rsb_released'] = '1'
+            self.defaults['_sbreleased'] = '1'
+            self.defaults['_sbversion'] = version.str()
+
     def sb_git(self):
         repo = git.repo(self.defaults.expand('%{_sbdir}'), self)
@@ -614,4 +620,5 @@
         o.defaults[k] = overrides[k]
 
+    o.sb_released()
     o.sb_git()
     o.rtems_options()
@@ -624,5 +631,5 @@
     try:
         _opts = load(args = args, defaults = 'defaults.mc')
-        log.notice('RTEMS Source Builder - Defaults, v%s' % (version.str()))
+        log.notice('RTEMS Source Builder - Defaults, %s' % (version.str()))
         _opts.log_info()
         log.notice('Options:')
Index: source-builder/sb/reports.py
===================================================================
--- source-builder/sb/reports.py	(revision 0d59530b2f3d8cc65c43fbf3b739750dfa9e066e)
+++ source-builder/sb/reports.py	(revision e8f511157c396e19308a6cbed2de2dc8258f275d)
@@ -1,5 +1,5 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2013 Chris Johns (chrisj@rtems.org)
+# Copyright 2010-2015 Chris Johns (chrisj@rtems.org)
 # All rights reserved.
 #
@@ -54,4 +54,5 @@
 _title = 'RTEMS Tools Project <users@rtems.org>'
 
+_release_status_text = 'RTEMS Source Builder Release'
 _git_status_text = 'RTEMS Source Builder Repository Status'
 
@@ -105,5 +106,5 @@
     def buildset_start(self, nest_level, name):
         self.line('=-' * (_line_len / 2))
-        self.line('Build Set: %s' % (name))
+        self.line('Build Set: (%d) %s' % (nest_level, name))
 
     def buildset_end(self, nest_level, name):
@@ -166,4 +167,14 @@
         if intro_text:
             self.line('%s' % ('\n'.join(intro_text)))
+
+    def release_status(self, release_string):
+        self.line('')
+        self.line("'''")
+        self.line('')
+        self.line('.%s' % (_release_status_text))
+        self.line('*Version*: %s;;' % (release_string))
+        self.line('')
+        self.line("'''")
+        self.line('')
 
     def git_status(self, valid, dirty, head, remotes):
@@ -294,4 +305,12 @@
         self.line('Report: %s' % (name))
 
+    def release_status_header(self):
+        self.line('-' * _line_len)
+        self.line('%s' % (_release_status_text))
+
+    def release_status(self, release_string):
+        self.release_status_header()
+        self.line('%s Version: %s' % (self.cini, release_string))
+
     def git_status_header(self):
         self.line('-' * _line_len)
@@ -325,4 +344,6 @@
         super(ini_formatter, self).__init__()
         self.cini = ';'
+        self.ini_pkg = {}
+        self.name = None
 
     def format(self):
@@ -340,4 +361,24 @@
             self.line(';')
 
+    def epilogue(self, name):
+        pkgs = sorted(self.ini_pkg.keys())
+        for pkg in pkgs:
+            self.line('')
+            self.line('[%s]' % (pkg))
+            items = sorted(self.ini_pkg[pkg].keys())
+            for item in items:
+                i = self.ini_pkg[pkg][item]
+                if len(i) == 1:
+                    self.line('%s = "%s"' % (item, i[0]))
+                else:
+                    self.line('%s = <<<DATA' % (item))
+                    self.line('\n'.join(i))
+                    self.line('DATA')
+        self.line('')
+
+    def release_status_header(self):
+        self.line(';')
+        self.line('; %s' % (_release_status_text))
+
     def git_status_header(self):
         self.line(';')
@@ -346,17 +387,29 @@
 
     def config(self, nest_level, name, _config):
-        return
+        pass
 
     def buildset_start(self, nest_level, name):
-        return
+        if name.endswith('.cfg'):
+            self.name = path.basename(name[:-4])
+            if self.name not in self.ini_pkg:
+                self.ini_pkg[self.name] = {}
+
+    def buildset_end(self, nest_level, name):
+        self.name = None
 
     def info(self, nest_level, name, info, separated):
-        return
+        if self.name:
+            if 'info' not in self.ini_pkg[self.name]:
+                self.ini_pkg[self.name]['info'] = []
+            self.ini_pkg[self.name]['info'] += info
 
     def directive(self, nest_level, name, data):
-        return
+        if self.name:
+            if name not in self.ini_pkg[self.name]:
+                self.ini_pkg[self.name][name] = []
+            self.ini_pkg[self.name][name] += data
 
     def files(self, nest_level, singular, plural, _files):
-        return
+        pass
 
 class xml_formatter(formatter):
@@ -377,4 +430,9 @@
     def epilogue(self, name):
         self.line('</RTEMSSourceBuilderReport>')
+
+    def release_status(self, release_string):
+        self.line('\t<Release>')
+        self.line('\t\t<Version>%s</Version>' % (release_string))
+        self.line('\t</Release>')
 
     def git_status(self, valid, dirty, head, remotes):
@@ -470,5 +528,5 @@
 
     def output(self, text):
-        self.out += text + '\n'
+        self.formatter.line(text)
 
     def is_ini(self):
@@ -480,4 +538,7 @@
     def footer(self):
         pass
+
+    def release_status(self):
+        self.formatter.release_status(version.str())
 
     def git_status(self):
@@ -488,5 +549,8 @@
         now = datetime.datetime.now().ctime()
         self.formatter.introduction(name, now, intro_text)
-        self.git_status()
+        if version.released():
+            self.release_status()
+        else:
+            self.git_status()
 
     def epilogue(self, name):
@@ -505,4 +569,5 @@
 
     def buildset_start(self, name):
+        self.bset_nesting += 1
         self.files['buildsets'] += [name]
         self.formatter.buildset_start(self.bset_nesting, name)
@@ -510,4 +575,5 @@
     def buildset_end(self, name):
         self.formatter.buildset_end(self.bset_nesting, name)
+        self.bset_nesting -= 1
 
     def source(self, macros):
@@ -546,4 +612,11 @@
         if directive is not None:
             self.formatter.directive(self.bset_nesting + 2, name, directive)
+
+    def tree_packages(self, tree, packages = []):
+        if 'bset' in tree:
+            for node in sorted(tree['bset'].keys()):
+                packages += [_tree_name(node)]
+                packages += self.tree_packages(tree['bset'][node], packages)
+        return set(packages)
 
     def tree_sources(self, name, tree, sources = []):
@@ -627,24 +700,4 @@
                                        prefix)
 
-    def generate_ini_node(self, name, tree, sections = []):
-        if name not in sections:
-            sections += [name]
-            self.output('')
-            self.output('[%s]' % (name))
-            if 'bset' in tree and len(tree['bset']):
-                self.output(' packages = %s' % \
-                                (', '.join([_tree_name(n) for n in sorted(tree['bset'])])))
-            if 'cfg' in tree:
-                packages = {}
-                if 'sources' in tree['cfg']:
-                    _merge(packages, tree['cfg']['sources'])
-                if 'patches' in tree['cfg']:
-                    _merge(packages, tree['cfg']['patches'])
-                for package in packages:
-                    self.output(' %s = %s' % (package, ', '.join([s[0] for s in packages[package]])))
-            if 'bset' in tree:
-                for node in sorted(tree['bset'].keys()):
-                    self.generate_ini_node(_tree_name(node), tree['bset'][node], sections)
-
     def generate_ini_source(self, sources):
         self.output('')
@@ -665,5 +718,4 @@
 
     def generate_ini(self):
-        #self.output(pp.pformat(self.tree))
         nodes = sorted([node for node in self.tree.keys() if node != 'bset'])
         self.output(';')
@@ -682,11 +734,7 @@
         self.generate_ini_source(sources)
         self.generate_ini_hash(sources)
-        for node in nodes:
-            self.generate_ini_node(_tree_name(node), self.tree[node])
 
     def write(self, name):
         self.out = self.formatter.post_process()
-        if self.is_ini():
-            self.generate_ini()
         if name is not None:
             try:
@@ -699,5 +747,4 @@
 
     def generate(self, name, tree = None, opts = None, macros = None):
-        self.bset_nesting += 1
         self.buildset_start(name)
         if tree is None:
@@ -716,14 +763,17 @@
                 self.generate(c, tree[name]['bset'], bset.opts, macros)
             elif c.endswith('.cfg'):
+                self.buildset_start(c)
                 self.config(config.file(c, bset.opts, macros),
                             tree[name]['cfg'], bset.opts, macros)
+                self.buildset_end(c)
             else:
                 raise error.general('invalid config type: %s' % (c))
         self.buildset_end(name)
-        self.bset_nesting -= 1
 
     def create(self, inname, outname = None, intro_text = None):
         self.introduction(inname, intro_text)
         self.generate(inname)
+        if self.is_ini():
+            self.generate_ini()
         self.epilogue(inname)
         self.write(outname)
@@ -738,5 +788,5 @@
         if opts.get_arg('--output') and len(opts.params()) > 1:
             raise error.general('--output can only be used with a single config')
-        print 'RTEMS Source Builder, Reporter v%s' % (version.str())
+        print 'RTEMS Source Builder, Reporter, %s' % (version.str())
         opts.log_info()
         if not check.host_setup(opts):
Index: source-builder/sb/rtemsconfig.py
===================================================================
--- source-builder/sb/rtemsconfig.py	(revision 0d59530b2f3d8cc65c43fbf3b739750dfa9e066e)
+++ source-builder/sb/rtemsconfig.py	(revision e8f511157c396e19308a6cbed2de2dc8258f275d)
@@ -192,5 +192,5 @@
 
         if opts.get_arg('--list'):
-            log.notice('RTEMS Source Builder - RTEMS Configuration, v%s' % (version.str()))
+            log.notice('RTEMS Source Builder - RTEMS Configuration, %s' % (version.str()))
             opts.log_info()
             configs = bsp.keys()
Index: source-builder/sb/setbuilder.py
===================================================================
--- source-builder/sb/setbuilder.py	(revision 0d59530b2f3d8cc65c43fbf3b739750dfa9e066e)
+++ source-builder/sb/setbuilder.py	(revision e8f511157c396e19308a6cbed2de2dc8258f275d)
@@ -469,5 +469,5 @@
         mailer.append_options(optargs)
         opts = options.load(sys.argv, optargs)
-        log.notice('RTEMS Source Builder - Set Builder, v%s' % (version.str()))
+        log.notice('RTEMS Source Builder - Set Builder, %s' % (version.str()))
         opts.log_info()
         if not check.host_setup(opts):
Index: source-builder/sb/version.py
===================================================================
--- source-builder/sb/version.py	(revision 0d59530b2f3d8cc65c43fbf3b739750dfa9e066e)
+++ source-builder/sb/version.py	(revision e8f511157c396e19308a6cbed2de2dc8258f275d)
@@ -1,5 +1,5 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2014 Chris Johns (chrisj@rtems.org)
+# Copyright 2010-2015 Chris Johns (chrisj@rtems.org)
 # All rights reserved.
 #
@@ -19,8 +19,13 @@
 
 #
-# Manage paths locally. The internally the path is in Unix or shell format and
-# we convert to the native format when performing operations at the Python
-# level. This allows macro expansion to work.
+# To release the RSB create a git archive and then add a suitable VERSION file
+# to the top directory.
 #
+
+import sys
+
+import error
+import git
+import path
 
 major = 4
@@ -28,6 +33,57 @@
 revision = 0
 
+#
+# Default to an internal string.
+#
+_version_str =  '%d.%d.%d' % (major, minor, revision)
+_released = False
+_git = False
+
+def _top():
+    top = path.dirname(sys.argv[0])
+    if len(top) == 0:
+        top = '.'
+    return top
+
+def _load_released_version():
+    global _released
+    global _version_str
+    top = _top()
+    for ver in [top, '..']:
+        if path.exists(path.join(ver, 'VERSION')):
+            try:
+                with open(path.join(ver, 'VERSION')) as v:
+                    _version_str = v.readline().strip()
+                v.close()
+                _released = True
+            except:
+                raise error.general('Cannot access the VERSION file')
+    return _released
+
+def _load_git_version():
+    global _git
+    global _version_str
+    repo = git.repo(_top())
+    if repo.valid():
+        head = repo.head()
+        if repo.dirty():
+            modified = ' modified'
+        else:
+            modified = ''
+        _version_str = '%d.%d.%d (%s%s)' % (major, minor, revision, head[0:12], modified)
+        _git = True
+    return _git
+
+def released():
+    return _load_released_version()
+
+def version_control():
+    return _load_git_version()
+
 def str():
-    return '%d.%d.%d'% (major, minor, revision)
+    if not _released and not _git:
+        if not _load_released_version():
+            _load_git_version()
+    return _version_str
 
 if __name__ == '__main__':
