mirror of
https://git.rtems.org/rtems-source-builder
synced 2024-10-09 07:15:10 +08:00
sb: Generate an error report on an error.
Generate an error report users can send to the mailing list with error details.
This commit is contained in:
@@ -36,6 +36,7 @@ try:
|
|||||||
import config
|
import config
|
||||||
import download
|
import download
|
||||||
import error
|
import error
|
||||||
|
import ereport
|
||||||
import execute
|
import execute
|
||||||
import log
|
import log
|
||||||
import options
|
import options
|
||||||
@@ -262,7 +263,8 @@ class build:
|
|||||||
log.output('run: ' + cmd)
|
log.output('run: ' + cmd)
|
||||||
exit_code, proc, output = e.shell(cmd, cwd = path.host(cwd))
|
exit_code, proc, output = e.shell(cmd, cwd = path.host(cwd))
|
||||||
if exit_code != 0:
|
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):
|
def builddir(self):
|
||||||
builddir = self.config.abspath('_builddir')
|
builddir = self.config.abspath('_builddir')
|
||||||
@@ -431,6 +433,10 @@ def find_config(config, configs):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def run(args):
|
def run(args):
|
||||||
|
ec = 0
|
||||||
|
opts = None
|
||||||
|
b = None
|
||||||
|
erheader = None
|
||||||
try:
|
try:
|
||||||
optargs = { '--list-configs': 'List available configurations' }
|
optargs = { '--list-configs': 'List available configurations' }
|
||||||
opts = options.load(args, optargs)
|
opts = options.load(args, optargs)
|
||||||
@@ -451,21 +457,29 @@ def run(args):
|
|||||||
for config_file in opts.config_files():
|
for config_file in opts.config_files():
|
||||||
b = build(config_file, True, opts)
|
b = build(config_file, True, opts)
|
||||||
b.make()
|
b.make()
|
||||||
del b
|
b = None
|
||||||
except error.general, gerr:
|
except error.general, gerr:
|
||||||
print gerr
|
erheader = 'Build: %s' % (gerr)
|
||||||
print >> sys.stderr, 'Build FAILED'
|
log.notice(str(gerr))
|
||||||
sys.exit(1)
|
log.stderr('Build FAILED')
|
||||||
|
ec = 1
|
||||||
except error.internal, ierr:
|
except error.internal, ierr:
|
||||||
print ierr
|
erheader = 'Build: %s' % (ierr)
|
||||||
print >> sys.stderr, 'Build FAILED'
|
log.notice(str(ierr))
|
||||||
sys.exit(1)
|
log.stderr('Internal Build FAILED')
|
||||||
|
ec = 1
|
||||||
except error.exit, eerr:
|
except error.exit, eerr:
|
||||||
pass
|
pass
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
log.notice('abort: user terminated')
|
log.notice('abort: user terminated')
|
||||||
sys.exit(1)
|
ec = 1
|
||||||
sys.exit(0)
|
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__":
|
if __name__ == "__main__":
|
||||||
run(sys.argv)
|
run(sys.argv)
|
||||||
|
53
source-builder/sb/ereport.py
Executable file
53
source-builder/sb/ereport.py
Executable file
@@ -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
|
@@ -83,7 +83,7 @@ def load():
|
|||||||
cxx = '/usr/bin/c++'
|
cxx = '/usr/bin/c++'
|
||||||
if check.check_exe(cxx, cxx):
|
if check.check_exe(cxx, cxx):
|
||||||
defines['__cxx'] = cxx
|
defines['__cxx'] = cxx
|
||||||
defines['optflags_build'] = '-O2 -pipe -fbracket-depth=1024'
|
#defines['optflags_build'] = '-O2 -pipe -fbracket-depth=1024'
|
||||||
cvs = 'cvs'
|
cvs = 'cvs'
|
||||||
if check.check_exe(cvs, cvs):
|
if check.check_exe(cvs, cvs):
|
||||||
defines['__cvs'] = cvs
|
defines['__cvs'] = cvs
|
||||||
|
@@ -50,10 +50,10 @@ class repo:
|
|||||||
self._git_exit_code(exit_code)
|
self._git_exit_code(exit_code)
|
||||||
return exit_code, output
|
return exit_code, output
|
||||||
|
|
||||||
def __init__(self, _path, opts, macros = None):
|
def __init__(self, _path, opts = None, macros = None):
|
||||||
self.path = _path
|
self.path = _path
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
if macros is None:
|
if macros is None and opts is not None:
|
||||||
self.macros = opts.defaults
|
self.macros = opts.defaults
|
||||||
else:
|
else:
|
||||||
self.macros = macros
|
self.macros = macros
|
||||||
|
@@ -86,9 +86,16 @@ def flush(log = None):
|
|||||||
elif default is not None:
|
elif default is not None:
|
||||||
default.flush()
|
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:
|
class log:
|
||||||
"""Log output to stdout or a file."""
|
"""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 = []
|
||||||
self.tail_size = tail_size
|
self.tail_size = tail_size
|
||||||
self.fhs = [None, None]
|
self.fhs = [None, None]
|
||||||
|
@@ -303,6 +303,10 @@ class command_line:
|
|||||||
repo_valid = '1'
|
repo_valid = '1'
|
||||||
repo_head = repo.head()
|
repo_head = repo.head()
|
||||||
repo_clean = not repo.dirty()
|
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
|
repo_id = repo_head
|
||||||
if not repo_clean:
|
if not repo_clean:
|
||||||
repo_id += '-modified'
|
repo_id += '-modified'
|
||||||
@@ -311,11 +315,13 @@ class command_line:
|
|||||||
repo_valid = '0'
|
repo_valid = '0'
|
||||||
repo_head = '%{nil}'
|
repo_head = '%{nil}'
|
||||||
repo_clean = '%{nil}'
|
repo_clean = '%{nil}'
|
||||||
|
repo_remotes = '%{nil}'
|
||||||
repo_id = 'no-repo'
|
repo_id = 'no-repo'
|
||||||
repo_mail = None
|
repo_mail = None
|
||||||
self.defaults['_sbgit_valid'] = repo_valid
|
self.defaults['_sbgit_valid'] = repo_valid
|
||||||
self.defaults['_sbgit_head'] = repo_head
|
self.defaults['_sbgit_head'] = repo_head
|
||||||
self.defaults['_sbgit_clean'] = str(repo_clean)
|
self.defaults['_sbgit_clean'] = str(repo_clean)
|
||||||
|
self.defaults['_sbgit_remotes'] = str(repo_remotes)
|
||||||
self.defaults['_sbgit_id'] = repo_id
|
self.defaults['_sbgit_id'] = repo_id
|
||||||
if repo_mail is not None:
|
if repo_mail is not None:
|
||||||
self.defaults['_sbgit_mail'] = repo_mail
|
self.defaults['_sbgit_mail'] = repo_mail
|
||||||
@@ -462,9 +468,13 @@ class command_line:
|
|||||||
def download_disabled(self):
|
def download_disabled(self):
|
||||||
return self.opts['no-download'] != '0'
|
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):
|
def log_info(self):
|
||||||
log.output(' Command Line: %s' % (' '.join(self.argv)))
|
log.output(self.info())
|
||||||
log.output(' Python: %s' % (sys.version.replace('\n', '')))
|
|
||||||
|
|
||||||
def load(args, optargs = None, defaults = '%{_sbdir}/defaults.mc'):
|
def load(args, optargs = None, defaults = '%{_sbdir}/defaults.mc'):
|
||||||
"""
|
"""
|
||||||
|
@@ -33,6 +33,7 @@ try:
|
|||||||
import build
|
import build
|
||||||
import check
|
import check
|
||||||
import error
|
import error
|
||||||
|
import ereport
|
||||||
import log
|
import log
|
||||||
import mailer
|
import mailer
|
||||||
import options
|
import options
|
||||||
@@ -423,6 +424,10 @@ def list_bset_cfg_files(opts, configs):
|
|||||||
|
|
||||||
def run():
|
def run():
|
||||||
import sys
|
import sys
|
||||||
|
ec = 0
|
||||||
|
opts = None
|
||||||
|
b = None
|
||||||
|
erheader = None
|
||||||
try:
|
try:
|
||||||
optargs = { '--list-configs': 'List available configurations',
|
optargs = { '--list-configs': 'List available configurations',
|
||||||
'--list-bsets': 'List available build sets',
|
'--list-bsets': 'List available build sets',
|
||||||
@@ -450,25 +455,34 @@ def run():
|
|||||||
for bset in opts.params():
|
for bset in opts.params():
|
||||||
b = buildset(bset, configs, opts)
|
b = buildset(bset, configs, opts)
|
||||||
b.build(deps)
|
b.build(deps)
|
||||||
del b
|
b = None
|
||||||
if deps is not None:
|
if deps is not None:
|
||||||
c = 0
|
c = 0
|
||||||
for d in sorted(set(deps)):
|
for d in sorted(set(deps)):
|
||||||
c += 1
|
c += 1
|
||||||
print 'dep[%d]: %s' % (c, d)
|
print 'dep[%d]: %s' % (c, d)
|
||||||
except error.general, gerr:
|
except error.general, gerr:
|
||||||
|
erheader = 'Build: %s' % (gerr)
|
||||||
log.notice(str(gerr))
|
log.notice(str(gerr))
|
||||||
print >> sys.stderr, 'Build FAILED'
|
log.stderr('Build FAILED')
|
||||||
sys.exit(1)
|
ec = 1
|
||||||
except error.internal, ierr:
|
except error.internal, ierr:
|
||||||
|
erheader = 'Build: %s' % (ierr)
|
||||||
log.notice(str(ierr))
|
log.notice(str(ierr))
|
||||||
sys.exit(1)
|
log.stderr('Internal Build FAILED')
|
||||||
|
ec = 1
|
||||||
except error.exit, eerr:
|
except error.exit, eerr:
|
||||||
pass
|
pass
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
log.notice('abort: user terminated')
|
log.notice('abort: user terminated')
|
||||||
sys.exit(1)
|
ec = 1
|
||||||
sys.exit(0)
|
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__":
|
if __name__ == "__main__":
|
||||||
run()
|
run()
|
||||||
|
Reference in New Issue
Block a user