2010-08-09 Chris Johns <chrisj@rtems.org>

* specbuilder, specbuilder/sb-build, specbuilder/sb-crossgcc,
        specbuilder/sb-setup, specbuilder/sb-specdump,
        specbuilder/sb-status, specbuilder/specbuilder/.cvsignore,
        specbuilder/specbuilder/build.py,
        specbuilder/specbuilder/config.sub,
        specbuilder/specbuilder/crossgcc.py,
        specbuilder/specbuilder/darwin.py,
        specbuilder/specbuilder/defaults.py,
        specbuilder/specbuilder/error.py,
        specbuilder/specbuilder/execute.py,
        specbuilder/specbuilder/log.py, specbuilder/specbuilder/setup.py,
        specbuilder/specbuilder/spec.py,
        specbuilder/specbuilder/status.py: New.
This commit is contained in:
Chris Johns 2010-08-09 01:29:43 +00:00
parent 2dc8560ba8
commit 7231f495e0
18 changed files with 4404 additions and 0 deletions

15
ChangeLog Normal file
View File

@ -0,0 +1,15 @@
2010-08-09 Chris Johns <chrisj@rtems.org>
* specbuilder, specbuilder/sb-build, specbuilder/sb-crossgcc,
specbuilder/sb-setup, specbuilder/sb-specdump,
specbuilder/sb-status, specbuilder/specbuilder/.cvsignore,
specbuilder/specbuilder/build.py,
specbuilder/specbuilder/config.sub,
specbuilder/specbuilder/crossgcc.py,
specbuilder/specbuilder/darwin.py,
specbuilder/specbuilder/defaults.py,
specbuilder/specbuilder/error.py,
specbuilder/specbuilder/execute.py,
specbuilder/specbuilder/log.py, specbuilder/specbuilder/setup.py,
specbuilder/specbuilder/spec.py,
specbuilder/specbuilder/status.py: New.

33
specbuilder/sb-build Executable file
View File

@ -0,0 +1,33 @@
#! /usr/bin/env python
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
import sys, os
base = os.path.dirname(sys.argv[0])
sys.path.insert(0, base + '/specbuilder')
try:
import build
build.run(sys.argv)
except ImportError:
print >> sys.stderr, "Incorrect SpecBulder installation"
sys.exit(1)

33
specbuilder/sb-crossgcc Executable file
View File

@ -0,0 +1,33 @@
#! /usr/bin/env python
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
import sys, os
base = os.path.dirname(sys.argv[0])
sys.path.insert(0, base + '/specbuilder')
try:
import crossgcc
crossgcc.run()
except ImportError:
print >> sys.stderr, "Incorrect SpecBulder installation"
sys.exit(1)

33
specbuilder/sb-setup Executable file
View File

@ -0,0 +1,33 @@
#! /usr/bin/env python
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
import sys, os
base = os.path.dirname(sys.argv[0])
sys.path.insert(0, base + '/specbuilder')
try:
import setup
setup.run()
except ImportError:
print >> sys.stderr, "Incorrect SpecBulder installation"
sys.exit(1)

33
specbuilder/sb-specdump Executable file
View File

@ -0,0 +1,33 @@
#! /usr/bin/env python
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
import sys, os
base = os.path.dirname(sys.argv[0])
sys.path.insert(0, base + '/specbuilder')
try:
import spec
spec.run()
except ImportError:
print >> sys.stderr, "Incorrect SpecBulder installation"
sys.exit(1)

33
specbuilder/sb-status Executable file
View File

@ -0,0 +1,33 @@
#! /usr/bin/env python
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
import sys, os
base = os.path.dirname(sys.argv[0])
sys.path.insert(0, base + '/specbuilder')
try:
import status
status.run()
except ImportError:
print >> sys.stderr, "Incorrect SpecBulder installation"
sys.exit(1)

View File

@ -0,0 +1 @@
*.pyc

View File

