mirror of
https://git.rtems.org/rtems-source-builder
synced 2024-10-09 07:15:10 +08:00
Add a faster bootstrap for RTEMS.
This is a threading dispatcher to bootstrap RTEMS using the available cores rather than the sequential standard script.
This commit is contained in:
parent
ccaa68e38c
commit
e879c9fe49
29
source-builder/sb-bootstrap
Executable file
29
source-builder/sb-bootstrap
Executable file
@ -0,0 +1,29 @@
|
||||
#! /usr/bin/env python
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2013 Chris Johns (chrisj@rtems.org)
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of the RTEMS Tools package in 'rtems-tools'.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import sys, os
|
||||
base = os.path.dirname(sys.argv[0])
|
||||
sys.path.insert(0, base + '/sb')
|
||||
try:
|
||||
import bootstrap
|
||||
bootstrap.run(sys.argv)
|
||||
except ImportError:
|
||||
print >> sys.stderr, "Incorrect Source Builder installation"
|
||||
sys.exit(1)
|
227
source-builder/sb/bootstrap.py
Normal file
227
source-builder/sb/bootstrap.py
Normal file
@ -0,0 +1,227 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2013 Chris Johns (chrisj@rtems.org)
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of the RTEMS Tools package in 'rtems-tools'.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
import datetime
|
||||
import operator
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
import error
|
||||
import log
|
||||
import options
|
||||
import path
|
||||
import version
|
||||
|
||||
def _collect(path_, file):
|
||||
confs = []
|
||||
for root, dirs, files in os.walk(path.host(path_), topdown = True):
|
||||
for f in files:
|
||||
if f == file:
|
||||
confs += [path.shell(path.join(root, f))]
|
||||
return confs
|
||||
|
||||
class command:
|
||||
|
||||
def __init__(self, cmd, cwd):
|
||||
self.exit_code = 0
|
||||
self.thread = None
|
||||
self.output = None
|
||||
self.cmd = cmd
|
||||
self.cwd = cwd
|
||||
|
||||
def runner(self):
|
||||
self.start_time = datetime.datetime.now()
|
||||
self.exit_code = 0
|
||||
try:
|
||||
self.output = subprocess.check_output(self.cmd, cwd = self.cwd)
|
||||
except subprocess.CalledProcessError, cpe:
|
||||
self.exit_code = cpe.returncode
|
||||
self.output = cpe.output
|
||||
self.end_time = datetime.datetime.now()
|
||||
|
||||
def run(self):
|
||||
self.thread = threading.Thread(target = self.runner)
|
||||
self.thread.start()
|
||||
|
||||
def is_alive(self):
|
||||
return self.thread and self.thread.is_alive()
|
||||
|
||||
class autoreconf:
|
||||
|
||||
def __init__(self, configure):
|
||||
self.configure = configure
|
||||
self.cwd = path.dirname(self.configure)
|
||||
self.bspopts()
|
||||
self.command = command(['autoreconf', '-i', '--no-recursive'], self.cwd)
|
||||
self.command.run()
|
||||
|
||||
def bspopts(self):
|
||||
try:
|
||||
c = open(self.configure, 'r')
|
||||
c_lines = c.readlines()
|
||||
c.close()
|
||||
except IOError, err:
|
||||
raise error.general('error reading: %s' % (configure))
|
||||
if 'RTEMS_CHECK_BSPDIR' in c_lines:
|
||||
bsp_specs = _collect(self.cwd, 'bsp_specs')
|
||||
try:
|
||||
acinclude = path.join(self.cwd, acinclude.m4)
|
||||
b = open(acinclude, 'w')
|
||||
b.write('# RTEMS_CHECK_BSPDIR(RTEMS_BSP_FAMILY) ')
|
||||
b.write('AC_DEFUN([RTEMS_CHECK_BSPDIR],')
|
||||
b.write('[')
|
||||
b.write(' case "$1" in')
|
||||
for bs in bsp_specs:
|
||||
b.write(' %s )' % (path.dirname(bs)))
|
||||
b.write(' AC_CONFIG_SUBDIRS([%s]);;' % (path.dirname(bs)))
|
||||
b.write(' *)')
|
||||
b.write(' AC_MSG_ERROR([Invalid BSP]);;')
|
||||
b.write(' esac')
|
||||
b.write('])')
|
||||
b.close()
|
||||
except IOError, err:
|
||||
raise error.general('error writing: %s' % (acinclude))
|
||||
|
||||
def is_alive(self):
|
||||
return self.command.is_alive()
|
||||
|
||||
def post_process(self):
|
||||
if self.command is not None:
|
||||
if self.command.exit_code != 0:
|
||||
raise error.general('error: autoreconf: %s' % (' '.join(self.command.cmd)))
|
||||
|
||||
def generate(topdir, jobs):
|
||||
if type(jobs) is str:
|
||||
jobs = int(jobs)
|
||||
start_time = datetime.datetime.now()
|
||||
confs = _collect(topdir, 'configure.ac')
|
||||
next = 0
|
||||
autoreconfs = []
|
||||
while next < len(confs) or len(autoreconfs) > 0:
|
||||
if next < len(confs) and len(autoreconfs) < jobs:
|
||||
log.notice('%3d/%3d: autoreconf: %s' % \
|
||||
(next + 1, len(confs), confs[next][len(topdir) + 1:]))
|
||||
autoreconfs += [autoreconf(confs[next])]
|
||||
next += 1
|
||||
else:
|
||||
for ac in autoreconfs:
|
||||
if not ac.is_alive():
|
||||
ac.post_process()
|
||||
autoreconfs.remove(ac)
|
||||
del ac
|
||||
if len(autoreconfs) >= jobs:
|
||||
time.sleep(1)
|
||||
end_time = datetime.datetime.now()
|
||||
log.notice('Bootstrap time: %s' % (str(end_time - start_time)))
|
||||
|
||||
class ampolish3:
|
||||
|
||||
def __init__(self, topdir, makefile):
|
||||
self.makefile = makefile
|
||||
self.topdir = topdir
|
||||
self.preinstall = path.join(path.dirname(makefile), 'preinstall.am')
|
||||
self.command = command([path.join(topdir, 'ampolish3'), makefile], self.topdir)
|
||||
self.command.run()
|
||||
|
||||
def is_alive(self):
|
||||
return self.command.is_alive()
|
||||
|
||||
def post_process(self):
|
||||
if self.command is not None:
|
||||
if self.command.exit_code != 0:
|
||||
raise error.general('error: ampolish3: %s' % (' '.join(self.command.cmd)))
|
||||
try:
|
||||
p = open(self.preinstall, 'w')
|
||||
for l in self.command.output:
|
||||
p.write(l)
|
||||
p.close()
|
||||
except IOError, err:
|
||||
raise error.general('error writing: %s' % (self.preinstall))
|
||||
|
||||
def preinstall(topdir, jobs):
|
||||
if type(jobs) is str:
|
||||
jobs = int(jobs)
|
||||
start_time = datetime.datetime.now()
|
||||
makes = []
|
||||
pre = re.compile('include .*/preinstall\.am')
|
||||
for am in _collect(topdir, 'Makefile.am'):
|
||||
try:
|
||||
m = open(am, 'r')
|
||||
am_lines = m.readlines()
|
||||
m.close()
|
||||
except IOError, err:
|
||||
raise error.general('error reading: %s' % (am))
|
||||
ml = [pre.match(l) != None for l in am_lines]
|
||||
if True in ml:
|
||||
makes += [am]
|
||||
next = 0
|
||||
ampolish3s = []
|
||||
while next < len(makes) or len(ampolish3s) > 0:
|
||||
if next < len(makes) and len(ampolish3s) < jobs:
|
||||
log.notice('%3d/%3d: ampolish3: %s' % \
|
||||
(next + 1, len(makes), makes[next][len(topdir) + 1:]))
|
||||
ampolish3s += [ampolish3(topdir, makes[next])]
|
||||
next += 1
|
||||
else:
|
||||
for ap in ampolish3s:
|
||||
if not ap.is_alive():
|
||||
ap.post_process()
|
||||
ampolish3s.remove(ap)
|
||||
del ap
|
||||
if len(ampolish3s) >= jobs:
|
||||
time.sleep(1)
|
||||
end_time = datetime.datetime.now()
|
||||
log.notice('Preinstall time: %s' % (str(end_time - start_time)))
|
||||
|
||||
def run(args):
|
||||
try:
|
||||
optargs = { '--rtems': 'The RTEMS source directory',
|
||||
'--preinstall': 'Preinstall AM generation' }
|
||||
log.notice('RTEMS Source Builder - RTEMS Bootstrap, v%s' % (version.str()))
|
||||
opts = options.load(sys.argv, optargs)
|
||||
if opts.get_arg('--rtems'):
|
||||
topdir = opts.get_arg('--rtems')
|
||||
else:
|
||||
topdir = os.getcwd()
|
||||
if opts.get_arg('--preinstall'):
|
||||
preinstall(topdir, opts.defaults['_ncpus'])
|
||||
else:
|
||||
generate(topdir, opts.defaults['_ncpus'])
|
||||
except error.general, gerr:
|
||||
print gerr
|
||||
print >> sys.stderr, 'Bootstrap FAILED'
|
||||
sys.exit(1)
|
||||
except error.internal, ierr:
|
||||
print ierr
|
||||
print >> sys.stderr, 'Bootstrap FAILED'
|
||||
sys.exit(1)
|
||||
except error.exit, eerr:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
log.notice('abort: user terminated')
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
run(sys.argv)
|
Loading…
x
Reference in New Issue
Block a user