Back to home page

LXR

 
 

    


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)