Warning, /rtems-bsps is written in an unsupported language. File is not indexed.
0001 #! /usr/bin/env python3
0002 #
0003 # RTEMS (http://www.rtems.org/)
0004 # Copyright 2020, 2022 Chris Johns (chrisj@rtems.org)
0005 # All rights reserved.
0006 #
0007 # Redistribution and use in source and binary forms, with or without
0008 # modification, are permitted provided that the following conditions are met:
0009 #
0010 # 1. Redistributions of source code must retain the above copyright notice,
0011 # this list of conditions and the following disclaimer.
0012 #
0013 # 2. Redistributions in binary form must reproduce the above copyright notice,
0014 # this list of conditions and the following disclaimer in the documentation
0015 # and/or other materials provided with the distribution.
0016 #
0017 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0018 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0019 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0020 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
0021 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0022 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0023 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0024 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0025 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0026 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0027 # POSSIBILITY OF SUCH DAMAGE.
0028 #
0029
0030 from __future__ import print_function
0031
0032 import argparse
0033 import os
0034 import os.path
0035 import re
0036 import sys
0037
0038 rtems_version = 6
0039
0040
0041 _BUILD_TYPE_BSP = re.compile(r"build-type:\s*bsp\n")
0042 _ARCH = re.compile(r"arch:\s*(\S+)\n")
0043 _FAMILY = re.compile(r"family:\s*(\S+)\n")
0044 _BSP = re.compile(r"bsp:\s*(\S+)\n")
0045
0046
0047 class ArchBsps:
0048 """Collects and processes the BSPs for a range of architectures
0049 creating output in text, markdown and HTML ir pandoc is installed"""
0050 def __init__(self, path='.', trace=False):
0051 self.trace = trace
0052 self._output = []
0053 self.top = os.path.realpath(path)
0054 self.base = os.path.join(self.top, 'spec', 'build', 'bsps')
0055 self.configs = []
0056 self.archs = {}
0057 self._collect('.yml')
0058 self._process()
0059
0060 def _clear(self):
0061 """Clears the output."""
0062 self._output = []
0063
0064 def _out(self, line=''):
0065 """Output a line to the output buffer."""
0066 if isinstance(line, list):
0067 self._output += line
0068 else:
0069 self._output += [line]
0070
0071 def _collect(self, ext):
0072 """Collect the config files from the source tree."""
0073 self.configs = []
0074 for root, dirs, files in os.walk(self.base, topdown=True):
0075 for f in files:
0076 if os.path.splitext(f)[1] == ext:
0077 self.configs += [os.path.join(root, f)]
0078
0079 def _process(self):
0080 """Process the collected list of config files."""
0081 self.archs = {}
0082 for cfg in self.configs:
0083 with open(cfg, 'r') as cfg_file:
0084 content = cfg_file.read()
0085 if _BUILD_TYPE_BSP.search(content):
0086 arch = _ARCH.search(content).group(1)
0087 family = _FAMILY.search(content).group(1)
0088 bsp = _BSP.search(content).group(1)
0089 self.archs.setdefault(arch, {})
0090 self.archs[arch].setdefault(family, {})
0091 self.archs[arch][family][bsp] = cfg[len(self.base) + 1:]
0092
0093 def _max_arch_len(self):
0094 """Finds the longest arch label"""
0095 maxlen = 0
0096 for arch in self.archs:
0097 if len(arch) > maxlen:
0098 maxlen = len(arch)
0099 return maxlen
0100
0101 def _max_family_len(self):
0102 """Finds the longest family label"""
0103 maxlen = 0
0104 for arch in self.archs:
0105 for family in self.archs[arch]:
0106 if len(family) > maxlen:
0107 maxlen = len(family)
0108 return maxlen
0109
0110 def _max_bsp_len(self):
0111 """Finds the longest BSP label"""
0112 maxlen = 0
0113 for arch in self.archs:
0114 for family in self.archs[arch]:
0115 for bsp in self.archs[arch][family]:
0116 if len(bsp) > maxlen:
0117 maxlen = len(bsp)
0118 return maxlen
0119
0120 def _max_bsp_path_len(self):
0121 """Finds the longest BSP path"""
0122 maxlen = 0
0123 for arch in self.archs:
0124 for family in self.archs[arch]:
0125 for bsp in self.archs[arch][family]:
0126 if len(self.archs[arch][family][bsp]) > maxlen:
0127 maxlen = len(self.archs[arch][family][bsp])
0128 return maxlen
0129
0130 def title(self):
0131 """Returns the output's title"""
0132 return 'RTEMS %d Board Support Packages' % (rtems_version)
0133
0134 def output(self):
0135 """Return the output"""
0136 return self._output
0137
0138 def architectures(self):
0139 """Returns the number of architectures we have"""
0140 return len(self.archs)
0141
0142 def families(self, arch=None):
0143 """Returns the number of BSP families we have for an architecture. If
0144 you supply an architecture the count is the families in the
0145 architure.
0146
0147 """
0148 if arch is not None:
0149 return len(self.archs[arch])
0150 count = 0
0151 for arch in self.archs:
0152 count += len(self.archs[arch])
0153 return count
0154
0155 def bsps(self, arch=None, family=None):
0156 """Returns the number of BSPs we have for an architecture or a family"""
0157 count = 0
0158 if arch is not None and family is not None:
0159 count = len(self.archs[arch][family])
0160 elif arch is None and family is not None:
0161 for arch in self.archs:
0162 if family in self.archs[arch]:
0163 count = len(self.archs[arch][family])
0164 break
0165 elif arch is not None and family is None:
0166 count = 0
0167 for family in self.archs[arch]:
0168 count += len(self.archs[arch][family])
0169 else:
0170 for arch in self.archs:
0171 for family in self.archs[arch]:
0172 count += len(self.archs[arch][family])
0173 return count
0174
0175 def text(self, arch_selector=None, family_selector=None, show_path=False):
0176 """Generate plain text output"""
0177 self._clear()
0178 self._out(self.title())
0179 self._out()
0180 self._out('Architectures: %d' % (self.architectures()))
0181 self._out('BSP Families: %d' % (self.families()))
0182 self._out('BSPs: %d' % (self.bsps()))
0183 max_family = self._max_family_len()
0184 max_bsp = self._max_bsp_len()
0185 if arch_selector is None:
0186 archs_matcher = []
0187 else:
0188 archs_matcher = [a.strip() for a in arch_selector.split(',')]
0189 if family_selector is None:
0190 family_matcher = []
0191 else:
0192 family_matcher = [f.strip() for f in family_selector.split(',')]
0193 for arch in sorted(self.archs.keys()):
0194 if arch_selector is None or arch in archs_matcher:
0195 first = True
0196 for family in sorted(self.archs[arch].keys()):
0197 if family_selector is None or family in family_matcher:
0198 if first:
0199 self._out()
0200 self._out('%s: (families:%d bsps:%d)' % \
0201 (arch,
0202 self.families(arch=arch),
0203 self.bsps(arch=arch)))
0204 first = False
0205 for bsp in sorted(self.archs[arch][family].keys()):
0206 if show_path:
0207 p = os.path.join('bsps',
0208 self.archs[arch][family][bsp])
0209 self._out(' %-*s %-*s %s' % \
0210 (max_bsp, bsp, max_family, family, p))
0211 else:
0212 self._out(' %-*s %s' % (max_bsp, bsp, family))
0213
0214 def markdown(self,
0215 arch_selector=None,
0216 family_selector=None,
0217 show_path=False,
0218 show_title=False):
0219 """Generates markdown output"""
0220 self._clear()
0221 if show_title:
0222 self._out('# ' + self.title())
0223 self._out()
0224 self._out('**Architectures:** %d ' % (self.architectures()))
0225 self._out('**BSP Families:** %d ' % (self.families()))
0226 self._out('**BSPs:** %d ' % (self.bsps()))
0227 max_arch = self._max_arch_len()
0228 max_family = self._max_family_len()
0229 max_bsp = self._max_bsp_len()
0230 max_bsp_path = self._max_bsp_path_len() + 4
0231 if arch_selector is None:
0232 archs_matcher = []
0233 else:
0234 archs_matcher = [a.strip() for a in arch_selector.split(',')]
0235 if family_selector is None:
0236 family_matcher = []
0237 else:
0238 family_matcher = [f.strip() for f in family_selector.split(',')]
0239 for arch in sorted(self.archs.keys()):
0240 if arch_selector is None or arch in archs_matcher:
0241 first = True
0242 for family in sorted(self.archs[arch].keys()):
0243 if family_selector is None or family in family_matcher:
0244 if first:
0245 fbs = 'families:%-2d bsps:%-3d' % \
0246 (self.families(arch=arch),
0247 self.bsps(arch=arch))
0248 if max_family < len(fbs):
0249 max_fb = len(fbs)
0250 else:
0251 max_fb = max_family
0252 self._out()
0253 if show_path:
0254 self._out('%-*s |%-*s |' %
0255 (max_bsp, arch, max_fb, fbs))
0256 self._out('%s-|%s-|-%s' %
0257 ('-' * max_bsp, '-' * max_fb,
0258 '-' * max_bsp_path))
0259 else:
0260 self._out('%-*s |%s' % (max_bsp, arch, fbs))
0261 self._out('%s-|-%s' %
0262 ('-' * max_bsp, '-' * max_fb))
0263 first = False
0264 for bsp in sorted(self.archs[arch][family].keys()):
0265 if show_path:
0266 p = os.path.join('bsps',
0267 self.archs[arch][family][bsp])
0268 self._out('%-*s |%-*s |%s' % \
0269 (max_bsp, bsp, max_fb, family, p))
0270 else:
0271 self._out('%-*s |%s' % (max_bsp, bsp, family))
0272
0273 def pairs(self, arch_selector=None, family_selector=None, show_path=False):
0274 """Generate output as pairs"""
0275 self._clear()
0276 max_arch = self._max_arch_len()
0277 max_bsp = self._max_bsp_len()
0278 if arch_selector is None:
0279 arch_matcher = []
0280 else:
0281 arch_matcher = [a.strip() for a in arch_selector.split(',')]
0282 if family_selector is None:
0283 family_matcher = []
0284 else:
0285 family_matcher = [f.strip() for f in family_selector.split(',')]
0286 for arch in sorted(self.archs.keys()):
0287 if arch_selector is None or arch in arch_matcher:
0288 for family in sorted(self.archs[arch].keys()):
0289 if family_selector is None or family in family_matcher:
0290 for bsp in sorted(self.archs[arch][family].keys()):
0291 if show_path:
0292 p = os.path.join('bsps',
0293 self.archs[arch][family][bsp])
0294 pair = arch + '/' + bsp
0295 pair = '%-*s %s' % (max_arch + max_bsp + 1, pair, p)
0296
0297 self._out(pair)
0298 else:
0299 self._out('%s/%s' % (arch, bsp))
0300
0301 def config(self, arch_selector=None, family_selector=None):
0302 """Generate output as pairs"""
0303 self._clear()
0304 self._out(['# Generated by rtems-bsp',
0305 '[DEFAULT]',
0306 '# Build',
0307 'RTEMS_BUILD_LABEL = DEFAULT',
0308 'RTEMS_DEBUG = False',
0309 'RTEMS_PROFILING = False',
0310 'RTEMS_POSIX_API = True',
0311 '# Tests',
0312 'BUILD_TESTS = False',
0313 'BUILD_BENCHMARKS = False',
0314 'BUILD_FSTESTS = False',
0315 'BUILD_LIBTESTS = False',
0316 'BUILD_MPTESTS = False',
0317 'BUILD_PSXTESTS = False',
0318 'BUILD_PSXTMTESTS = False',
0319 'BUILD_RHEALSTONE = False',
0320 'BUILD_SAMPLES = True',
0321 'BUILD_SMPTESTS = False',
0322 'BUILD_SPTESTS = False',
0323 'BUILD_TMTESTS = False',
0324 'BUILD_UNITTESTS = False',
0325 'BUILD_VALIDATIONTESTS = False',
0326 'RTEMS_TEST_VERBOSITY = Normal',
0327 '# Compliler',
0328 '; WARNING_FLAGS = -Wall',
0329 '; CC_WARNING_FLAGS = -Wmissing-prototypes -Wimplicit-function-declaration -Wstrict-prototypes -Wnested-externs',
0330 '; CXX_WARNING_FLAGS = ',
0331 '; OPTIMIZATION_FLAGS = -O2 -g -fdata-sections -ffunction-sections',
0332 '; BSP_OPTIMIZATION_FLAGS = ${OPTIMIZATION_FLAGS}',
0333 '; CPUKIT_OPTIMIZATION_FLAGS = ${OPTIMIZATION_FLAGS}',
0334 '; TEST_OPTIMIZATION_FLAGS = ${OPTIMIZATION_FLAGS}',
0335 '; LINKFLAGS = ',
0336 '; LDFLAGS = -Wl,--gc-sections',
0337 '# BSP',
0338 'BSP_VERBOSE_FATAL_EXTENSION = 1',
0339 'BSP_PRINT_EXCEPTION_CONTEXT = 1',
0340 'BSP_RESET_BOARD_AT_EXIT = 1'])
0341 self._out()
0342 max_arch = self._max_arch_len()
0343 max_bsp = self._max_bsp_len()
0344 if arch_selector is None:
0345 arch_matcher = []
0346 else:
0347 arch_matcher = [a.strip() for a in arch_selector.split(',')]
0348 if family_selector is None:
0349 family_matcher = []
0350 else:
0351 family_matcher = [f.strip() for f in family_selector.split(',')]
0352 for arch in sorted(self.archs.keys()):
0353 if arch_selector is None or arch in arch_matcher:
0354 for family in sorted(self.archs[arch].keys()):
0355 if family_selector is None or family in family_matcher:
0356 for bsp in sorted(self.archs[arch][family].keys()):
0357 self._out('[%s/%s]' % (arch, bsp))
0358 self._out()
0359
0360
0361 def run(args):
0362 """Runs the command"""
0363 argsp = argparse.ArgumentParser(
0364 prog='rtems-bsps',
0365 description='List the BSP and architectures in RTEMS')
0366 argsp.add_argument('-a',
0367 '--arch',
0368 help='Output the BSPs in an architecture',
0369 type=str,
0370 default=None)
0371 argsp.add_argument('-f',
0372 '--family',
0373 help='Output the BSPs in an architecture family',
0374 type=str,
0375 default=None)
0376 argsp.add_argument('-p',
0377 '--paths',
0378 help='Show the BSP paths in the output',
0379 action='store_true')
0380 argsp.add_argument('-m',
0381 '--markdown',
0382 help='Output list in markdown format',
0383 action='store_true')
0384 argsp.add_argument('-T',
0385 '--title',
0386 help='Output a title in the markdown format',
0387 action='store_true')
0388 argsp.add_argument('-v',
0389 '--trace',
0390 help='Verbose or trace for debugging',
0391 action='store_true')
0392 argsp.add_argument('-P',
0393 '--pairs',
0394 help='Output architectures and BSPs in CPU/BSP format',
0395 action='store_true')
0396 argsp.add_argument('-C',
0397 '--config',
0398 help='Output architectures and BSPs in `config.ini` format',
0399 action='store_true')
0400
0401 argopts = argsp.parse_args(args[1:])
0402
0403 if argopts.arch is not None and argopts.family is not None:
0404 print('error: arch or family, not both at once', file=sys.stderr)
0405 sys.exit(1)
0406
0407 ab = ArchBsps(trace=argopts.trace)
0408
0409 if argopts.markdown:
0410 ab.markdown(arch_selector=argopts.arch,
0411 family_selector=argopts.family,
0412 show_path=argopts.paths,
0413 show_title=argopts.title)
0414 elif argopts.pairs:
0415 ab.pairs(arch_selector=argopts.arch,
0416 family_selector=argopts.family,
0417 show_path=argopts.paths)
0418 elif argopts.config:
0419 ab.config(arch_selector=argopts.arch,
0420 family_selector=argopts.family)
0421 else:
0422 ab.text(arch_selector=argopts.arch,
0423 family_selector=argopts.family,
0424 show_path=argopts.paths)
0425
0426 print(os.linesep.join(ab.output()))
0427
0428
0429 if __name__ == "__main__":
0430 run(sys.argv)