@ -0,0 +1,411 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# This code builds a package given a spec file. It only builds to be installed
# not to be package unless you run a packager around this.
#
import getopt
import os
import shutil
import stat
import sys
import urllib2
import urlparse
import defaults
import error
import execute
import log
import spec
#
# Version of Spec Builder.
#
version = '0.1'
def _notice(opts, text):
if not opts.quiet() and not log.default.has_stdout():
print text
log.output(text)
log.flush()
class script:
"""Create and manage a shell script."""
def __init__(self, quiet = True):
self.quiet = quiet
self.reset()
def reset(self):
self.body = []
self.lc = 0
def append(self, text):
if type(text) is str:
text = text.splitlines()
if not self.quiet:
i = 0
for l in text:
i += 1
log.output('script:%3d: ' % (self.lc + i) + l)
self.lc += len(text)
self.body.extend(text)
def write(self, name, check_for_errors = False):
s = None
try:
s = open(name, 'w')
s.write('\n'.join(self.body))
s.close()
os.chmod(name, stat.S_IRWXU | \
stat.S_IRGRP | stat.S_IXGRP | \
stat.S_IROTH | stat.S_IXOTH)
except IOError, err:
raise error.general('creating script: ' + name)
finally:
if s is not None:
s.close()
class build:
"""Build a package given a spec file."""
def __init__(self, name, _defaults, opts):
self.opts = opts
_notice(opts, 'building: ' + name)
self.spec = spec.file(name, _defaults = _defaults, opts = opts)
self.script = script(quiet = opts.quiet())
def _output(self, text):
if not self.opts.quiet():
log.output(text)
def rmdir(self, path):
if not self.opts.dry_run():
self._output('removing: ' + path)
if os.path.exists(path):
try:
shutil.rmtree(path)
except IOError, err:
raise error.error('error removing: ' + path)
def mkdir(self, path):
if not self.opts.dry_run():
self._output('making dir: ' + path)
try:
os.makedirs(path)
except IOError, err:
raise error.general('error creating path: ' + path)
def get_file(self, url, local):
if not os.path.isdir(os.path.dirname(local)):
raise error.general('source path not found: ' + os.path.dirname(local))
if not os.path.exists(local):
#
# Not localy found so we need to download it. Check if a URL
# has been provided on the command line.
#
url_bases = self.opts.urls()
urls = []
if url_bases is not None:
for base in url_bases:
if base[-1:] != '/':
base += '/'
url_path = urlparse.urlsplit(url).path
slash = url_path.rfind('/')
if slash < 0:
url_file = url_path
else:
url_file = url_path[slash + 1:]
urls.append(urlparse.urljoin(base, url_file))
urls.append(url)
for url in urls:
_notice(self.opts, 'download: ' + url + ' -> ' + local)
if not self.opts.dry_run():
failed = False
_in = None
_out = None
try:
_in = urllib2.urlopen(url)
_out = open(local, 'wb')
_out.write(_in.read())
except IOError, err:
_notice(self.opts, 'download: ' + url + ': failed: ' + str(err))
if os.path.exists(local):
os.remove(local)
failed = True
finally:
if _out is not None:
_out.close()
if _in is not None:
del _in
if not failed:
if not os.path.isfile(local):
raise error.general('source is not a file: ' + local)
return
raise error.general('downloading ' + url + ': all paths have failed, giving up')
def parse_url(self, url):
#
# Split the source up into the parts we need.
#
source = {}
source['url'] = url
source['path'] = os.path.dirname(url)
source['file'] = os.path.basename(url)
source['name'], source['ext'] = os.path.splitext(source['file'])
#
# Get the file. Checks the local source directory first.
#
source['local'] = os.path.join(self.spec.abspath('_sourcedir'),
source['file'])
#
# Is the file compressed ?
#
esl = source['ext'].split('.')
if esl[-1:][0] == 'gz':
source['compressed'] = '%{__gzip} -dc'
elif esl[-1:][0] == 'bz2':
source['compressed'] = '%{__bzip2} -dc'
elif esl[-1:][0] == 'bz2':
source['compressed'] = '%{__zip} -u'
source['script'] = ''
return source
def source(self, package, source_tag):
#
# Scan the sources found in the spec file for the one we are
# after. Infos or tags are lists.
#
sources = package.sources()
url = None
for s in sources:
tag = s[len('source'):]
if tag.isdigit():
if int(tag) == source_tag:
url = sources[s][0]
break
if url is None:
raise error.general('source tag not found: source' + str(source_tag))
source = self.parse_url(url)
self.get_file(source['url'], source['local'])
if 'compressed' in source:
source['script'] = source['compressed'] + ' ' + \
source['local'] + ' | %{__tar_extract} -'
else:
source['script'] = '%{__tar_extract} ' + source['local']
return source
def patch(self, package, args):
#
# Scan the patches found in the spec file for the one we are
# after. Infos or tags are lists.
#
patches = package.patches()
url = None
for p in patches:
if args[0][1:].lower() == p:
url = patches[p][0]
break
if url is None:
raise error.general('patch tag not found: ' + args[0])
patch = self.parse_url(url)
self.get_file(patch['url'], patch['local'])
if 'compressed' in patch:
patch['script'] = patch['compressed'] + ' ' + patch['local']
else:
patch['script'] = '%{__cat} ' + patch['local']
patch['script'] += ' | %{__patch} ' + ' '.join(args[1:])
self.script.append(self.spec.expand(patch['script']))
def setup(self, package, args):
self._output('prep: ' + package.name() + ': ' + ' '.join(args))
opts, args = getopt.getopt(args[1:], 'qDcTn:b:a:')
source_tag = 0
quiet = False
unpack_default_source = True
delete_before_unpack = True
create_dir = False
name = None
unpack_before_chdir = True
for o in opts:
if o[0] == '-q':
quiet = True
elif o[0] == '-D':
delete_before_unpack = False
elif o[0] == '-c':
create_dir = True
elif o[0] == '-T':
unpack_default_source = False
elif o[0] == '-n':
name = o[1]
elif o[0] == '-b':
unpack_before_chdir = True
if not o[1].isdigit():
raise error.general('setup source tag no a number: ' + o[1])
source_tag = int(o[1])
elif o[0] == '-a':
unpack_before_chdir = False
source_tag = int(o[1])
source0 = None
source = self.source(package, source_tag)
if name is None:
if source:
name = source['name']
else:
name = source0['name']
self.script.append(self.spec.expand('cd %{_builddir}'))
if delete_before_unpack:
self.script.append(self.spec.expand('%{__rm} -rf ' + name))
if create_dir:
self.script.append(self.spec.expand('%{__mkdir_p} ' + name))
#
# If -a? then change directory before unpacking.
#
if not unpack_before_chdir:
self.script.append(self.spec.expand('cd ' + name))
#
# Unpacking the source. Note, treated the same as -a0.
#
if unpack_default_source and source_tag != 0:
source0 = self.source(package, 0)
if source0 is None:
raise error.general('no setup source0 tag found')
self.script.append(self.spec.expand(source0['script']))
self.script.append(self.spec.expand(source['script']))
if unpack_before_chdir:
self.script.append(self.spec.expand('cd ' + name))
self.script.append(self.spec.expand('%{__setup_post}'))
if create_dir:
self.script.append(self.spec.expand('cd ..'))
def run(self, command, shell_opts = '', cwd = None):
e = execute.capture_execution(log = log.default, dump = self.opts.quiet())
cmd = self.spec.expand('%{___build_shell} -ex ' + shell_opts + ' ' + command)
self._output('run: ' + cmd)
exit_code, proc, output = e.shell(cmd, cwd = cwd)
if exit_code != 0:
raise error.general('shell cmd failed: ' + cmd)
def builddir(self):
builddir = self.spec.abspath('_builddir')
self.rmdir(builddir)
if not self.opts.dry_run():
self.mkdir(builddir)
def prep(self, package):
self.script.append('echo "==> %prep:"')
_prep = package.prep()
for l in _prep:
args = l.split()
if args[0] == '%setup':
self.setup(package, args)
elif args[0].startswith('%patch'):
self.patch(package, args)
else:
self.script.append(' '.join(args))
def build(self, package):
self.script.append('echo "==> %build:"')
_build = package.build()
for l in _build:
args = l.split()
self.script.append(' '.join(args))
def install(self, package):
self.script.append('echo "==> %install:"')
_install = package.install()
for l in _install:
args = l.split()
self.script.append(' '.join(args))
def files(self, package):
self.script.append('echo "==> %files:"')
prefixbase = self.opts.prefixbase()
if prefixbase is None:
prefixbase = ''
inpath = os.path.join('%{buildroot}', prefixbase)
self.script.append(self.spec.expand('cd ' + inpath))
tar = os.path.join('%{_rpmdir}', package.long_name() + '.tar.bz2')
cmd = self.spec.expand('%{__tar} -cf - . ' + '| %{__bzip2} > ' + tar)
self.script.append(cmd)
self.script.append(self.spec.expand('cd %{_builddir}'))
def clean(self, package):
self.script.append('echo "==> %clean:"')
_clean = package.clean()
for l in _clean:
args = l.split()
self.script.append(' '.join(args))
def cleanup(self):
buildroot = self.spec.abspath('buildroot')
builddir = self.spec.abspath('_builddir')
self.rmdir(buildroot)
self.rmdir(builddir)
def make(self):
packages = self.spec.packages()
package = packages['main']
_notice(self.opts, 'package: ' + package.name() + '-' + package.version())
self.script.reset()
self.script.append(self.spec.expand('%{___build_template}'))
self.script.append('echo "=> ' + package.name() + '-' + package.version() + ':"')
self.prep(package)
self.build(package)
self.install(package)
self.files(package)
if not self.opts.no_clean():
self.clean(package)
if not self.opts.dry_run():
self.builddir()
sn = self.spec.expand(os.path.join('%{_builddir}', 'doit'))
self._output('write script: ' + sn)
self.script.write(sn)
self.run(sn)
if not self.opts.no_clean():
self.cleanup()
def run(args):
try:
opts, _defaults = defaults.load(args)
log.default = log.log(opts.logfiles())
_notice(opts, 'RTEMS Tools, Spec Builder, v%s' % (version))
for spec_file in opts.spec_files():
b = build(spec_file, _defaults = _defaults, opts = opts)
b.make()
del b
except error.general, gerr:
print gerr
sys.exit(1)
except error.internal, ierr:
print ierr
sys.exit(1)
except KeyboardInterrupt:
_notice(opts, 'user terminated')
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
run(sys.argv)

1705
specbuilder/specbuilder/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,157 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# This code builds a cross-gcc compiler suite of tools given an architecture.
#
import distutils.dir_util
import operator
import os
import build
import defaults
import error
import log
#
# Version of Spec CrossGCC Builder.
#
version = '0.1'
def _notice(opts, text):
if not opts.quiet() and not log.default.has_stdout():
print text
log.output(text)
log.flush()
class crossgcc:
"""Build a Cross GCC Compiler tool suite."""
_order = { 'binutils': 0,
'gcc' : 1,
'gdb' : 2 }
def __init__(self, arch, _defaults, opts):
self.arch = arch
self.opts = opts
self.defaults = _defaults
def _output(self, text):
if not self.opts.quiet():
log.output(text)
def copy(self, src, dst):
what = src + ' -> ' + dst
_notice(self.opts, 'coping: ' + what)
try:
files = distutils.dir_util.copy_tree(src, dst)
for f in files:
self._output(f)
except IOError, err:
raise error.general('coping tree: ' + what + ': ' + str(err))
def first_package(self, _build):
path = os.path.join(_build.spec.abspath('%{_tmppath}'),
_build.spec.expand('crossgcc-%(%{__id_u} -n)'))
_build.rmdir(path)
_build.mkdir(path)
prefix = os.path.join(_build.spec.expand('%{_prefix}'), 'bin')
if prefix[0] == os.sep:
prefix = prefix[1:]
binpath = os.path.join(path, prefix)
os.environ['PATH'] = binpath + os.pathsep + os.environ['PATH']
self._output('path: ' + os.environ['PATH'])
return path
def every_package(self, _build, path):
self.copy(_build.spec.abspath('%{buildroot}'), path)
_build.cleanup()
def last_package(self, _build, path):
tar = os.path.join('%{_rpmdir}', self.arch + '-tools.tar.bz2')
cmd = _build.spec.expand("'cd " + path + \
" && %{__tar} -cf - . | %{__bzip2} > " + tar + "'")
_build.run(cmd, shell_opts = '-c', cwd = path)
if not self.opts.no_clean():
_build.rmdir(path)
def make(self):
def _sort(specs):
_specs = {}
for spec in specs:
for order in crossgcc._order:
if spec.lower().find(order) >= 0:
_specs[spec] = crossgcc._order[order]
sorted_specs = sorted(_specs.iteritems(), key = operator.itemgetter(1))
specs = []
for s in range(0, len(sorted_specs)):
specs.append(sorted_specs[s][0])
return specs
_notice(self.opts, 'arch: ' + self.arch)
specs = self.opts.get_spec_files('*' + self.arch + '*')
arch_specs = []
for spec in specs:
if spec.lower().find(self.arch.lower()) >= 0:
arch_specs.append(spec)
arch_specs = _sort(arch_specs)
self.opts.opts['no-clean'] = '1'
current_path = os.environ['PATH']
try:
for s in range(0, len(arch_specs)):
b = build.build(arch_specs[s], _defaults = self.defaults, opts = self.opts)
if s == 0:
path = self.first_package(b)
b.make()
self.every_package(b, path)
if s == len(arch_specs) - 1:
self.last_package(b, path)
del b
finally:
os.environ['PATH'] = current_path
def run():
import sys
try:
opts, _defaults = defaults.load(sys.argv)
log.default = log.log(opts.logfiles())
_notice(opts, 'RTEMS Tools, CrossGCC Spec Builder, v%s' % (version))
for arch in opts.params():
c = crossgcc(arch, _defaults = _defaults, opts = opts)
c.make()
del c
except error.general, gerr:
print gerr
sys.exit(1)
except error.internal, ierr:
print ierr
sys.exit(1)
except KeyboardInterrupt:
_notice(opts, 'user terminated')
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
run()

