mirror of
https://git.rtems.org/rtems-source-builder
synced 2024-10-09 07:15:10 +08:00
sb/track: Add a command to track build sets.
- Process a build set for a range of hosts and output a dependency tree, the used build set and configuration files. - Output the configuration files that are no referenced Closes #4036
This commit is contained in:
254
source-builder/sb/track.py
Normal file
254
source-builder/sb/track.py
Normal file
@@ -0,0 +1,254 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2020 Chris Johns (chrisj@rtems.org)
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of the RTEMS Tools package in 'rtems-tools'.
|
||||
#
|
||||
# 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.
|
||||
|
||||
#
|
||||
# This code builds a package compiler tool suite given a tool set. A tool
|
||||
# set lists the various tools. These are specific tool configurations.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import copy
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
import build
|
||||
import error
|
||||
import git
|
||||
import log
|
||||
import simhost
|
||||
import version
|
||||
except KeyboardInterrupt:
|
||||
print('abort: user terminated', file = sys.stderr)
|
||||
sys.exit(1)
|
||||
except:
|
||||
print('error: unknown application load error', file = sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def unique(l):
|
||||
return sorted(list(set(l)))
|
||||
|
||||
def filter_deps(deps, ext):
|
||||
rdeps = []
|
||||
for d in deps:
|
||||
ds = d.split(':', 2)
|
||||
if ds[0].endswith(ext):
|
||||
rdeps += [ds[0] + ':' + ds[1]]
|
||||
return sorted(rdeps)
|
||||
|
||||
def normalise_paths(includes, root):
|
||||
normalised = []
|
||||
for inc in unique(includes):
|
||||
config, parent = inc.split(':', 2)
|
||||
if config.startswith(root):
|
||||
config = config[len(root):]
|
||||
if parent.startswith(root):
|
||||
parent = parent[len(root):]
|
||||
normalised += [config + ':' + parent]
|
||||
return normalised
|
||||
|
||||
def process_dependencies(includes):
|
||||
deps = {}
|
||||
incs = [i.split(':', 2) for i in includes]
|
||||
for config, parent in incs:
|
||||
if parent not in deps:
|
||||
deps[parent] = []
|
||||
for inc in incs:
|
||||
if inc[1] == parent:
|
||||
deps[parent] += [inc[0]]
|
||||
for d in deps:
|
||||
deps[d] = unique(deps[d])
|
||||
return deps
|
||||
|
||||
def includes_str(includes):
|
||||
o = []
|
||||
deps = [i.split(':', 2) for i in includes]
|
||||
ll = max([len(d[1]) for d in deps])
|
||||
for d in deps:
|
||||
o += ['%*s %s' % (ll, d[1], d[0])]
|
||||
return o
|
||||
|
||||
def deps_str(deps):
|
||||
def print_node(deps, node, level = 0, prefix = '', indent = ''):
|
||||
o = []
|
||||
if node != 'root':
|
||||
level += 1
|
||||
if level == 1:
|
||||
o += ['']
|
||||
o += [prefix + '+-- ' + node]
|
||||
if node in deps:
|
||||
prefix += indent
|
||||
for c, child in enumerate(deps[node], start = 1):
|
||||
if c < len(deps[node]) and level > 1:
|
||||
indent = '| '
|
||||
else:
|
||||
indent = ' '
|
||||
o += print_node(deps, child, level, prefix, indent)
|
||||
return o
|
||||
return print_node(deps, 'root')
|
||||
|
||||
def run(args = sys.argv):
|
||||
ec = 0
|
||||
output = []
|
||||
try:
|
||||
#
|
||||
# The RSB options support cannot be used because it loads the defaults
|
||||
# for the host which we cannot do here.
|
||||
#
|
||||
description = 'RTEMS Track Dependencies a build set has for all hosts.'
|
||||
|
||||
argsp = argparse.ArgumentParser(prog = 'sb-dep-check',
|
||||
description = description)
|
||||
argsp.add_argument('--rtems-version', help = 'Set the RTEMS version.',
|
||||
type = str,
|
||||
default = version.version())
|
||||
argsp.add_argument('--list-hosts', help = 'List the hosts.',
|
||||
action = 'store_true')
|
||||
argsp.add_argument('--list-bsets', help = 'List the hosts.',
|
||||
action = 'store_true')
|
||||
argsp.add_argument('--output', help = 'Output file.',
|
||||
type = str,
|
||||
default = None)
|
||||
argsp.add_argument('--log', help = 'Log file.',
|
||||
type = str,
|
||||
default = simhost.log_default('trackdeps'))
|
||||
argsp.add_argument('--trace', help = 'Enable trace logging for debugging.',
|
||||
action = 'store_true')
|
||||
argsp.add_argument('--not-referenced',
|
||||
help = 'Write out the list of not config files not referenced.',
|
||||
action = 'store_true')
|
||||
argsp.add_argument('bsets', nargs='*', help = 'Build sets.')
|
||||
|
||||
argopts = argsp.parse_args(args[2:])
|
||||
|
||||
simhost.load_log(argopts.log)
|
||||
log.notice('RTEMS Source Builder - Track Dependencies, %s' % (version.string()))
|
||||
log.tracing = argopts.trace
|
||||
|
||||
opts = simhost.load_options(args, argopts, extras = ['---keep-going'])
|
||||
configs = build.get_configs(opts)
|
||||
|
||||
if argopts.list_hosts:
|
||||
simhost.list_hosts()
|
||||
elif argopts.list_bsets:
|
||||
simhost.list_bset_files(opts, configs)
|
||||
else:
|
||||
all_bsets = simhost.get_bset_files(configs)
|
||||
if len(argopts.bsets) == 0:
|
||||
bsets = all_bsets
|
||||
else:
|
||||
bsets = argopts.bsets
|
||||
includes = []
|
||||
errors = []
|
||||
for bset in bsets:
|
||||
b = None
|
||||
try:
|
||||
for host in simhost.profiles:
|
||||
b = simhost.buildset(bset, configs, opts)
|
||||
b.build(host)
|
||||
includes += b.includes()
|
||||
errors += b.errors()
|
||||
del b
|
||||
except error.general as gerr:
|
||||
log.stderr(str(gerr))
|
||||
log.stderr('Build FAILED')
|
||||
if b:
|
||||
includes += b.includes()
|
||||
errors += b.errors()
|
||||
b = None
|
||||
root = simhost.get_root(configs)
|
||||
all_configs = simhost.get_config_files(configs, True)
|
||||
includes = normalise_paths(includes, root)
|
||||
bsets = filter_deps(includes, '.bset')
|
||||
configs = filter_deps(includes, '.cfg')
|
||||
deps_tree = deps_str(process_dependencies(bsets + configs))
|
||||
bsets = unique([b.split(':', 2)[0] for b in bsets])
|
||||
configs = unique([i.split(':', 2)[0] for i in configs])
|
||||
not_used_configs = [c for c in all_configs if c not in configs]
|
||||
if len(errors) > 0:
|
||||
errors = [e.split(':', 2)[0] for e in normalise_paths(errors, root)]
|
||||
errs = []
|
||||
for e in errors:
|
||||
if e not in bsets + configs:
|
||||
errs += [e]
|
||||
errors = errs
|
||||
if argopts.not_referenced:
|
||||
output = not_used_configs
|
||||
else:
|
||||
output = ['RSB Dependency Tracker',
|
||||
'',
|
||||
'Total buildsets: %d' % (len(all_bsets)),
|
||||
'Total configs: %d' % (len(all_configs)),
|
||||
'']
|
||||
if len(errors) > 0:
|
||||
output += ['Errored File Set (%d):' % (len(errors)),
|
||||
''] + \
|
||||
errors + \
|
||||
['']
|
||||
if len(configs) > 0:
|
||||
output += ['Include Tree(s):',
|
||||
''] + \
|
||||
deps_tree + \
|
||||
['']
|
||||
if len(bsets) > 0:
|
||||
output += ['Buildsets (%d):' % (len(bsets)),
|
||||
''] + \
|
||||
bsets + \
|
||||
['']
|
||||
if len(configs) > 0:
|
||||
output += ['Configurations (%d):' % (len(configs)),
|
||||
''] + \
|
||||
configs + \
|
||||
['']
|
||||
if len(not_used_configs) > 0:
|
||||
output += ['Not referenced (%d): ' % (len(not_used_configs)),
|
||||
''] + \
|
||||
not_used_configs
|
||||
output = os.linesep.join(output)
|
||||
if argopts.output:
|
||||
o = open(argopts.output, "w")
|
||||
o.write(output)
|
||||
o.close
|
||||
else:
|
||||
print()
|
||||
print(output)
|
||||
except error.general as gerr:
|
||||
log.stderr(str(gerr))
|
||||
log.stderr('Build FAILED')
|
||||
ec = 1
|
||||
except error.internal as ierr:
|
||||
log.stderr(str(ierr))
|
||||
log.stderr('Internal Build FAILED')
|
||||
ec = 1
|
||||
except error.exit as eerr:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
log.notice('abort: user terminated')
|
||||
ec = 1
|
||||
except:
|
||||
raise
|
||||
log.notice('abort: unknown error')
|
||||
ec = 1
|
||||
sys.exit(ec)
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
Reference in New Issue
Block a user