source: rtems-source-builder/source-builder/sb/bootstrap.py @ bf23399

4.104.114.9
Last change on this file since bf23399 was bf23399, checked in by Chris Johns <chrisj@…>, on Apr 27, 2013 at 11:56:33 AM

Add a grep function and timestamp.

Fix the acinclude.m4.

  • Property mode set to 100644
File size: 8.1 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 subprocess
26import sys
27import threading
28import time
29
30import error
31import log
32import options
33import path
34import version
35
36def _collect(path_, file):
37    confs = []
38    for root, dirs, files in os.walk(path.host(path_), topdown = True):
39        for f in files:
40            if f == file:
41                confs += [path.shell(path.join(root, f))]
42    return confs
43
44def _grep(file, pattern):
45    rege = re.compile(pattern)
46    try:
47        f = open(file, 'r')
48        matches = [rege.match(l) != None for l in f.readlines()]
49        f.close()
50    except IOError, err:
51        raise error.general('error reading: %s' % (file))
52    return True in matches
53
54class command:
55
56    def __init__(self, cmd, cwd):
57        self.exit_code = 0
58        self.thread = None
59        self.output = None
60        self.cmd = cmd
61        self.cwd = cwd
62
63    def runner(self):
64        self.start_time = datetime.datetime.now()
65        self.exit_code = 0
66        try:
67            self.output = subprocess.check_output(self.cmd, cwd = self.cwd)
68        except subprocess.CalledProcessError, cpe:
69            self.exit_code = cpe.returncode
70            self.output = cpe.output
71        self.end_time = datetime.datetime.now()
72
73    def run(self):
74        self.thread = threading.Thread(target = self.runner)
75        self.thread.start()
76
77    def is_alive(self):
78        return self.thread and self.thread.is_alive()
79
80class autoreconf:
81
82    def __init__(self, topdir, configure):
83        self.topdir = topdir
84        self.configure = configure
85        self.cwd = path.dirname(self.configure)
86        self.bspopts()
87        self.command = command(['autoreconf', '-i', '--no-recursive'], self.cwd)
88        self.command.run()
89
90    def bspopts(self):
91        if _grep(self.configure, 'RTEMS_CHECK_BSPDIR'):
92            bsp_specs = _collect(self.cwd, 'bsp_specs')
93            try:
94                acinclude = path.join(self.cwd, 'acinclude.m4')
95                b = open(acinclude, 'w')
96                b.write('# RTEMS_CHECK_BSPDIR(RTEMS_BSP_FAMILY) ' + os.linesep)
97                b.write('AC_DEFUN([RTEMS_CHECK_BSPDIR],' + os.linesep)
98                b.write('[' + os.linesep)
99                b.write(' case "$1" in' + os.linesep)
100                for bs in bsp_specs:
101                    dir = path.dirname(bs)[len(self.cwd) + 1:]
102                    b.write('   %s )%s' % (dir, os.linesep))
103                    b.write('     AC_CONFIG_SUBDIRS([%s]);;%s' % (dir, os.linesep))
104                b.write('  *)' + os.linesep)
105                b.write('    AC_MSG_ERROR([Invalid BSP]);;' + os.linesep)
106                b.write('  esac' + os.linesep)
107                b.write('])' + os.linesep)
108                b.close()
109            except IOError, err:
110                raise error.general('error writing: %s' % (acinclude))
111
112    def is_alive(self):
113        return self.command.is_alive()
114
115    def post_process(self):
116        if self.command is not None:
117            if self.command.exit_code != 0:
118                raise error.general('error: autoreconf: %s' % (' '.join(self.command.cmd)))
119            makefile = path.join(self.cwd, 'Makefile.am')
120            if path.exists(makefile):
121                if _grep(makefile, 'stamp-h\.in'):
122                    stamp_h = path.join(self.cwd, 'stamp-h.in')
123                    try:
124                        t = open(stamp_h, 'w')
125                        t.write('timestamp')
126                        t.close()
127                    except IOError, err:
128                        raise error.general('error writing: %s' % (stamp_h))
129
130def generate(topdir, jobs):
131    if type(jobs) is str:
132        jobs = int(jobs)
133    start_time = datetime.datetime.now()
134    confs = _collect(topdir, 'configure.ac')
135    next = 0
136    autoreconfs = []
137    while next < len(confs) or len(autoreconfs) > 0:
138        if next < len(confs) and len(autoreconfs) < jobs:
139            log.notice('%3d/%3d: autoreconf: %s' % \
140                           (next + 1, len(confs), confs[next][len(topdir) + 1:]))
141            autoreconfs += [autoreconf(topdir, confs[next])]
142            next += 1
143        else:
144            for ac in autoreconfs:
145                if not ac.is_alive():
146                    ac.post_process()
147                    autoreconfs.remove(ac)
148                    del ac
149            if len(autoreconfs) >= jobs:
150                time.sleep(1)
151    end_time = datetime.datetime.now()
152    log.notice('Bootstrap time: %s' % (str(end_time - start_time)))
153
154class ampolish3:
155
156    def __init__(self, topdir, makefile):
157        self.topdir = topdir
158        self.makefile = makefile
159        self.preinstall = path.join(path.dirname(makefile), 'preinstall.am')
160        self.command = command([path.join(topdir, 'ampolish3'), makefile], self.topdir)
161        self.command.run()
162
163    def is_alive(self):
164        return self.command.is_alive()
165
166    def post_process(self):
167        if self.command is not None:
168            if self.command.exit_code != 0:
169                raise error.general('error: ampolish3: %s' % (' '.join(self.command.cmd)))
170            try:
171                p = open(self.preinstall, 'w')
172                for l in self.command.output:
173                    p.write(l)
174                p.close()
175            except IOError, err:
176                raise error.general('error writing: %s' % (self.preinstall))
177
178def preinstall(topdir, jobs):
179    if type(jobs) is str:
180        jobs = int(jobs)
181    start_time = datetime.datetime.now()
182    makes = []
183    for am in _collect(topdir, 'Makefile.am'):
184        if _grep(am, 'include .*/preinstall\.am'):
185            makes += [am]
186    next = 0
187    ampolish3s = []
188    while next < len(makes) or len(ampolish3s) > 0:
189        if next < len(makes) and len(ampolish3s) < jobs:
190            log.notice('%3d/%3d: ampolish3: %s' % \
191                           (next + 1, len(makes), makes[next][len(topdir) + 1:]))
192            ampolish3s += [ampolish3(topdir, makes[next])]
193            next += 1
194        else:
195            for ap in ampolish3s:
196                if not ap.is_alive():
197                    ap.post_process()
198                    ampolish3s.remove(ap)
199                    del ap
200            if len(ampolish3s) >= jobs:
201                time.sleep(1)
202    end_time = datetime.datetime.now()
203    log.notice('Preinstall time: %s' % (str(end_time - start_time)))
204
205def run(args):
206    try:
207        optargs = { '--rtems':       'The RTEMS source directory',
208                    '--preinstall':  'Preinstall AM generation' }
209        log.notice('RTEMS Source Builder - RTEMS Bootstrap, v%s' % (version.str()))
210        opts = options.load(sys.argv, optargs)
211        if opts.get_arg('--rtems'):
212            topdir = opts.get_arg('--rtems')
213        else:
214            topdir = os.getcwd()
215        if opts.get_arg('--preinstall'):
216            preinstall(topdir, opts.defaults['_ncpus'])
217        else:
218            generate(topdir, opts.defaults['_ncpus'])
219    except error.general, gerr:
220        print gerr
221        print >> sys.stderr, 'Bootstrap FAILED'
222        sys.exit(1)
223    except error.internal, ierr:
224        print ierr
225        print >> sys.stderr, 'Bootstrap FAILED'
226        sys.exit(1)
227    except error.exit, eerr:
228        pass
229    except KeyboardInterrupt:
230        log.notice('abort: user terminated')
231        sys.exit(1)
232    sys.exit(0)
233
234if __name__ == "__main__":
235    run(sys.argv)
Note: See TracBrowser for help on using the repository browser.