View File

@ -0,0 +1,52 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# This code is based on what ever doco about spec files I could find and
# RTEMS project's spec files.
#
import pprint
import os
def load():
uname = os.uname()
defines = {
'_os': 'darwin',
'_host': uname[4] + '-apple-darwin' + uname[2],
'_host_vendor': 'apple',
'_host_os': 'darwin',
'_host_cpu': uname[4],
'_host_alias': '%{nil}',
'_host_arch': uname[4],
'_usr': '/opt/local',
'_var': '/opt/local/var',
'optflags': '-O2 -fasynchronous-unwind-tables',
'_smp_mflags': '-j4',
# Build readline with gdb.
'without_system_readline': 'without_system_readline'
}
return defines
if __name__ == '__main__':
pprint.pprint(load())

View File

@ -0,0 +1,407 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# Determine the defaults and load the specific file.
#
import glob
import pprint
import re
import os
import error
import execute
defaults = {
# Hack. Suspect a hidden platform or comand line thing
'_with_noarch_subpackages': '1',
# Paths
'_host_platform': '%{_host_cpu}-%{_host_vendor}-%{_host_os}%{?_gnu}',
'_build': '%{_host}',
'_arch': '%{_host_arch}',
'_topdir': os.getcwd(),
'_srcrpmdir': '%{_topdir}/SRPMS',
'_sourcedir': '%{_topdir}/SOURCES',
'_specdir': '%{_topdir}/SPECS',
'_rpmdir': '%{_topdir}/TARS',
'_builddir': '%{_topdir}/BUILD/%{name}-%{version}-%{release}',
'_docdir': '%{_defaultdocdir}',
'_usrlibrpm': '%{_topdir}/RPMLIB',
'_tmppath': '%{_topdir}/TMP',
'buildroot:': '%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)',
# Not sure.
'_gnu': '-gnu',
# Cloned stuff from an RPM insall
'___build_args': '-e',
'___build_cmd': '%{?_sudo:%{_sudo} }%{?_remsh:%{_remsh} %{_remhost} }%{?_remsudo:%{_remsudo} }%{?_remchroot:%{_remchroot} %{_remroot} }%{___build_shell} %{___build_args}',
'___build_post': 'exit 0',
'___build_pre': '''# ___build_pre in defaults.py
RPM_SOURCE_DIR="%{_sourcedir}"
RPM_BUILD_DIR="%{_builddir}"
RPM_OPT_FLAGS="%{optflags}"
RPM_ARCH="%{_arch}"
RPM_OS="%{_os}"
export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS
RPM_DOC_DIR="%{_docdir}"
export RPM_DOC_DIR
RPM_PACKAGE_NAME="%{name}"
RPM_PACKAGE_VERSION="%{version}"
RPM_PACKAGE_RELEASE="%{release}"
export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE
%{?buildroot:RPM_BUILD_ROOT="%{buildroot}"}
export RPM_BUILD_ROOT
%{?_javaclasspath:CLASSPATH="%{_javaclasspath}"; export CLASSPATH}
LANG=C
export LANG
unset DISPLAY || :
umask 022
cd "%{_builddir}"''',
'___build_shell': '%{?_buildshell:%{_buildshell}}%{!?_buildshell:/bin/sh}',
'___build_template': '''#!%{___build_shell}
%{___build_pre}
%{nil}''',
'__aclocal': 'aclocal',
'__ar': 'ar',
'__arch_install_post': '%{nil}',
'__as': 'as',
'__autoconf': 'autoconf',
'__autoheader': 'autoheader',
'__automake': 'automake',
'__awk': 'awk',
'__bash': '/bin/bash',
'__bzip2': '/usr/bin/bzip2',
'__cat': '/bin/cat',
'__cc': '/usr/bin/gcc',
'__check_files': '%{_usrlibrpm}/check-files %{buildroot}',
'__chgrp': '/usr/bin/chgrp',
'__chmod': '/bin/chmod',
'__chown': '/usr/sbin/chown',
'__cp': '/bin/cp',
'__cpio': '/usr/bin/cpio',
'__cpp': '/usr/bin/gcc -E',
'__cxx': '/usr/bin/g++',
'__grep': '/usr/bin/grep',
'__gzip': '/usr/bin/gzip',
'__id': '/usr/bin/id',
'__id_u': '%{__id} -u',
'__install': '/usr/bin/install',
'__install_info': '/usr/bin/install-info',
'__ld': '/usr/bin/ld',
'__ldconfig': '/sbin/ldconfig',
'__ln_s': 'ln -s',
'__make': '/usr/bin/make',
'__mkdir': '/bin/mkdir',
'__mkdir_p': '/bin/mkdir -p',
'__mv': '/bin/mv',
'__nm': '/usr/bin/nm',
'__objcopy': '%{_bindir}/objcopy',
'__objdump': '%{_bindir}/objdump',
'__patch': '/usr/bin/patch',
'__perl': 'perl',
'__perl_provides': '%{_usrlibrpm}/perl.prov',
'__perl_requires': '%{_usrlibrpm}/perl.req',
'__ranlib': 'ranlib',
'__remsh': '%{__rsh}',
'__rm': '/bin/rm',
'__rsh': '/usr/bin/rsh',
'__sed': '/usr/bin/sed',
'__setup_post': '%{__chmod} -R a+rX,g-w,o-w .',
'__sh': '/bin/sh',
'__tar': '/usr/bin/tar',
'__tar_extract': '%{__tar} -xvvf',
'__unzip': '/usr/bin/unzip',
'_datadir': '%{_prefix}/share',
'_defaultdocdir': '%{_prefix}/share/doc',
'_exeext': '',
'_exec_prefix': '%{_prefix}',
'_lib': 'lib',
'_libdir': '%{_exec_prefix}/%{_lib}',
'_libexecdir': '%{_exec_prefix}/libexec',
'_localedir': '%{_datadir}/locale',
'_localstatedir': '%{_prefix}/var',
'_usr': '/usr/local',
'_usrsrc': '%{_usr}/src',
'_var': '/usr/local/var',
'_varrun': '%{_var}/run',
'nil': ''
}
class command_line:
"""Process the command line in a common way across all speculater commands."""
_defaults = { 'params' : [],
'warn-all' : '0',
'quiet' : '0',
'trace' : '0',
'dry-run' : '0',
'no-clean' : '0' }
_long_opts = { '--prefix' : '_prefix',
'--prefixbase' : '_prefixbase',
'--topdir' : '_topdir',
'--specdir' : '_specdir',
'--builddir' : '_builddir',
'--sourcedir' : '_sourcedir',
'--usrlibrpm' : '_usrlibrpm',
'--tmppath' : '_tmppath',
'--log' : '_logfile',
'--url' : '_url_base' }
_long_true_opts = { '--trace' : '_trace',
'--warn-all' : '_warn_all',
'--no-clean' : '_no_clean' }
_target_triplets = { '--host' : '_host',
'--build' : '_build',
'--target' : '_target' }
def __init__(self, argv):
self.command_path = os.path.dirname(argv[0])
if len(self.command_path) == 0:
self.command_path = '.'
self.command_name = os.path.basename(argv[0])
self.args = argv[1:]
self.defaults = {}
for to in command_line._long_true_opts:
self.defaults[command_line._long_true_opts[to]] = '0'
self._process()
def __str__(self):
def _dict(dd):
s = ''
ddl = dd.keys()
ddl.sort()
for d in ddl:
s += ' ' + d + ': ' + str(dd[d]) + '\n'
return s
s = 'command: ' + self.command() + \
'\nargs: ' + str(self.args) + \
'\nopts:\n' + _dict(self.opts)
return s
def _expand(self, s, _defaults):
"""Simple basic expander of spec file macros."""
mf = re.compile(r'%{[^}]+}')
expanded = True
while expanded:
expanded = False
for m in mf.findall(s):
name = m[2:-1]
if name in _defaults:
s = s.replace(m, _defaults[name])
expanded = True
else:
raise error.general('cannot process default macro: ' + m)
return s
def _process(self):
def _process_lopt(opt, arg, long_opts, args, values = False):
for lo in long_opts:
if values and opt.startswith(lo):
equals = opt.find('=')
if equals < 0:
if arg == len(args) - 1:
raise error.general('missing option value: ' + lo)
arg += 1
value = args[arg]
else:
value = opt[equals + 1:]
return lo, long_opts[lo], value, arg
elif opt == lo:
return lo, long_opts[lo], True, arg
return None, None, None, arg
self.opts = command_line._defaults
i = 0
while i < len(self.args):
a = self.args[i]
if a.startswith('-'):
if a.startswith('--'):
if a.startswith('--warn-all'):
self.opts['warn-all'] = True
else:
lo, macro, value, i = _process_lopt(a, i,
command_line._long_true_opts,
self.args)
if lo:
self.defaults[macro] = '1'
self.opts[lo[2:]] = '1'
else:
lo, macro, value, i = _process_lopt(a, i,
command_line._long_opts,
self.args, True)
if lo:
self.defaults[macro] = value
self.opts[lo[2:]] = value
else:
#
# The target triplet is 'cpu-vendor-os'.
#
lo, macro, value, i = _process_lopt(a, i,
command_line._target_triplets,
self.args, True)
if lo:
#
# This is a target triplet. Run it past config.sub to make
# make sure it is ok.
#
e = execute.capture_execution()
config_sub = os.path.join(self.command_path, 'config.sub')
exit_code, proc, output = e.shell(config_sub + ' ' + value)
if exit_code == 0:
value = output
self.defaults[macro] = value
self.opts[lo[2:]] = value
_arch = macro + '_cpu'
_vendor = macro + '_vendor'
_os = macro + '_os'
_arch_value = ''
_vendor_value = ''
_os_value = ''
dash = value.find('-')
if dash >= 0:
_arch_value = value[:dash]
value = value[dash + 1:]
dash = value.find('-')
if dash >= 0:
_vendor_value = value[:dash]
value = value[dash + 1:]
if len(value):
_os_value = value
self.defaults[_arch] = _arch_value
self.defaults[_vendor] = _vendor_value
self.defaults[_os] = _os_value
if not lo:
raise error.general('invalid argument: ' + a)
else:
if a == '-n':
self.opts['dry-run'] = '1'
elif a == '-q':
self.opts['quiet'] = '1'
else:
self.opts['params'].append(a)
i += 1
def _post_process(self, _defaults):
pass
def command(self):
return os.path.join(self.command_path, self.command_name)
def dry_run(self):
return self.opts['dry-run'] != '0'
def quiet(self):
return self.opts['quiet'] != '0'
def trace(self):
return self.opts['trace'] != '0'
def warn_all(self):
return self.opts['warn-all'] != '0'
def no_clean(self):
return self.opts['no-clean'] != '0'
def params(self):
return self.opts['params']
def get_spec_files(self, spec):
if spec.find('*') >= 0 or spec.find('?'):
specdir = os.path.dirname(spec)
specbase = os.path.basename(spec)
if len(specbase) == 0:
specbase = '*'
if len(specdir) == 0:
specdir = self._expand(defaults['_specdir'], defaults)
if not os.path.isdir(specdir):
raise error.general('specdir is not a directory or does not exist: ' + specdir)
files = glob.glob(os.path.join(specdir, specbase))
specs = files
else:
specs = [spec]
return specs
def spec_files(self):
specs = []
for spec in self.opts['params']:
specs.extend(self.get_spec_files(spec))
return specs
def logfiles(self):
if 'log' in self.opts:
return self.opts['log'].split(',')
return ['stdout']
def urls(self):
if 'url' in self.opts:
return self.opts['url'].split(',')
return None
def prefixbase(self):
if 'prefixbase' in self.opts:
return self.opts['prefixbase']
return None
def load(args):
"""
Copy the defaults, get the host specific values and merge
them overriding any matching defaults, then create an options
object to handle the command line merging in any command line
overrides. Finally post process the command line.
"""
d = defaults
overrides = None
uname = os.uname()
if uname[0] == 'Darwin':
import darwin
overrides = darwin.load()
for k in overrides:
d[k] = overrides[k]
o = command_line(args)
for k in o.defaults:
d[k] = o.defaults[k]
o._post_process(d)
return o, d
if __name__ == '__main__':
import sys
try:
_opts, _defaults = load(args = sys.argv)
print _opts
pprint.pprint(_defaults)
except error.general, gerr:
print gerr
sys.exit(1)
except error.internal, ierr:
print ierr
sys.exit(1)
sys.exit(0)

