[PATCH 1/3] sb/get-sources: Fix getting sources with archs
chrisj at rtems.org
chrisj at rtems.org
Tue Aug 16 23:34:21 UTC 2022
From: Chris Johns <chrisj at rtems.org>
- Add a stop on error option
- Add listing root or toplevel buildset files
- Add used and unused file output to track what is not used
for clean ups
- Update to handle macro expanded includes in buildset files
---
source-builder/sb/getsources.py | 30 +++++++-
source-builder/sb/simhost.py | 128 ++++++++++++++++++++++++--------
2 files changed, 123 insertions(+), 35 deletions(-)
diff --git a/source-builder/sb/getsources.py b/source-builder/sb/getsources.py
index d348da4..eb5c855 100644
--- a/source-builder/sb/getsources.py
+++ b/source-builder/sb/getsources.py
@@ -60,7 +60,9 @@ def run(args = sys.argv):
default = version.version())
argsp.add_argument('--list-hosts', help = 'List the hosts.',
action = 'store_true')
- argsp.add_argument('--list-bsets', help = 'List the hosts.',
+ argsp.add_argument('--list-bsets', help = 'List the buildsets.',
+ action = 'store_true')
+ argsp.add_argument('--list-root-bsets', help = 'List the toplevel or root buildsets.',
action = 'store_true')
argsp.add_argument('--download-dir', help = 'Download directory.',
type = str)
@@ -71,8 +73,14 @@ def run(args = sys.argv):
argsp.add_argument('--log', help = 'Log file.',
type = str,
default = simhost.log_default('getsource'))
+ argsp.add_argument('--stop-on-error', help = 'Stop on error.',
+ action = 'store_true')
argsp.add_argument('--trace', help = 'Enable trace logging for debugging.',
action = 'store_true')
+ argsp.add_argument('--used', help = 'Save the used buildset and config files.',
+ type = str, default = None)
+ argsp.add_argument('--unused', help = 'Save the unused buildset and config files.',
+ type = str, default = None)
argsp.add_argument('bsets', nargs='*', help = 'Build sets.')
argopts = argsp.parse_args(args[1:])
@@ -84,10 +92,14 @@ def run(args = sys.argv):
opts = simhost.load_options(args, argopts, extras = ['--with-download'])
configs = build.get_configs(opts)
+ stop_on_error = argopts.stop_on_error
+
if argopts.list_hosts:
simhost.list_hosts()
elif argopts.list_bsets:
simhost.list_bset_files(opts, configs)
+ elif argopts.list_root_bsets:
+ simhost.list_root_bset_files(opts, configs)
else:
if argopts.clean:
if argopts.download_dir is None:
@@ -95,11 +107,11 @@ def run(args = sys.argv):
if path.exists(argopts.download_dir):
log.notice('Cleaning source directory: %s' % (argopts.download_dir))
path.removeall(argopts.download_dir)
- all_bsets = simhost.get_bset_files(configs)
if len(argopts.bsets) == 0:
- bsets = all_bsets
+ bsets = simhost.get_root_bset_files(opts, configs)
else:
bsets = argopts.bsets
+ deps = copy.copy(simhost.strip_common_prefix(bsets))
for bset in bsets:
b = None
try:
@@ -108,11 +120,23 @@ def run(args = sys.argv):
b = simhost.buildset(bset, configs, opts)
get_sources_error = False
b.build(host)
+ deps += b.deps()
del b
except error.general as gerr:
+ if stop_on_error:
+ raise
log.stderr(str(gerr))
log.stderr('Build FAILED')
b = None
+ deps = sorted(list(set(deps)))
+ if argopts.used:
+ with open(argopts.used, 'w') as o:
+ o.write(os.linesep.join(deps))
+ if argopts.unused:
+ cfgs_bsets = \
+ [cb for cb in simhost.get_config_bset_files(opts, configs) if not cb in deps]
+ with open(argopts.unused, 'w') as o:
+ o.write(os.linesep.join(cfgs_bsets))
except error.general as gerr:
if get_sources_error:
log.stderr(str(gerr))
diff --git a/source-builder/sb/simhost.py b/source-builder/sb/simhost.py
index 1ff98e8..f58a66d 100644
--- a/source-builder/sb/simhost.py
+++ b/source-builder/sb/simhost.py
@@ -36,6 +36,7 @@ try:
from . import log
from . import macros
from . import path
+ from . import shell
from . import sources
from . import version
except KeyboardInterrupt:
@@ -122,7 +123,6 @@ profiles = {
'_var': ('dir', 'optional', '/usr/local/var') },
}
-
class log_capture(object):
def __init__(self):
self.log = []
@@ -154,6 +154,18 @@ def find_bset_config(bset_config, macros):
raise error.general('no build set file found: %s' % (bset_config))
return name
+def macro_expand(macros, _str):
+ cstr = None
+ while cstr != _str:
+ cstr = _str
+ _str = macros.expand(_str)
+ _str = shell.expand(macros, _str)
+ return _str
+
+def strip_common_prefix(files):
+ commonprefix = os.path.commonprefix(files)
+ return sorted(list(set([f[len(commonprefix):] for f in files])))
+
#
# A skinny options command line class to get the configs to load.
#
@@ -252,10 +264,10 @@ class options(object):
a += 1
return None
- def rtems_bsp(self):
+ def rtems_bsp(self, arch='arch'):
self.defaults['rtems_version'] = str(version.version())
- self.defaults['_target'] = 'arch-rtems'
- self.defaults['rtems_host'] = 'rtems-arch'
+ self.defaults['_target'] = arch + '-rtems'
+ self.defaults['rtems_host'] = 'rtems-' + arch
self.defaults['with_rtems_bsp'] = 'rtems-bsp'
def sb_git(self):
@@ -383,8 +395,19 @@ class buildset:
rebased += [i]
return rebased
+ def root(self):
+ for i in self._includes:
+ si = i.split(':')
+ if len(si) == 2:
+ if si[1] == 'root':
+ return si[0]
+ return None
+
def includes(self):
- return sorted(list(set(self._includes)))
+ return [i for i in self._includes if not i.endswith(':root')]
+
+ def deps(self):
+ return strip_common_prefix([i.split(':')[0] for i in self.includes()])
def errors(self):
return sorted(list(set(self._errors)))
@@ -393,7 +416,7 @@ class buildset:
if not _build.disabled():
_build.make()
- def parse(self, bset):
+ def parse(self, bset, expand=True):
#
# Ouch, this is a copy of the setbuilder.py code.
@@ -409,7 +432,7 @@ class buildset:
bsetname = find_bset_config(bset, self.macros)
try:
- log.trace('_bset: %s: open: %s' % (self.bset, bsetname))
+ log.trace('_bset: %s: open: %s %s' % (self.bset, bsetname, expand))
bsetf = open(path.host(bsetname), 'r')
except IOError as err:
raise error.general('error opening bset file: %s' % (bsetname))
@@ -432,19 +455,26 @@ class buildset:
if ls[0][-1] == ':' and ls[0][:-1] == 'package':
self.bset_pkg = ls[1].strip()
self.macros['package'] = self.bset_pkg
- elif ls[0][0] == '%':
+ elif ls[0][0] == '%' and (len(ls[0]) > 1 and ls[0][1] != '{'):
def err(msg):
raise error.general('%s:%d: %s' % (self.bset, lc, msg))
- if ls[0] == '%define':
+ if ls[0] == '%define' or ls[0] == '%defineifnot' :
+ name = ls[1].strip()
+ value = None
if len(ls) > 2:
- self.macros.define(ls[1].strip(),
- ' '.join([f.strip() for f in ls[2:]]))
- else:
- self.macros.define(ls[1].strip())
+ value = ' '.join([f.strip() for f in ls[2:]])
+ if ls[0] == '%defineifnot':
+ if self.macros.defined(name):
+ name = None
+ if name is not None:
+ if value is not None:
+ self.macros.define(name, value)
+ else:
+ self.macros.define(name)
elif ls[0] == '%undefine':
if len(ls) > 2:
- raise error.general('%s:%d: %undefine requires just the name' \
- % (self.bset, lc))
+ raise error.general('%s:%d: %undefine requires ' \
+ 'just the name' % (self.bset, lc))
self.macros.undefine(ls[1].strip())
elif ls[0] == '%include':
configs += self.parse(ls[1].strip())
@@ -453,12 +483,18 @@ class buildset:
elif ls[0] == '%hash':
sources.hash(ls[1:], self.macros, err)
else:
- l = l.strip()
- c = build.find_config(l, self.configs)
- if c is None:
- raise error.general('%s:%d: cannot find file: %s'
- % (self.bset, lc, l))
- configs += [c + ':' + self.parent]
+ try:
+ l = macro_expand(self.macros, l.strip())
+ except:
+ if expand:
+ raise
+ l = None
+ if l is not None:
+ c = build.find_config(l, self.configs)
+ if c is None:
+ raise error.general('%s:%d: cannot find file: %s'
+ % (self.bset, lc, l))
+ configs += [c + ':' + self.parent]
finally:
bsetf.close()
self.parent = parent
@@ -523,7 +559,7 @@ class buildset:
nesting_count += 1
- log.trace('_bset: %s for %s: make' % (self.bset, host))
+ log.trace('_bset: %2d: %s for %s: make' % (nesting_count, self.bset, host))
log.notice('Build Set: %s for %s' % (self.bset, host))
mail_subject = '%s on %s' % (self.bset,
@@ -538,7 +574,7 @@ class buildset:
try:
configs = self.load()
- log.trace('_bset: %s: configs: %s' % (self.bset, ','.join(configs)))
+ log.trace('_bset: %2d: %s: configs: %s' % (nesting_count, self.bset, ','.join(configs)))
sizes_valid = False
builds = []
@@ -556,14 +592,14 @@ class buildset:
self.set_host_details(host, opts, macros)
config, parent = configs[s].split(':', 2)
if config.endswith('.bset'):
- log.trace('_bset: == %2d %s' % (nesting_count + 1, '=' * 75))
+ log.trace('_bset: %2d: %s' % (nesting_count + 1, '=' * 75))
bs = buildset(config, self.configs, opts, macros)
bs.build(host, nesting_count)
self._includes += \
self._rebase_includes(bs.includes(), parent)
del bs
elif config.endswith('.cfg'):
- log.trace('_bset: -- %2d %s' % (nesting_count + 1, '-' * 75))
+ log.trace('_bset: %2d: %s' % (nesting_count + 1, '-' * 75))
try:
b = build.build(config,
False,
@@ -579,7 +615,7 @@ class buildset:
#
# Dump post build macros.
#
- log.trace('_bset: macros post-build')
+ log.trace('_bset: %2d: macros post-build' % (nesting_count))
log.trace(str(macros))
else:
raise error.general('invalid config type: %s' % (config))
@@ -589,13 +625,16 @@ class buildset:
if self.build_failure is None:
self.build_failure = b.name()
self._includes += b.includes()
- self._errors += [find_bset_config(config, opts.defaults) + ':' + parent] + self._includes
+ self._errors += \
+ [find_bset_config(config, opts.defaults) + ':' + parent] + self._includes
raise
#
# Clear out the builds ...
#
for b in builds:
del b
+ self._includes += \
+ [find_bset_config(c.split(':')[0], self.macros) + ':' + self.bset for c in configs]
except error.general as gerr:
if not build_error:
log.stderr(str(gerr))
@@ -616,9 +655,9 @@ def list_hosts():
max_os_len = max(len(h) for h in hosts)
max_host_len = max(len(profiles[h]['_host'][2]) for h in hosts)
for h in hosts:
- print('%*s: %-*s %s' % (max_os_len, h, max_host_len,
- profiles[h]['_host'][2],
- profiles[h]['_host'][2]))
+ log.notice('%*s: %-*s %s' % (max_os_len, h, max_host_len,
+ profiles[h]['_host'][2],
+ profiles[h]['_host'][2]))
def get_files(configs, ext, localpath):
files = []
@@ -635,14 +674,39 @@ def get_config_files(configs, localpath = False):
def get_bset_files(configs, localpath = False):
return get_files(configs, '.bset', localpath)
+def get_config_bset_files(opts, configs):
+ cbs = get_config_files(configs) + get_bset_files(configs)
+ return strip_common_prefix([find_bset_config(cb, opts.defaults) for cb in cbs])
+
+def get_root_bset_files(opts, configs, localpath = False):
+ bsets = get_bset_files(configs, localpath)
+ incs = {}
+ for bs in bsets:
+ bset = buildset(bs, configs, opts)
+ cfgs = [find_bset_config(c.split(':')[0], bset.macros) for c in bset.parse(bs, False)]
+ incs[bset.root()] = bset.includes() + cfgs
+ roots = sorted(incs.keys())
+ for inc in incs:
+ for i in incs[inc]:
+ si = i.split(':')
+ if len(si) > 0 and si[0] in roots:
+ roots.remove(si[0])
+ return roots
+
def get_root(configs):
return configs['root']
+def list_root_bset_files(opts, configs):
+ for p in configs['paths']:
+ log.notice('Examining: %s' % (os.path.relpath(p)))
+ for r in strip_common_prefix(get_root_bset_files(opts, configs)):
+ log.notice(' %s' % (r))
+
def list_bset_files(opts, configs):
for p in configs['paths']:
- print('Examining: %s' % (os.path.relpath(p)))
+ log.notice('Examining: %s' % (os.path.relpath(p)))
for b in get_bset_files(configs):
- print(' %s' % (b[:b.rfind('.')]))
+ log.notice(' %s' % (b[:b.rfind('.')]))
def load_log(logfile):
log.default = log.log(streams = [logfile])
--
2.24.1
More information about the devel
mailing list