summaryrefslogtreecommitdiff
path: root/rtemstoolkit
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2018-10-02 16:49:54 +1000
committerChris Johns <chrisj@rtems.org>2018-10-02 16:49:54 +1000
commit5416cfa39dd6b386958571f925b72a15fd63372b (patch)
tree917569756370be9f1654b3b34ecc974cd4b1fb3f /rtemstoolkit
parent5075e8ed025baf2a0020b5f8832ffaf6ac336d7a (diff)
config: Create a config directory and move the RTEMS arch/bsp data to it.
Closes #3536
Diffstat (limited to 'rtemstoolkit')
-rw-r--r--rtemstoolkit/__init__.py12
-rwxr-xr-xrtemstoolkit/rtems.py372
-rw-r--r--rtemstoolkit/wscript1
3 files changed, 384 insertions, 1 deletions
diff --git a/rtemstoolkit/__init__.py b/rtemstoolkit/__init__.py
index ca2d619..6878782 100644
--- a/rtemstoolkit/__init__.py
+++ b/rtemstoolkit/__init__.py
@@ -1,6 +1,6 @@
#
# RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2016 Chris Johns (chrisj@rtems.org)
+# Copyright 2010-2018 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -30,26 +30,36 @@
all = ['check',
'config',
+ 'configuration',
'error',
'execute',
'git',
+ 'host',
'log',
'macros',
'mailer',
'options',
'path',
'reraise',
+ 'rtems',
+ 'stacktraces',
+ 'textbox',
'version']
from . import check
from . import config
+from . import configuration
from . import error
from . import execute
from . import git
+from . import host
from . import log
from . import macros
from . import mailer
from . import options
from . import path
from . import reraise
+from . import rtems
+from . import stacktraces
+from . import textbox
from . import version
diff --git a/rtemstoolkit/rtems.py b/rtemstoolkit/rtems.py
new file mode 100755
index 0000000..13b1e7a
--- /dev/null
+++ b/rtemstoolkit/rtems.py
@@ -0,0 +1,372 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 20162018 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+from __future__ import print_function
+
+import copy
+import os
+import re
+import textwrap
+
+from rtemstoolkit import configuration as configuration_
+from rtemstoolkit import error
+from rtemstoolkit import textbox
+from rtemstoolkit import version
+
+
+def clean_windows_path():
+ #
+ # On Windows MSYS2 prepends a path to itself to the environment
+ # path. This means the RTEMS specific automake is not found and which
+ # breaks the bootstrap. We need to remove the prepended path. Also
+ # remove any ACLOCAL paths from the environment.
+ #
+ if os.name == 'nt':
+ cspath = os.environ['PATH'].split(os.pathsep)
+ if 'msys' in cspath[0] and cspath[0].endswith('bin'):
+ os.environ['PATH'] = os.pathsep.join(cspath[1:])
+
+class configuration:
+
+ def __init__(self):
+ self.config = configuration_.configuration()
+ self.archs = { }
+ self.profiles = { }
+
+ def __str__(self):
+ s = self.name + os.linesep
+ s += 'Archs:' + os.linesep + \
+ pprint.pformat(self.archs, indent = 1, width = 80) + os.linesep
+ s += 'Profiles:' + os.linesep + \
+ pprint.pformat(self.profiles, indent = 1, width = 80) + os.linesep
+ return s
+
+ def _build_options(self, build, nesting = 0):
+ if ':' in build:
+ section, name = build.split(':', 1)
+ opts = [self.config.get_item(section, name)]
+ return opts
+ builds = self.builds_['builds']
+ if build not in builds:
+ raise error.general('build %s not found' % (build))
+ if nesting > 20:
+ raise error.general('nesting build %s' % (build))
+ options = []
+ for option in self.builds_['builds'][build]:
+ if ':' in option:
+ section, name = option.split(':', 1)
+ opts = [self.config.get_item(section, name)]
+ else:
+ opts = self._build_options(option, nesting + 1)
+ for opt in opts:
+ if opt not in options:
+ options += [opt]
+ return options
+
+ def load(self, name, build):
+ self.config.load(name)
+ archs = []
+ self.profiles['profiles'] = \
+ self.config.comma_list('profiles', 'profiles', err = False)
+ if len(self.profiles['profiles']) == 0:
+ self.profiles['profiles'] = ['tier-%d' % (t) for t in range(1,4)]
+ for p in self.profiles['profiles']:
+ profile = {}
+ profile['name'] = p
+ profile['archs'] = self.config.comma_list(profile['name'], 'archs', err = False)
+ archs += profile['archs']
+ for arch in profile['archs']:
+ bsps = 'bsps_%s' % (arch)
+ profile[bsps] = self.config.comma_list(profile['name'], bsps)
+ self.profiles[profile['name']] = profile
+ invalid_chars = re.compile(r'[^a-zA-Z0-9_-]')
+ for a in set(archs):
+ if len(invalid_chars.findall(a)) != 0:
+ raise error.general('invalid character(s) in arch name: %s' % (a))
+ arch = {}
+ arch['excludes'] = {}
+ for exclude in self.config.comma_list(a, 'exclude', err = False):
+ arch['excludes'][exclude] = ['all']
+ for i in self.config.get_items(a, False):
+ if i[0].startswith('exclude-'):
+ exclude = i[0][len('exclude-'):]
+ if exclude not in arch['excludes']:
+ arch['excludes'][exclude] = []
+ arch['excludes'][exclude] += \
+ sorted(set([b.strip() for b in i[1].split(',')]))
+ arch['bsps'] = self.config.comma_list(a, 'bsps', err = False)
+ for b in arch['bsps']:
+ if len(invalid_chars.findall(b)) != 0:
+ raise error.general('invalid character(s) in BSP name: %s' % (b))
+ arch[b] = {}
+ arch[b]['bspopts'] = \
+ self.config.comma_list(a, 'bspopts_%s' % (b), err = False)
+ self.archs[a] = arch
+ builds = {}
+ builds['default'] = self.config.get_item('builds', 'default')
+ if build is None:
+ build = builds['default']
+ builds['config'] = { }
+ for config in self.config.get_items('config'):
+ builds['config'][config[0]] = config[1]
+ builds['build'] = build
+ builds_ = self.config.get_item_names('builds')
+ builds['builds'] = {}
+ for build in builds_:
+ build_builds = self.config.comma_list('builds', build)
+ has_config = False
+ has_build = False
+ for b in build_builds:
+ if ':' in b:
+ if has_build:
+ raise error.general('config and build in build: %s' % (build))
+ has_config = True
+ else:
+ if has_config:
+ raise error.general('config and build in build: %s' % (build))
+ has_build = True
+ builds['builds'][build] = build_builds
+ self.builds_ = builds
+
+ def configs(self):
+ return sorted(list(self.builds_['config'].keys()))
+
+ def config_flags(self, config):
+ if config not in self.builds_['config']:
+ raise error.general('config entry not found: %s' % (config))
+ return self.builds_['config'][config]
+
+ def build(self):
+ return self.builds_['build']
+
+ def builds(self):
+ if self.builds_['build'] in self.builds_['builds']:
+ build = copy.copy(self.builds_['builds'][self.builds_['build']])
+ if ':' in build[0]:
+ return [self.builds_['build']]
+ return build
+ return None
+
+ def build_options(self, build):
+ return ' '.join(self._build_options(build))
+
+ def excludes(self, arch, bsp):
+ return list(set(self.arch_excludes(arch) + self.bsp_excludes(arch, bsp)))
+
+ def exclude_options(self, arch, bsp):
+ return ' '.join([self.config_flags('no-' + e) for e in self.excludes(arch, bsp)])
+
+ def archs(self):
+ return sorted(self.archs.keys())
+
+ def arch_present(self, arch):
+ return arch in self.archs
+
+ def arch_excludes(self, arch):
+ excludes = self.archs[arch]['excludes'].keys()
+ for exclude in self.archs[arch]['excludes']:
+ if 'all' not in self.archs[arch]['excludes'][exclude]:
+ excludes.remove(exclude)
+ return sorted(excludes)
+
+ def arch_bsps(self, arch):
+ return sorted(self.archs[arch]['bsps'])
+
+ def bsp_present(self, arch, bsp):
+ return bsp in self.archs[arch]['bsps']
+
+ def bsp_excludes(self, arch, bsp):
+ excludes = self.archs[arch]['excludes'].keys()
+ for exclude in self.archs[arch]['excludes']:
+ if 'all' not in self.archs[arch]['excludes'][exclude] and \
+ bsp not in self.archs[arch]['excludes'][exclude]:
+ excludes.remove(exclude)
+ return sorted(excludes)
+
+ def bspopts(self, arch, bsp):
+ if arch not in self.archs:
+ raise error.general('invalid architecture: %s' % (arch))
+ if bsp not in self.archs[arch]:
+ raise error.general('invalid BSP: %s' % (bsp))
+ return self.archs[arch][bsp]['bspopts']
+
+ def profile_present(self, profile):
+ return profile in self.profiles
+
+ def profile_archs(self, profile):
+ if profile not in self.profiles:
+ raise error.general('invalid profile: %s' % (profile))
+ return self.profiles[profile]['archs']
+
+ def profile_arch_bsps(self, profile, arch):
+ if profile not in self.profiles:
+ raise error.general('invalid profile: %s' % (profile))
+ if 'bsps_%s' % (arch) not in self.profiles[profile]:
+ raise error.general('invalid profile arch: %s' % (arch))
+ return ['%s/%s' % (arch, bsp) for bsp in self.profiles[profile]['bsps_%s' % (arch)]]
+
+ def report(self, profiles = True, builds = True, architectures = True):
+ width = 70
+ cols_1 = [width]
+ cols_2 = [10, width - 10]
+ s = textbox.line(cols_1, line = '=', marker = '+', indent = 1)
+ s1 = ' File(s)'
+ for f in self.config.files():
+ colon = ':'
+ for l in textwrap.wrap(f, width = cols_2[1] - 3):
+ s += textbox.row(cols_2, [s1, ' ' + l], marker = colon, indent = 1)
+ colon = ' '
+ s1 = ' ' * len(s1)
+ s += textbox.line(cols_1, marker = '+', indent = 1)
+ s += os.linesep
+ if profiles:
+ s += textbox.line(cols_1, line = '=', marker = '+', indent = 1)
+ profiles = sorted(self.profiles['profiles'])
+ archs = []
+ bsps = []
+ for profile in profiles:
+ archs += self.profiles[profile]['archs']
+ for arch in sorted(self.profiles[profile]['archs']):
+ bsps += self.profiles[profile]['bsps_%s' % (arch)]
+ archs = len(set(archs))
+ bsps = len(set(bsps))
+ s += textbox.row(cols_1,
+ [' Profiles : %d (archs:%d, bsps:%d)' % \
+ (len(profiles), archs, bsps)],
+ indent = 1)
+ for profile in profiles:
+ textbox.row(cols_2,
+ [profile, self.profiles[profile]['name']],
+ indent = 1)
+ s += textbox.line(cols_1, marker = '+', indent = 1)
+ for profile in profiles:
+ s += textbox.row(cols_1, [' %s' % (profile)], indent = 1)
+ profile = self.profiles[profile]
+ archs = sorted(profile['archs'])
+ for arch in archs:
+ arch_bsps = ', '.join(profile['bsps_%s' % (arch)])
+ if len(arch_bsps) > 0:
+ s += textbox.line(cols_2, marker = '+', indent = 1)
+ s1 = ' ' + arch
+ for l in textwrap.wrap(arch_bsps,
+ width = cols_2[1] - 3):
+ s += textbox.row(cols_2, [s1, ' ' + l], indent = 1)
+ s1 = ' ' * len(s1)
+ s += textbox.line(cols_2, marker = '+', indent = 1)
+ s += os.linesep
+ if builds:
+ s += textbox.line(cols_1, line = '=', marker = '+', indent = 1)
+ s += textbox.row(cols_1,
+ [' Builds: %s (default)' % (self.builds_['default'])],
+ indent = 1)
+ builds = self.builds_['builds']
+ bsize = 0
+ for build in builds:
+ if len(build) > bsize:
+ bsize = len(build)
+ cols_b = [bsize + 2, width - bsize - 2]
+ s += textbox.line(cols_b, marker = '+', indent = 1)
+ for build in builds:
+ s1 = ' ' + build
+ for l in textwrap.wrap(', '.join(builds[build]),
+ width = cols_b[1] - 3):
+ s += textbox.row(cols_b, [s1, ' ' + l], indent = 1)
+ s1 = ' ' * len(s1)
+ s += textbox.line(cols_b, marker = '+', indent = 1)
+ configs = self.builds_['config']
+ s += textbox.row(cols_1,
+ [' Configure Options: %d' % (len(configs))],
+ indent = 1)
+ csize = 0
+ for config in configs:
+ if len(config) > csize:
+ csize = len(config)
+ cols_c = [csize + 3, width - csize - 3]
+ s += textbox.line(cols_c, marker = '+', indent = 1)
+ for config in configs:
+ s1 = ' ' + config
+ for l in textwrap.wrap(configs[config], width = cols_c[1] - 3):
+ s += textbox.row(cols_c, [s1, ' ' + l], indent = 1)
+ s1 = ' ' * len(s1)
+ s += textbox.line(cols_c, marker = '+', indent = 1)
+ s += os.linesep
+ if architectures:
+ s += textbox.line(cols_1, line = '=', marker = '+', indent = 1)
+ archs = sorted(self.archs.keys())
+ bsps = 0
+ asize = 0
+ for arch in archs:
+ if len(arch) > asize:
+ asize = len(arch)
+ bsps += len(self.archs[arch]['bsps'])
+ s += textbox.row(cols_1,
+ [' Architectures : %d (bsps: %d)' % (len(archs), bsps)],
+ indent = 1)
+ cols_a = [asize + 2, width - asize - 2]
+ s += textbox.line(cols_a, marker = '+', indent = 1)
+ for arch in archs:
+ s += textbox.row(cols_a,
+ [' ' + arch, ' %d' % (len(self.archs[arch]['bsps']))],
+ indent = 1)
+ s += textbox.line(cols_a, marker = '+', indent = 1)
+ for archn in archs:
+ arch = self.archs[archn]
+ if len(arch['bsps']) > 0:
+ bsize = 0
+ for bsp in arch['bsps']:
+ if len(bsp) > bsize:
+ bsize = len(bsp)
+ cols_b = [bsize + 3, width - bsize - 3]
+ s += textbox.row(cols_1, [' ' + archn + ':'], indent = 1)
+ s += textbox.line(cols_b, marker = '+', indent = 1)
+ for bsp in arch['bsps']:
+ s1 = ' ' + bsp
+ bspopts = ' '.join(arch[bsp]['bspopts'])
+ if len(bspopts):
+ for l in textwrap.wrap('bopt: ' + bspopts,
+ width = cols_b[1] - 3):
+ s += textbox.row(cols_b, [s1, ' ' + l], indent = 1)
+ s1 = ' ' * len(s1)
+ excludes = []
+ for exclude in arch['excludes']:
+ if 'all' in arch['excludes'][exclude] or \
+ bsp in arch['excludes'][exclude]:
+ excludes += [exclude]
+ excludes = ', '.join(excludes)
+ if len(excludes):
+ for l in textwrap.wrap('ex: ' + excludes,
+ width = cols_b[1] - 3):
+ s += textbox.row(cols_b, [s1, ' ' + l], indent = 1)
+ s1 = ' ' * len(s1)
+ if len(bspopts) == 0 and len(excludes) == 0:
+ s += textbox.row(cols_b, [s1, ' '], indent = 1)
+ s += textbox.line(cols_b, marker = '+', indent = 1)
+ s += os.linesep
+ return s
diff --git a/rtemstoolkit/wscript b/rtemstoolkit/wscript
index 4b5fa34..1b124c7 100644
--- a/rtemstoolkit/wscript
+++ b/rtemstoolkit/wscript
@@ -148,6 +148,7 @@ def build(bld):
'options.py',
'path.py',
'reraise.py',
+ 'rtems.py',
'stacktraces.py',
'textbox.py',
'version.py',