View File

@ -0,0 +1,53 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# Various errors we can raise.
#
class error(Exception):
"""Base class for Builder exceptions."""
def set_output(self, msg):
self.msg = msg
def __str__(self):
return self.msg
class general(error):
"""Raise for a general error."""
def __init__(self, what):
self.set_output('error: ' + what)
class internal(error):
"""Raise for an internal error."""
def __init__(self, what):
self.set_output('internal error: ' + what)
if __name__ == '__main__':
try:
raise general('a general error')
except general, gerr:
print 'caught:', gerr
try:
raise internal('an internal error')
except internal, ierr:
print 'caught:', ierr

View File

@ -0,0 +1,367 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# Execute commands or scripts.
#
# Note, the subprocess module is only in Python 2.4 or higher.
#
import os
import re
import sys
import subprocess
import threading
import error
import log
# Redefine the PIPE from subprocess
PIPE = subprocess.PIPE
# Regular expression to find quotes.
qstr = re.compile('[rR]?\'([^\\n\'\\\\]|\\\\.)*\'|[rR]?"([^\\n"\\\\]|\\\\.)*"')
def check_type(command):
"""Checks the type of command we have. The types are spawn and
shell."""
if command in ['spawn', 'shell']:
return True
return False
def arg_list(args):
"""Turn a string of arguments into a list suitable for
spawning a command. If the args are already a list return
it."""
if type(args) is list:
return args
argstr = args
args = []
while len(argstr):
qs = qstr.search(argstr)
if not qs:
args.extend(argstr.split())
argstr= ''
else:
# We have a quoted string. Get the string before
# the quoted string and spltt on white space then
# add the quoted string as an option then remove
# the first + quoted string and try again
front = argstr[:qs.start()]
args.extend(front.split())
args.append(argstr[qs.start() + 1:qs.end() - 1])
argstr = argstr[qs.end():]
return args
def arg_subst(command, substs):
"""Substitute the %[0-9] in the command with the subst values."""
args = arg_list(command)
if substs:
for a in range(0, len(args)):
for r in range(0, len(substs)):
args[a] = re.compile(('%%%d' % (r))).sub(substs[r], args[a])
return args
def arg_subst_str(command, subst):
cmd = arg_subst(command, subst)
def add(x, y): return x + ' ' + str(y)
return reduce(add, cmd, '')
class execute:
"""Execute commands or scripts. The 'output' is a funtion
that handles the output from the process."""
def __init__(self, output = None, error_prefix = '', verbose = False):
self.output = output
self.error_prefix = error_prefix
self.verbose = verbose
self.shell_exe = None
self.shell_commands = False
self.path = None
self.environment = None
def capture(self, proc, timeout = None):
"""Create 2 threads to read stdout and stderr and send to the
output handler. Based on the 'communicate' code in the subprocess
module."""
def _readthread(fh, out, prefix = ''):
"""Read from a file handle and write to the output handler
until the file closes."""
while True:
line = fh.readline()
if len(line) == 0:
break
if out:
out(prefix + line)
else:
log.output(prefix + line)
def _timerthread(proc, timer):
"""Timer thread calls the timer handler if one
is present once a second. The user provides a handler
and returns False to kill the process or True continue."""
while True:
time.sleep(1)
if not timer(proc):
proc.stdout.close()
proc.stderr.close()
if proc.stdout:
stdout_thread = threading.Thread(target = _readthread,
args = (proc.stdout,
self.output,
''))
stdout_thread.setDaemon(True)
stdout_thread.start()
if proc.stderr:
stderr_thread = threading.Thread(target = _readthread,
args = (proc.stderr,
self.output,
self.error_prefix))
stderr_thread.setDaemon(True)
stderr_thread.start()
if proc.stdout:
stdout_thread.join()
if proc.stderr:
stderr_thread.join()
return proc.wait()
def open(self, command, capture = True, shell = False,
cwd = None, env = None,
stdin = None, stdout = None, stderr = None):
"""Open a command with arguments. Provide the arguments as a list or
a string."""
if self.verbose:
s = command
if type(command) is list:
def add(x, y): return x + ' ' + str(y)
s = reduce(add, command, '')[1:]
what = 'spawn'
if shell:
what = 'shell'
log.output(what + ': ' + s)
if shell and self.shell_exe:
command = arg_list(command)
command[:0] = self.shell_exe
if not stdout:
stdout = subprocess.PIPE
if not stderr:
stderr = subprocess.PIPE
proc = None
if cwd is None:
cwd = self.path
if env is None:
env = self.environment
try:
# Work around a problem on Windows with commands that
# have a '.' and no extension. Windows needs the full
# command name.
if sys.platform == "win32" and type(command) is list:
if command[0].find('.') >= 0:
r, e = os.path.splitext(command[0])
if e not in ['.exe', '.com', '.bat']:
command[0] = command[0] + '.exe'
proc = subprocess.Popen(command, shell = shell,
cwd = cwd, env = env,
stdin = stdin, stdout = stdout,
stderr = stderr)
if not capture:
return (0, proc)
exit_code = self.capture(proc)
if self.verbose:
log.output('exit: ' + str(exit_code))
except OSError, ose:
exit_code = ose.errno
if self.verbose:
log.output('exit: ' + str(ose))
return (exit_code, proc)
def spawn(self, command, capture = True, cwd = None, env = None,
stdin = None, stdout = None, stderr = None):
"""Spawn a command with arguments. Provide the arguments as a list or
a string."""
return self.open(command, capture, False, cwd, env,
stdin, stdout, stderr)
def shell(self, command, capture = True, cwd = None, env = None,
stdin = None, stdout = None, stderr = None):
"""Execute a command within a shell context. The command can contain
argumments. The shell is specific to the operating system. For example
it is cmd.exe on Windows XP."""
return self.open(command, capture, True, cwd, env,
stdin, stdout, stderr)
def command(self, command, args = None, capture = True, shell = False,
cwd = None, env = None,
stdin = None, stdout = None, stderr = None):
"""Run the command with the args. The args can be a list
or a string."""
if args and not type(args) is list:
args = arg_list(args)
cmd = [command]
if args:
cmd.extend(args)
return self.open(cmd, capture = capture, shell = shell,
cwd = cwd, env = env,
stdin = stdin, stdout = stdout, stderr = stderr)
def command_subst(self, command, substs, capture = True, shell = False,
cwd = None, env = None,
stdin = None, stdout = None, stderr = None):
"""Run the command from the config data with the
option format string subsituted with the subst variables."""
args = arg_subst(command, substs)
return self.command(args[0], args[1:], capture = capture,
shell = shell or self.shell_commands,
cwd = cwd, env = env,
stdin = stdin, stdout = stdout, stderr = stderr)
def set_shell(self, execute):
"""Set the shell to execute when issuing a shell command."""
args = arg_list(execute)
if len(args) == 0 or not os.path.isfile(args[0]):
raise error.general('could find shell: ' + execute)
self.shell_exe = args
def command_use_shell(self):
"""Force all commands to use a shell. This can be used with set_shell
to allow Unix commands be executed on Windows with a Unix shell such
as Cygwin or MSYS. This may cause piping to fail."""
self.shell_commands = True
def set_output(self, output):
"""Set the output handler. The stdout of the last process in a pipe
line is passed to this handler."""
old_output = self.output
self.output = output
return old_output
def set_path(self, path):
"""Set the path changed to before the child process is created."""
old_path = self.path
self.path = path
return old_path
def set_environ(self, environment):
"""Set the environment passed to the child process when created."""
old_environment = self.environment
self.environment = environment
return old_environment
class capture_execution(execute):
"""Capture all output as a string and return it."""
class _output_snapper:
def __init__(self, log = None, dump = False):
self.output = ''
self.log = log
self.dump = dump
def handler(self, text):
if not self.dump:
if self.log is not None:
self.log.output(text)
else:
self.output += text
def get_and_clear(self):
text = self.output
self.output = ''
return text.strip()
def __init__(self, log = None, dump = False, error_prefix = '', verbose = False):
self.snapper = capture_execution._output_snapper(log = log, dump = dump)
execute.__init__(self, output = self.snapper.handler,
error_prefix = error_prefix,
verbose = verbose)
def open(self, command, capture = True, shell = False, cwd = None, env = None,
stdin = None, stdout = None, stderr = None):
if not capture:
raise error.general('output capture must be true; leave as default')
#self.snapper.get_and_clear()
exit_code, proc = execute.open(self, command, capture = True, shell = shell,
cwd = cwd, env = env,
stdin = stdin, stdout = stdout, stderr = stderr)
return (exit_code, proc, self.snapper.get_and_clear())
def set_output(self, output):
raise error.general('output capture cannot be overrided')
if __name__ == "__main__":
def run_tests(e, commands, use_shell):
for c in commands['shell']:
e.shell(c)
for c in commands['spawn']:
e.spawn(c)
for c in commands['cmd']:
if type(c) is str:
e.command(c, shell = use_shell)
else:
e.command(c[0], c[1], shell = use_shell)
for c in commands['csubsts']:
e.command_subst(c[0], c[1], shell = use_shell)
ec, proc = e.command(commands['pipe'][0], commands['pipe'][1],
capture = False, stdin = subprocess.PIPE)
if ec == 0:
print 'piping input into ' + commands['pipe'][0] + ': ' + \
commands['pipe'][2]
proc.stdin.write(commands['pipe'][2])
proc.stdin.close()
e.capture(proc)
del proc
cmd_shell_test = 'if "%OS%" == "Windows_NT" (echo It is WinNT) else echo Is is not WinNT'
sh_shell_test = 'x="me"; if [ $x = "me" ]; then echo "It was me"; else "It was him"; fi'
commands = {}
commands['windows'] = {}
commands['unix'] = {}
commands['windows']['shell'] = ['cd', 'dir /w', '.\\xyz', cmd_shell_test]
commands['windows']['spawn'] = ['hostname', 'hostnameZZ', ['netstat', '/e']]
commands['windows']['cmd'] = [('ipconfig'), ('nslookup', 'www.python.org')]
commands['windows']['csubsts'] = [('netstat %0', ['-a']),
('netstat %0 %1', ['-a', '-n'])]
commands['windows']['pipe'] = ('ftp', None, 'help\nquit')
commands['unix']['shell'] = ['pwd', 'ls -las', './xyz', sh_shell_test]
commands['unix']['spawn'] = ['ls', 'execute.pyc', ['ls', '-i']]
commands['unix']['cmd'] = [('date'), ('date', '-R'), ('date', ['-u', '+%d %D']),
('date', '-u "+%d %D %S"')]
commands['unix']['csubsts'] = [('date %0 "+%d %D %S"', ['-u']),
('date %0 %1', ['-u', '+%d %D %S'])]
commands['unix']['pipe'] = ('grep', 'hello', 'hello world')
print arg_list('cmd a1 a2 "a3 is a string" a4')
print arg_list('cmd b1 b2 "b3 is a string a4')
print arg_subst(['nothing', 'xx-%0-yyy', '%1', '%2-something'],
['subst0', 'subst1', 'subst2'])
e = execute(error_prefix = 'ERR: ', verbose = True)
if sys.platform == "win32":
run_tests(e, commands['windows'], False)
if os.path.exists('c:\\msys\\1.0\\bin\\sh.exe'):
e.set_shell('c:\\msys\\1.0\\bin\\sh.exe --login -c')
commands['unix']['pipe'] = ('c:\\msys\\1.0\\bin\\grep',
'hello', 'hello world')
run_tests(e, commands['unix'], True)
else:
run_tests(e, commands['unix'], False)
del e

