source: rtems-source-builder/source-builder/sb/rtemsconfig.py @ 0393814

4.104.114.95
Last change on this file since 0393814 was 0393814, checked in by Chris Johns <chrisj@…>, on 08/05/14 at 03:51:08

sb: PR 2184 - Fix the subprocess use on Python < 2.7.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2013 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Permission to use, copy, modify, and/or distribute this software for any
9# purpose with or without fee is hereby granted, provided that the above
10# copyright notice and this permission notice appear in all copies.
11#
12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19#
20
21import datetime
22import operator
23import os
24import re
25import sys
26import threading
27import time
28
29import error
30import log
31import options
32import path
33import version
34
35def _collect(path_, file):
36    confs = []
37    for root, dirs, files in os.walk(path.host(path_), topdown = True):
38        for f in files:
39            if f == file:
40                confs += [path.shell(path.join(root, f))]
41    return confs
42
43def _grep(file, pattern):
44    rege = re.compile(pattern)
45    try:
46        f = open(path.host(file), 'r')
47        matches = [rege.match(l) != None for l in f.readlines()]
48        f.close()
49    except IOError, err:
50        raise error.general('error reading: %s' % (file))
51    return True in matches
52
53class command:
54
55    def __init__(self, opts, cmd, cwd = None):
56        self.exit_code = 0
57        self.output = None
58        self.opts = opts
59        self.cmd = cmd
60        self.cwd = cwd
61
62    def run(self):
63
64        import subprocess
65
66        #
67        # Support Python 2.6
68        #
69        if "check_output" not in dir(subprocess):
70            def f(*popenargs, **kwargs):
71                if 'stdout' in kwargs:
72                    raise ValueError('stdout argument not allowed, it will be overridden.')
73                process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
74                output, unused_err = process.communicate()
75                retcode = process.poll()
76                if retcode:
77                    cmd = kwargs.get("args")
78                    if cmd is None:
79                        cmd = popenargs[0]
80                    raise subprocess.CalledProcessError(retcode, cmd)
81                return output
82            subprocess.check_output = f
83
84        self.start_time = datetime.datetime.now()
85        self.exit_code = 0
86        try:
87            cmd = [self.opts.defaults.expand(c) for c in self.cmd]
88            self.output = subprocess.check_output(cmd, cwd = self.cwd)
89        except subprocess.CalledProcessError, cpe:
90            self.exit_code = cpe.returncode
91            self.output = cpe.output
92        self.end_time = datetime.datetime.now()
93
94class bsp_config:
95
96    filter_out = ['as', 'cc', 'ld', 'objcopy', 'size' ]
97
98    def __init__(self, opts, prefix, arch_bsp):
99        self.opts = opts
100        self.prefix = prefix
101        if not path.exists(prefix):
102            raise error.general('RTEMS prefix path not found: %s' % (prefix))
103        self.makefile_inc = None
104        if '/' in arch_bsp:
105            arch, bsp = arch_bsp.split('/', 1)
106        else:
107            arch = None
108            bsp = arch_bsp
109        makefile_incs = _collect(prefix, 'Makefile.inc')
110        for mi in makefile_incs:
111            found = True
112            if arch is not None and arch not in mi:
113                found = False
114            if bsp not in mi:
115                found = False
116            if found:
117                self.makefile_inc = mi
118                break
119        if self.makefile_inc is None:
120            raise error.general('RTEMS BSP not found: %s' % (arch_bsp))
121        if not path.exists(self.makefile_inc):
122            raise error.general('RTEMS BSP configuration not found: %s: %s' % \
123                                    (arch_bsp, self.makefile_inc))
124        self.command = command(opts, ['%{__make}',
125                                      '-f' '%{_sbdir}/sb/rtemsconfig.mk',
126                                      'makefile_inc=%s' % (self.makefile_inc)])
127        self.command.run()
128        self.parse(self.command.output)
129
130    def __str__(self):
131        s = None
132        for c in sorted(self.configs.keys()):
133            if s is None:
134                s = ''
135            else:
136                s += os.linesep
137            s += '%s = %s' % (c, self.configs[c])
138        return s
139
140    def parse(self, text):
141        self.configs = {}
142        lines = text.splitlines()
143        lc = 0
144        while lc < len(lines):
145            l = lines[lc].strip()
146            lc += 1
147            if len(l) == 0 or l[0] == '#' or '=' not in l:
148                continue
149            key = l[:l.index('=')].strip()
150            data = l[l.index('=') + 1:].strip()
151            if len(data) == 0:
152                continue
153            if data[0] == '"':
154                if len(data) == 1 or data[-1] != '"':
155                    not_closed = True
156                    while lc < len(lines) and not_closed:
157                        l = lines[lc]
158                        lc += 1
159                        if l[-1] == '"':
160                            data += l
161                            not_close = False
162            self.configs[key] = data
163
164    def keys(self):
165        _keys = {}
166        for k in sorted(self.configs.keys()):
167            _keys[k.lower()] = k
168        return _keys
169
170    def find(self, name):
171        _keys = self.keys()
172        nl = name.lower()
173        if nl in _keys and not nl in bsp_config.filter_out:
174            return self.configs[_keys[nl]]
175        raise error.general('invalid configuration: %s' % (name))
176
177def run(args):
178    try:
179        optargs = { '--rtems':      'The RTEMS source directory',
180                    '--rtems-bsp':  'The RTEMS BSP (arch/bsp)',
181                    '--list':       'List the configurations' }
182        opts = options.load(sys.argv, optargs)
183
184        if opts.get_arg('--rtems'):
185            prefix = opts.get_arg('--rtems')[1]
186        else:
187            prefix = os.getcwd()
188        if opts.get_arg('--rtems-bsp') is None:
189            raise error.general('no --rtems-bsp option; please provide')
190
191        bsp = bsp_config(opts, prefix, opts.get_arg('--rtems-bsp')[1])
192
193        if opts.get_arg('--list'):
194            log.notice('RTEMS Source Builder - RTEMS Configuration, v%s' % (version.str()))
195            opts.log_info()
196            configs = bsp.keys()
197            for c in sorted(configs.keys()):
198                print c
199        else:
200            for p in opts.params():
201                print bsp.find(p)
202
203    except error.general, gerr:
204        print gerr
205        sys.exit(1)
206    except error.internal, ierr:
207        print ierr
208        sys.exit(1)
209    except error.exit, eerr:
210        pass
211    except KeyboardInterrupt:
212        log.notice('abort: user terminated')
213        sys.exit(1)
214    sys.exit(0)
215
216if __name__ == "__main__":
217    run(sys.argv)
Note: See TracBrowser for help on using the repository browser.