115
specbuilder/specbuilder/log.py Executable file
View File

@ -0,0 +1,115 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-testing'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# Log output to stdout and/or a file.
#
import os
import sys
import error
#
# A global log.
#
default = None
def set_default_once(log):
if default is None:
default = log
def output(text = os.linesep, log = None):
"""Output the text to a log if provided else send it to stdout."""
if text is None:
text = os.linesep
if type(text) is list:
_text = ''
for l in text:
_text += l + os.linesep
text = _text
if log:
log.output(text)
elif default is not None:
default.output(text)
else:
for l in text.replace(chr(13), '').splitlines():
print l
def flush(log = None):
if log:
log.flush()
elif default is not None:
default.flush()
class log:
"""Log output to stdout or a file."""
def __init__(self, streams = None):
self.fhs = [None, None]
if streams:
for s in streams:
if s == 'stdout':
self.fhs[0] = sys.stdout
elif s == 'stderr':
self.fhs[1] = sys.stderr
else:
try:
self.fhs.append(file(s, 'w'))
except IOError, ioe:
raise error.general("creating log file '" + s + \
"': " + str(ioe))
def __del__(self):
for f in range(2, len(self.fhs)):
self.fhs[f].close()
def has_stdout(self):
return self.fhs[0] is not None
def has_stderr(self):
return self.fhs[1] is not None
def output(self, text):
"""Output the text message to all the logs."""
# Reformat the text to have local line types.
out = ''
for l in text.replace(chr(13), '').splitlines():
out += l + os.linesep
for f in range(0, len(self.fhs)):
if self.fhs[f] is not None:
self.fhs[f].write(out)
def flush(self):
"""Flush the output."""
for f in range(0, len(self.fhs)):
if self.fhs[f] is not None:
self.fhs[f].flush()
if __name__ == "__main__":
l = log(['stdout', 'log.txt'])
for i in range(0, 10):
l.output('hello world: %d\n' % (i))
l.output('hello world CRLF\r\n')
l.output('hello world NONE')
l.flush()
del l

View File

@ -0,0 +1,101 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# Setup a series of directories ready for building with the Spec Builder.
#
import os
import shutil
import build
import defaults
import error
import log
#
# Version of Spec CrossGCC Builder.
#
version = '0.1'
def _notice(opts, text):
if not opts.quiet() and not log.default.has_stdout():
print text
log.output(text)
log.flush()
class setup:
"""Set up the various directories in a specified path"""
_dirs = [ 'TARS',
'TARS',
'SPECS',
'SOURCE',
'RPMLIB',
'BUILD',
'TMP' ]
def __init__(self, path, _defaults, opts):
self.path = path
self.opts = opts
self.defaults = _defaults
def _output(self, text):
if not self.opts.quiet():
log.output(text)
def mkdir(self, path):
if not self.opts.dry_run():
self._output('making dir: ' + path)
try:
os.makedirs(path)
except IOError, err:
raise error.general('error creating path: ' + path)
def make(self, path):
for d in setup._dirs:
self.mkdir(os.path.join(path, d))
def run():
import sys
try:
opts, _defaults = defaults.load(sys.argv)
log.default = log.log(opts.logfiles())
_notice(opts, 'RTEMS Tools, Setup Spec Builder, v%s' % (version))
for path in opts.params():
s = setup(path, _defaults = _defaults, opts = opts)
s.make()
del s
except error.general, gerr:
print gerr
sys.exit(1)
except error.internal, ierr:
print ierr
sys.exit(1)
except KeyboardInterrupt:
print 'user terminated'
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
run()

View File

@ -0,0 +1,760 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# This code is based on what ever doco about spec files I could find and
# RTEMS project's spec files. It parses a spec file into Python data types
# that can be used by other software modules.
#
import os
import re
import sys
import defaults
import error
import execute
import log
debug = False
class package:
def __init__(self, name, arch):
self._name = name
self._arch = arch
self.directives = {}
self.infos = {}
def __str__(self):
def _dictlist(dl):
s = ''
dll = dl.keys()
dll.sort()
for d in dll:
s += ' ' + d + ':\n'
for l in dl[d]:
s += ' ' + l + '\n'
return s
s = '\npackage: ' + self._name + \
'\n directives:\n' + _dictlist(self.directives) + \
'\n infos:\n' + _dictlist(self.infos)
return s
def get_info(self, info):
if not info in self.infos:
raise error.general('no ' + info + ' in package "' + self.name + '"')
return self.info
def version(self):
return self.get_info('Version')
def extract_info(self, label):
infos = {}
for i in self.infos:
il = i.lower()
if il.startswith(label) and il[len(label):].isdigit():
infos[il] = self.infos[i]
return infos
def find_info(self, label):
for i in self.infos:
if i.lower() == label:
return self.infos[i]
return None
def find_directive(self, label):
for d in self.directives:
if d.lower() == label:
return self.directives[d]
return None
def name(self):
info = self.find_info('name')
if info:
return info[0]
return self._name
def version(self):
info = self.find_info('version')
if not info:
return None
return info[0]
def release(self):
info = self.find_info('release')
if not info:
return None
return info[0]
def buildarch(self):
info = self.find_info('buildarch')
if not info:
return self._arch
return info[0]
def sources(self):
return self.extract_info('source');
def patches(self):
return self.extract_info('patch')
def prep(self):
return self.find_directive('%prep')
def build(self):
return self.find_directive('%build')
def install(self):
return self.find_directive('%install')
def clean(self):
return self.find_directive('%clean')
def post(self):
return self.find_directive('%post')
def long_name(self):
buildarch = self.buildarch()
return '-'.join([self.name(), self.version(), self.release()]) + \
'.' + buildarch
class file:
"""Parse a spec file."""
_directive = [ '%description',
'%prep',
'%build',
'%install',
'%clean',
'%post',
'%preun',
'%files' ]
_ignore = [ re.compile('%setup'),
re.compile('%doc'),
re.compile('%dir'),
re.compile('%ghost'),
re.compile('%exclude'),
re.compile('%source[0-9]*'),
re.compile('%patch[0-9]*'),
re.compile('%__os_install_post') ]
def __init__(self, name, _defaults, opts):
self.opts = opts
self.specpath = 'not set'
self.wss = re.compile(r'\s+')
self.tags = re.compile(r':+')
self.sf = re.compile(r'%\([^\)]+\)')
self.default_defines = {}
for d in _defaults:
self.default_defines[self._label(d)] = _defaults[d]
for arg in self.opts.args:
if arg.startswith('--with-') or arg.startswith('--without-'):
label = arg[2:].lower().replace('-', '_')
self.default_defines[self._label(label)] = label
self.load(name)
def __str__(self):
def _dict(dd):
s = ''
ddl = dd.keys()
ddl.sort()
for d in ddl:
s += ' ' + d + ': ' + dd[d] + '\n'
return s
s = 'spec: %s' % (self.specpath) + \
'\n' + str(self.opts) + \
'\nlines parsed: %d' % (self.lc) + \
'\nname: ' + self.name + \
'\ndefines:\n' + _dict(self.defines)
for _package in self._packages:
s += str(self._packages[_package])
return s
def _output(self, text):
if not self.opts.quiet():
log.output(text)
def _warning(self, msg):
self._output('warning: ' + self.name + ':' + str(self.lc) + ': ' + msg)
def _error(self, msg):
print >> sys.stderr, \
'error: ' + self.name + ':' + str(self.lc) + ': ' + msg
self.in_error = True
def _label(self, name):
return '%{' + name.lower() + '}'
def _macro_split(self, s):
'''Split the string (s) up by macros. Only split on the
outter level. Nested levels will need to split with futher calls.'''
trace_me = False
macros = []
nesting = []
has_braces = False
c = 0
while c < len(s):
if trace_me:
print 'ms:', c, '"' + s[c:] + '"', has_braces, len(nesting), nesting
#
# We need to watch for shell type variables or the form '${var}' because
# they can upset the brace matching.
#
if s[c] == '%' or s[c] == '$':
start = s[c]
c += 1
if c == len(s):
continue
#
# Do we have '%%' or '%(' or '$%' or '$(' or not '${' ?
#
if s[c] == '%' or s[c] == '(' or (start == '$' and s[c] != '{'):
continue
elif not s[c].isspace():
#
# If this is a shell macro and we are at the outter
# level or is '$var' forget it and move on.
#
if start == '$' and (s[c] != '{' or len(nesting) == 0):
continue
if s[c] == '{':
this_has_braces = True
else:
this_has_braces = False
nesting.append((c - 1, has_braces))
has_braces = this_has_braces
elif len(nesting) > 0:
if s[c] == '}' or (s[c].isspace() and not has_braces):
#
# Can have '%{?test: something %more}' where the
# nested %more ends with the '}' which also ends
# the outter macro.
#
if not has_braces:
if s[c] == '}':
macro_start, has_braces = nesting[len(nesting) - 1]
nesting = nesting[:-1]
if len(nesting) == 0:
macros.append(s[macro_start:c].strip())
if len(nesting) > 0:
macro_start, has_braces = nesting[len(nesting) - 1]
nesting = nesting[:-1]
if len(nesting) == 0:
macros.append(s[macro_start:c + 1].strip())
c += 1
if trace_me:
print 'ms:', macros
return macros
def _shell(self, line):
sl = self.sf.findall(line)
if len(sl):
e = execute.capture_execution()
for s in sl:
exit_code, proc, output = e.shell(s[2:-1])
if exit_code == 0:
line = line.replace(s, output)
else:
raise error.general('shell macro failed: ' + s + ': ' + output)
return line
def _expand(self, s):
expanded = True
while expanded:
expanded = False
ms = self._macro_split(s)
for m in ms:
mn = m
#
# A macro can be '%{macro}' or '%macro'. Turn the later into
# the former.
#
show_warning = True
if mn[1] != '{':
for r in self._ignore:
if r.match(mn) is not None:
mn = None
break
else:
mn = self._label(mn[1:])
show_warning = False
elif m.startswith('%{expand'):
colon = m.find(':')
if colon < 8:
self._warning('malformed expand macro, no colon found')
else:
e = self._expand(m[colon + 1:-1].strip())
s = s.replace(m, e)
expanded = True
mn = None
elif m.startswith('%{with '):
#
# Change the ' ' to '_' because the macros have no spaces.
#
n = self._label('with_' + m[7:-1].strip())
if n in self.defines:
s = s.replace(m, '1')
else:
s = s.replace(m, '0')
expanded = True
mn = None
elif m.startswith('%{echo'):
mn = None
elif m.startswith('%{defined'):
n = self._label(m[9:-1].strip())
if n in self.defines:
s = s.replace(m, '1')
else:
s = s.replace(m, '0')
expanded = True
mn = None
elif m.startswith('%{?') or m.startswith('%{!?'):
if m[2] == '!':
start = 4
else:
start = 3
colon = m[start:].find(':')
if colon < 0:
if not m.endswith('}'):
self._warning("malform conditional macro'" + m)
mn = None
else:
mn = self._label(m[start:-1])
else:
mn = self._label(m[start:start + colon])
if mn:
if m.startswith('%{?'):
if mn in self.defines:
if colon >= 0:
s = s.replace(m, m[start + colon + 1:-1])
expanded = True
mn = None
else:
mn = '%{nil}'
else:
if mn not in self.defines:
if colon >= 0:
s = s.replace(m, m[start + colon + 1:-1])
expanded = True
mn = None
else:
mn = '%{nil}'
if mn:
if mn.lower() in self.defines:
s = s.replace(m, self.defines[mn.lower()])
expanded = True
elif show_warning:
self._error("macro '" + mn + "' not found")
return self._shell(s)
def _define(self, spec, ls):
if len(ls) <= 1:
self._warning('invalid macro definition')
else:
d = self._label(ls[1])
if d not in self.defines:
if len(ls) == 2:
self.defines[d] = '1'
else:
self.defines[d] = ls[2].strip()
else:
if self.opts.warn_all():
self._warning("macro '" + d + "' already defined")
def _undefine(self, spec, ls):
if len(ls) <= 1:
self._warning('invalid macro definition')
else:
mn = self._label(ls[1])
if mn in self.defines:
self._error("macro '" + mn + "' not defined")
del self.defines[mn]
def _ifs(self, spec, ls, label, iftrue, isvalid):
text = []
in_iftrue = True
while True:
if isvalid and \
((iftrue and in_iftrue) or (not iftrue and not in_iftrue)):
this_isvalid = True
else:
this_isvalid = False
r = self._parse(spec, roc = True, isvalid = this_isvalid)
if r[0] == 'control':
if r[1] == '%end':
self._error(label + ' without %endif')
if r[1] == '%endif':
return text
if r[1] == '%else':
in_iftrue = False
elif r[0] == 'data':
if this_isvalid:
text.extend(r[1])
def _if(self, spec, ls, isvalid):
global debug
def add(x, y):
return x + ' ' + str(y)
def check_bool(value):
if value.isdigit():
if int(value) == 0:
istrue = False
else:
istrue = True
else:
istrue = None
return istrue
istrue = False
if isvalid:
if len(ls) == 2:
s = ls[1]
else:
s = (ls[1] + ' ' + ls[2])
ifls = s.split()
if len(ifls) == 1:
istrue = check_bool(ifls[0])
if istrue == None:
self._error('invalid if bool value: ' + reduce(add, ls, ''))
istrue = False
elif len(ifls) == 2:
if ifls[0] == '!':
istrue = check_bool(ifls[1])
if istrue == None:
self._error('invalid if bool value: ' + reduce(add, ls, ''))
istrue = False
else:
istrue = not istrue
else:
self._error('invalid if bool operator: ' + reduce(add, ls, ''))
elif len(ifls) == 3:
if ifls[1] == '==':
if ifls[0] == ifls[2]:
istrue = True
else:
istrue = False
elif ifls[1] == '!=' or ifls[1] == '=!':
if ifls[0] != ifls[2]:
istrue = True
else:
istrue = False
elif ifls[1] == '>':
if ifls[0] > ifls[2]:
istrue = True
else:
istrue = False
elif ifls[1] == '>=' or ifls[1] == '=>':
if ifls[0] >= ifls[2]:
istrue = True
else:
istrue = False
elif ifls[1] == '<=' or ifls[1] == '=<':
if ifls[0] <= ifls[2]:
istrue = True
else:
istrue = False
elif ifls[1] == '<':
if ifls[0] < ifls[2]:
istrue = True
else:
istrue = False
else:
self._error('invalid %if operator: ' + reduce(add, ls, ''))
else:
self._error('malformed if: ' + reduce(add, ls, ''))
if debug:
print '_if: ', ifls, istrue
return self._ifs(spec, ls, '%if', istrue, isvalid)
def _ifos(self, spec, ls, isvalid):
isos = False
if isvalid:
os = self.define('_os')
if ls[0].find(os) >= 0 or ls[1].find(os) >= 0:
isos = True
else:
isos = False
return self._ifs(spec, ls, '%ifos', isos, isvalid)
def _ifarch(self, spec, positive, ls, isvalid):
isarch = False
if isvalid:
arch = self.define('_arch')
if ls[0].find(arch) >= 0 or ls[1].find(arch) >= 0:
isarch = True
else:
isarch = False
if not positive:
isarch = not isarch
return self._ifs(spec, ls, '%ifarch', isarch, isvalid)
def _parse(self, spec, roc = False, isvalid = True):
# roc = return on control
global debug
def _clean(line):
line = line[0:-1]
b = line.find('#')
if b >= 0:
line = line[1:b]
return line.strip()
#
# Need to add code to count matching '{' and '}' and if they
# do not match get the next line and add to the string until
# they match. This closes an opening '{' that is on another
# line.
#
for l in spec:
self.lc += 1
l = _clean(l)
if len(l) == 0:
continue
if debug:
print '%03d: %d %s' % (self.lc, isvalid, l)
if isvalid:
l = self._expand(l)
if len(l) == 0:
continue
if l[0] == '%':
ls = self.wss.split(l, 2)
if ls[0] == '%package':
if isvalid:
if ls[1] == '-n':
name = ls[2]
else:
name = self.name + '-' + ls[1]
return ('package', name)
elif ls[0] == '%define' or ls[0] == '%global':
if isvalid:
self._define(spec, ls)
elif ls[0] == '%undefine':
if isvalid:
self._undefine(spec, ls)
elif ls[0] == '%if':
d = self._if(spec, ls, isvalid)
if len(d):
return ('data', d)
elif ls[0] == '%ifos':
d = self._ifos(spec, ls, isvalid)
if len(d):
return ('data', d)
elif ls[0] == '%ifarch':
d = self._ifarch(spec, True, ls, isvalid)
if len(d):
return ('data', d)
elif ls[0] == '%ifnarch':
d = self._ifarch(spec, False, ls, isvalid)
if len(d):
return ('data', d)
elif ls[0] == '%endif':
if roc:
return ('control', '%endif')
self._warning("unexpected '" + ls[0] + "'")
elif ls[0] == '%else':
if roc:
return ('control', '%else')
self._warning("unexpected '" + ls[0] + "'")
elif ls[0].startswith('%defattr'):
return ('data', [l])
elif ls[0] == '%bcond_with':
if isvalid:
#
# Check is already defined. Would be by the command line or
# even a host specific default.
#
if self._label('with_' + ls[1]) not in self.defines:
self._define(spec, (ls[0], 'without_' + ls[1]))
elif ls[0] == '%bcond_without':
if isvalid:
if self._label('without_' + ls[1]) not in self.defines:
self._define(spec, (ls[0], 'with_' + ls[1]))
else:
for r in self._ignore:
if r.match(ls[0]) is not None:
return ('data', [l])
if isvalid:
for d in self._directive:
if ls[0].strip() == d:
if len(ls) == 1:
package = 'main'
elif len(ls) == 2:
package = ls[1].strip()
else:
if ls[1].strip() != '-n':
self._warning("unknown directive option: '" + ls[1] + "'")
package = ls[2].strip()
return ('directive', ls[0].strip(), package)
self._warning("unknown directive: '" + ls[0] + "'")
return ('data', [l])
else:
return ('data', [l])
return ('control', '%end')
def _set_package(self, _package):
if self.package == 'main' and \
self._packages[self.package].name() != None:
if self._packages[self.package].name() == _package:
return
if _package not in self._packages:
self._packages[_package] = package(_package,
self.define('%{_arch}'))
self.package = _package
def _directive_extend(self, dir, data):
if dir not in self._packages[self.package].directives:
self._packages[self.package].directives[dir] = []
for i in range(0, len(data)):
data[i] = data[i].strip()
self._packages[self.package].directives[dir].extend(data)
def _info_append(self, info, data):
if info not in self._packages[self.package].infos:
self._packages[self.package].infos[info] = []
self._packages[self.package].infos[info].append(data)
def load(self, name):
global debug
self.in_error = False
self.name = name
self.lc = 0
self.defines = self.default_defines
self.conditionals = {}
self._packages = {}
self.package = 'main'
self._packages[self.package] = package(self.package,
self.define('%{_arch}'))
self.specpath = os.path.join(self.abspath('_specdir'), name)
if not os.path.exists(self.specpath):
raise error.general('no spec file found: ' + self.specpath)
try:
spec = open(self.specpath, 'r')
except IOError, err:
raise error.general('error opening spec file: ' + self.specpath)
try:
dir = None
data = []
while True:
r = self._parse(spec)
if r[0] == 'package':
self._set_package(r[1])
dir = None
elif r[0] == 'control':
if r[1] == '%end':
break
self._warning("unexpected '" + r[1] + "'")
elif r[0] == 'directive':
self._set_package(r[2])
if dir and dir != r[1]:
self._directive_extend(dir, data)
dir = r[1]
data = []
elif r[0] == 'data':
for l in r[1]:
l = self._expand(l)
if not dir:
ls = self.tags.split(l, 1)
if debug:
print '_tag: ', l, ls
if len(ls) > 1:
i = ls[0]
self._info_append(i, ls[1].strip())
# It seems like the info's also appear as
# defines or can be accessed via macros.
if ls[0][len(ls[0]) - 1] == ':':
ls[0] = ls[0][:-1]
ls[0] = ls[0].lower()
self._define(None, ('', ls[0], ls[1]))
else:
self._warning("invalid format: '" + l[:-1] + "'")
else:
data.append(l)
else:
self._error("invalid parse state: '" + r[0] + "'")
self._directive_extend(dir, data)
finally:
spec.close()
def define(self, name):
if name.lower() in self.defines:
d = self.defines[name.lower()]
else:
n = self._label(name)
if n in self.defines:
d = self.defines[n]
else:
raise error.general('macro "' + name + '" not found')
return self._expand(d)
def expand(self, line):
return self._expand(line)
def directive(self, _package, name):
if _package not in self._packages:
raise error.general('package "' + _package + '" not found')
if name not in self._packages[_package].directives:
raise error.general('directive "' + name + \
'" not found in package "' + _package + '"')
return self._packages[_package].directives[name]
def abspath(self, path):
return os.path.abspath(self.define(path))
def packages(self):
return self._packages
def run():
import sys
try:
opts, _defaults = defaults.load(sys.argv)
for spec_file in opts.spec_files():
s = file(spec_file, _defaults = _defaults, opts = opts)
print s
del s
except error.general, gerr:
print gerr
sys.exit(1)
except error.internal, ierr:
print ierr
sys.exit(1)
except KeyboardInterrupt:
print 'user terminated'
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
run()

View File

@ -0,0 +1,95 @@
#
# $Id$
#
# RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010 Chris Johns (chrisj@rtems.org)
# All rights reserved.
#
# This file is part of the RTEMS Tools package in 'rtems-tools'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# Extract the status of the spec files found in the SPECS directory.
# The status is the name, source and patches.
#
import os
import defaults
import error
import spec
class status:
"""Return the status of a package given a spec file."""
def __init__(self, name, _defaults, opts):
self.opts = opts
self.spec = spec.file(name, _defaults = _defaults, opts = opts)
def __str__(self):
def str_package(package):
sources = package.sources()
patches = package.patches()
version = package.version()
release = package.release()
buildarch = package.buildarch()
s = '\n name: ' + package.name()
if buildarch:
s += '\n arch: ' + buildarch
if version:
s += '\n version: ' + version
if release:
s += '\n release: ' + release
if len(sources):
s += '\n sources: %d' % (len(sources))
c = 1
for i in sources:
s += '\n %d: ' % (c) + sources[i][0]
c += 1
s += '\n patches: %d' % (len(patches))
c = 1
for i in patches:
s += '\n %d: ' % (c) + patches[i][0]
c += 1
return s
packages = self.spec.packages()
s = 'spec: ' + os.path.basename(self.spec.name) + \
str_package(packages['main'])
for p in packages:
if p != 'main':
s += str_package(packages[p])
return s
def run():
import sys
try:
opts, _defaults = defaults.load(sys.argv)
for spec_file in opts.spec_files():
s = status(spec_file, _defaults = _defaults, opts = opts)
print s
del s
except error.general, gerr:
print gerr
sys.exit(1)
except error.internal, ierr:
print ierr
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
run()