mirror of
https://git.rtems.org/rtems-source-builder
synced 2024-10-09 07:15:10 +08:00
Initial import.
This commit is contained in:
commit
bf13d27ab0
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*~
|
||||
*.pyc
|
34
config/base.cfg
Normal file
34
config/base.cfg
Normal file
@ -0,0 +1,34 @@
|
||||
#
|
||||
# Base set up for all configurations.
|
||||
#
|
||||
|
||||
# _prefix is set in the tool
|
||||
|
||||
%define _exec_prefix %{_prefix}
|
||||
%define _bindir %{_exec_prefix}/bin
|
||||
%define _sbindir %{_exec_prefix}/sbin
|
||||
%define _libexecdir %{_exec_prefix}/libexec
|
||||
%define _datarootdir %{_prefix}/share
|
||||
%define _datadir %{_datarootdir}
|
||||
%define _sysconfdir %{_prefix}/etc
|
||||
%define _sharedstatedir %{_prefix}/com
|
||||
%define _localstatedir %{_prefix}/var
|
||||
%define _includedir %{_prefix}/include
|
||||
%define _libdir %{_exec_prefix}/%{_lib}
|
||||
%define _mandir %{_datarootdir}/man
|
||||
%define _infodir %{_datarootdir}/info
|
||||
%define _localedir %{_datarootdir}/locale
|
||||
|
||||
%ifos mingw mingw32
|
||||
%define _exeext .exe
|
||||
%define debug_package %{nil}
|
||||
%define _libdir %{_exec_prefix}/lib
|
||||
%else
|
||||
%define _exeext %{nil}
|
||||
%endif
|
||||
|
||||
%if "%{_build}" != "%{_host}"
|
||||
%define _host_prefix %{_host}-
|
||||
%else
|
||||
%define _host_prefix %{nil}
|
||||
%endif
|
86
config/binutils-2-1.cfg
Normal file
86
config/binutils-2-1.cfg
Normal file
@ -0,0 +1,86 @@
|
||||
#
|
||||
# Binutils 2.xx Version 1.
|
||||
#
|
||||
# This configuration file configure's, make's and install's binutils.
|
||||
#
|
||||
|
||||
%include %{_configdir}/checks.cfg
|
||||
|
||||
Summary: Binutils v%{binutils_version} for target %{_target} on host %{_host}
|
||||
Version: %{binutils_version}
|
||||
Release: %{release}
|
||||
URL: http://sources.redhat.com/binutils
|
||||
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
|
||||
|
||||
#
|
||||
# Source
|
||||
#
|
||||
Source0: ftp://ftp.gnu.org/gnu/binutils/binutils-%{binutils_version}.tar.bz2
|
||||
|
||||
#
|
||||
# Prepare the source code.
|
||||
#
|
||||
%prep
|
||||
%setup -q -c -T -n %{name}-%{version}
|
||||
%setup -q -D -T -n %{name}-%{version} -a0
|
||||
cd binutils-%{binutils_version}
|
||||
%{?patch0:%patch0 -p1}
|
||||
cd ..
|
||||
|
||||
%build
|
||||
export PATH="%{_bindir}:${PATH}"
|
||||
mkdir -p build
|
||||
cd build
|
||||
%if "%{_build}" != "%{_host}"
|
||||
CFLAGS_FOR_BUILD="-g -O2 -Wall" \
|
||||
%endif
|
||||
CFLAGS="$TB_OPT_FLAGS" \
|
||||
../binutils-%{binutils_version}/configure \
|
||||
--build=%{_build} --host=%{_host} \
|
||||
--target=%{_target} \
|
||||
--verbose --disable-nls \
|
||||
--without-included-gettext \
|
||||
--disable-win32-registry \
|
||||
--disable-werror \
|
||||
--prefix=%{_prefix} --bindir=%{_bindir} \
|
||||
--exec-prefix=%{_exec_prefix} \
|
||||
--includedir=%{_includedir} --libdir=%{_libdir} \
|
||||
--mandir=%{_mandir} --infodir=%{_infodir}
|
||||
|
||||
%{__make} %{?_smp_mflags} all
|
||||
cd ..
|
||||
|
||||
%install
|
||||
export PATH="%{_bindir}:${PATH}"
|
||||
rm -rf $TB_BUILD_ROOT
|
||||
|
||||
cd build
|
||||
%{__make} DESTDIR=$TB_BUILD_ROOT install
|
||||
|
||||
# Dropped in FSF-binutils-2.9.5, but Cygwin still ships it.
|
||||
rm -rf $TB_BUILD_ROOT%{_infodir}/configure.info*
|
||||
|
||||
rm -f $TB_BUILD_ROOT%{_infodir}/dir
|
||||
touch $TB_BUILD_ROOT%{_infodir}/dir
|
||||
|
||||
# binutils does not install share/locale, however it uses it
|
||||
mkdir -p $TB_BUILD_ROOT%{_prefix}/share/locale
|
||||
|
||||
# We don't ship host files
|
||||
rm -f ${TB_BUILD_ROOT}%{_libdir}/libiberty*
|
||||
|
||||
# manpages without corresponding tools
|
||||
if test ! -f ${TB_BUILD_ROOT}%{_bindir}/%{_target}-dlltool%{_exeext}; then
|
||||
rm -f ${TB_BUILD_ROOT}%{_mandir}/man1/%{_target}-dlltool*
|
||||
fi
|
||||
if test ! -f ${TB_BUILD_ROOT}%{_bindir}/%{_target}-nlmconv%{_exeext}; then
|
||||
rm -f ${TB_BUILD_ROOT}%{_mandir}/man1/%{_target}-nlmconv*
|
||||
fi
|
||||
if test ! -f ${TB_BUILD_ROOT}%{_bindir}/%{_target}-windres%{_exeext}; then
|
||||
rm -f ${TB_BUILD_ROOT}%{_mandir}/man1/%{_target}-windres*
|
||||
fi
|
||||
if test ! -f ${TB_BUILD_ROOT}%{_bindir}/%{_target}-windmc%{_exeext}; then
|
||||
rm -f ${TB_BUILD_ROOT}%{_mandir}/man1/%{_target}-windmc*
|
||||
fi
|
||||
|
||||
cd ..
|
18
config/binutils-2.22-1.cfg
Normal file
18
config/binutils-2.22-1.cfg
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# Binutils 2.22.
|
||||
#
|
||||
|
||||
%include %{_configdir}/checks.cfg
|
||||
%include %{_configdir}/base.cfg
|
||||
|
||||
%define binutils_version 2.22
|
||||
|
||||
Name: %{_target}-binutils-%{binutils_version}-%{release}
|
||||
|
||||
%description
|
||||
Cross binutils for target %{_target}.
|
||||
|
||||
#
|
||||
# The binutils build instructions. We use 2.xx Release 1.
|
||||
#
|
||||
%include %{_configdir}/binutils-2-1.cfg
|
11
config/checks.cfg
Normal file
11
config/checks.cfg
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# Standard checks.
|
||||
#
|
||||
|
||||
%if %{_target} == %{nil}
|
||||
%error No 'target' defined
|
||||
%endif
|
||||
|
||||
%ifn %{defined release}
|
||||
%error No 'release' defined
|
||||
%endif
|
175
config/gcc-4.6-1.cfg
Normal file
175
config/gcc-4.6-1.cfg
Normal file
@ -0,0 +1,175 @@
|
||||
#
|
||||
# GCC 4.6 Version 1.
|
||||
#
|
||||
# This configuration file configure's, make's and install's gcc. It uses
|
||||
# newlib, MPFR, MPC, and GMP in a one-tree build configuration.
|
||||
#
|
||||
|
||||
%include %{_configdir}/checks.cfg
|
||||
|
||||
%ifn %{defined gcc_version_message}
|
||||
%error No GCC Version message defined.
|
||||
%endif
|
||||
|
||||
Summary: GCC v%{gcc_version} and Newlib v%{newlib_version} for target %{_target} on host %{_host}
|
||||
Version: %{gcc_version}
|
||||
Release: %{release}
|
||||
URL: http://gcc.gnu.org/
|
||||
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
|
||||
|
||||
#
|
||||
# Source
|
||||
#
|
||||
#
|
||||
# GCC core and G++
|
||||
#
|
||||
Source0: ftp://ftp.gnu.org/gnu/gcc/gcc-%{gcc_version}/gcc-core-%{gcc_version}.tar.bz2
|
||||
%if %{enable_cxx}
|
||||
Source1: ftp://ftp.gnu.org/gnu/gcc/gcc-%{gcc_pkgvers}/%{gcc_version}/gcc-g++-%{gcc_version}.tar.bz2
|
||||
%endif
|
||||
|
||||
#
|
||||
# Newlib
|
||||
#
|
||||
Source10: ftp://sourceware.org/pub/newlib/newlib-%{newlib_version}.tar.gz
|
||||
|
||||
#
|
||||
# Packages GCC requires
|
||||
#
|
||||
Source20: http://www.mpfr.org/mpfr-%{mpfr_version}/mpfr-%{mpfr_version}.tar.bz2
|
||||
Source21: http://www.multiprecision.org/mpc/download/mpc-%{mpc_version}.tar.gz
|
||||
Source22: ftp://ftp.gnu.org/gnu/gmp/gmp-%{gmp_version}.tar.bz2
|
||||
|
||||
#
|
||||
# The GCC library directory
|
||||
#
|
||||
%global _gcclibdir %{_prefix}/lib
|
||||
|
||||
#
|
||||
# Prepare the source code.
|
||||
#
|
||||
%prep
|
||||
%setup -q -c -T -n %{name}-%{version}
|
||||
|
||||
# gcc core
|
||||
%setup -q -T -D -n %{name}-%{version} -a0
|
||||
cd gcc-%{gcc_version}
|
||||
%{?patch0:%patch0 -p1}
|
||||
cd ..
|
||||
|
||||
# g++
|
||||
%{?source1:%setup -q -T -D -n %{name}-%{version} -a1}
|
||||
cd gcc-%{gcc_version}
|
||||
%{?patch1:%patch1 -p1}
|
||||
cd ..
|
||||
|
||||
# newlib
|
||||
%setup -q -T -D -n %{name}-%{version} -a10
|
||||
cd newlib-%{newlib_version}
|
||||
%{?patch10:%patch10 -p1}
|
||||
cd ..
|
||||
# Link newlib into the gcc source tree
|
||||
ln -s ../newlib-%{newlib_version}/newlib gcc-%{gcc_version}
|
||||
|
||||
# MPFR
|
||||
%setup -q -T -D -n %{name}-%{version} -a20
|
||||
cd mpfr-%{mpfr_version}
|
||||
%{?patch20:%patch20 -p1}
|
||||
cd ..
|
||||
# Build MPFR one-tree style
|
||||
ln -s ../mpfr-%{mpfr_version} gcc-%{gcc_version}/mpfr
|
||||
|
||||
# MPC
|
||||
%setup -q -T -D -n %{name}-%{version} -a21
|
||||
cd mpc-%{mpc_version}
|
||||
%{?patch21:%patch21 -p1}
|
||||
cd ..
|
||||
# Build MPC one-tree style
|
||||
ln -s ../mpc-%{mpc_version} gcc-%{gcc_version}/mpc
|
||||
|
||||
# GMP
|
||||
%setup -q -T -D -n %{name}-%{version} -a22
|
||||
cd gmp-%{gmp_version}
|
||||
%{?patch22:%patch22 -p1}
|
||||
cd ..
|
||||
# Build GMP one-tree style
|
||||
ln -s ../gmp-%{gmp_version} gcc-%{gcc_version}/gmp
|
||||
|
||||
echo "%{gcc_version_message}" > gcc-%{gcc_version}/gcc/DEV-PHASE
|
||||
|
||||
# Fix timestamps
|
||||
cd gcc-%{gcc_version}
|
||||
contrib/gcc_update --touch
|
||||
cd ..
|
||||
|
||||
%build
|
||||
export PATH="%{_bindir}:${PATH}"
|
||||
mkdir -p build
|
||||
cd build
|
||||
languages="c"
|
||||
%if %{enable_cxx}
|
||||
languages="$languages,c++"
|
||||
%endif
|
||||
%if "%{_build}" != "%{_host}"
|
||||
CFLAGS_FOR_BUILD="-g -O2 -Wall" \
|
||||
CC="%{_host}-gcc ${TB_OPT_FLAGS}" \
|
||||
%else
|
||||
# gcc is not ready to be compiled with -std=gnu99
|
||||
CC=$(echo "%{__cc} ${TB_OPT_FLAGS}" | sed -e 's,-std=gnu99 ,,') \
|
||||
%endif
|
||||
../gcc-%{gcc_version}/configure \
|
||||
--prefix=%{_prefix} \
|
||||
--bindir=%{_bindir} \
|
||||
--exec_prefix=%{_exec_prefix} \
|
||||
--includedir=%{_includedir} \
|
||||
--libdir=%{_gcclibdir} \
|
||||
--libexecdir=%{_libexecdir} \
|
||||
--mandir=%{_mandir} \
|
||||
--infodir=%{_infodir} \
|
||||
--datadir=%{_datadir} \
|
||||
--build=%_build --host=%_host \
|
||||
--target=%{_target} \
|
||||
--disable-libstdcxx-pch \
|
||||
--with-gnu-as --with-gnu-ld --verbose \
|
||||
--with-newlib \
|
||||
--with-system-zlib \
|
||||
--disable-nls --without-included-gettext \
|
||||
--disable-win32-registry \
|
||||
--enable-version-specific-runtime-libs \
|
||||
--disable-lto \
|
||||
%{?with_threads:--enable-threads}%{!?with_threads:--disable-threads} \
|
||||
%{?with_plugin:--enable-plugin}%{!?with_plugin:--disable-plugin} \
|
||||
--enable-newlib-io-c99-formats \
|
||||
%{?with_iconv:--enable-newlib-iconv} \
|
||||
--enable-languages="$languages"
|
||||
|
||||
%if "%_host" != "%_build"
|
||||
# Bug in gcc-3.2.1:
|
||||
# Somehow, gcc doesn't get syslimits.h right for Cdn-Xs
|
||||
mkdir -p gcc/include
|
||||
cp ../gcc-%{gcc_version}/gcc/gsyslimits.h gcc/include/syslimits.h
|
||||
%endif
|
||||
|
||||
%{__make} %{?_smp_mflags} all
|
||||
cd ..
|
||||
|
||||
%install
|
||||
export PATH="%{_bindir}:${PATH}"
|
||||
rm -rf $TB_BUILD_ROOT
|
||||
|
||||
cd build
|
||||
%{__make} DESTDIR=$TB_BUILD_ROOT install
|
||||
cd ..
|
||||
|
||||
# libiberty doesn't honor --libdir, but always installs to a
|
||||
# magically guessed _libdir
|
||||
rm -f ${TB_BUILD_ROOT}%{_libdir}/libiberty.a
|
||||
|
||||
# We use the version from binutils
|
||||
rm -f $TB_BUILD_ROOT%{_bindir}/%{_target}-c++filt%{_exeext}
|
||||
|
||||
# We don't ship info/dir
|
||||
rm -f $TB_BUILD_ROOT%{_infodir}/dir
|
||||
|
||||
# Don't want libffi's man-pages
|
||||
rm -f $TB_BUILD_ROOT%{_mandir}/man3/*ffi*
|
19
config/gcc-4.6-newlib-1.20-1.cfg
Normal file
19
config/gcc-4.6-newlib-1.20-1.cfg
Normal file
@ -0,0 +1,19 @@
|
||||
#
|
||||
# GCC 2.6, Newlib 1.20
|
||||
#
|
||||
|
||||
%include %{_configdir}/checks.cfg
|
||||
%include %{_configdir}/base.cfg
|
||||
|
||||
%define gcc_version 4.6.3
|
||||
%define newlib_version 1.20.0
|
||||
%define mpfr_version 3.0.1
|
||||
%define mpc_version 0.8.2
|
||||
%define gmp_version 5.0.1
|
||||
|
||||
Name: %{_target}-gcc-%{gcc_version}-newlib-%{newlib_version}-%{release}
|
||||
|
||||
#
|
||||
# The gcc/newlib build instructions. We use 4.6 Release 1.
|
||||
#
|
||||
%include %{_configdir}/gcc-4.6-1.cfg
|
29
tb-builder
Normal file
29
tb-builder
Normal file
@ -0,0 +1,29 @@
|
||||
#! /usr/bin/env python
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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 + '/tb')
|
||||
try:
|
||||
import build
|
||||
build.run(sys.argv)
|
||||
except ImportError:
|
||||
print >> sys.stderr, "Incorrect Tool Builder installation"
|
||||
sys.exit(1)
|
29
tb-crossgcc
Executable file
29
tb-crossgcc
Executable file
@ -0,0 +1,29 @@
|
||||
#! /usr/bin/env python
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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 + '/tb')
|
||||
try:
|
||||
import crossgcc
|
||||
crossgcc.run()
|
||||
except ImportError:
|
||||
print >> sys.stderr, "Incorrect Tools Bulder installation"
|
||||
sys.exit(1)
|
428
tb/build.py
Normal file
428
tb/build.py
Normal file
@ -0,0 +1,428 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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.
|
||||
|
||||
#
|
||||
# This code builds a package given a config 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 config
|
||||
import defaults
|
||||
import error
|
||||
import execute
|
||||
import log
|
||||
|
||||
#
|
||||
# Version of Tools 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)
|
||||
except:
|
||||
if s is not None:
|
||||
s.close()
|
||||
raise
|
||||
if s is not None:
|
||||
s.close()
|
||||
|
||||
class build:
|
||||
"""Build a package given a config file."""
|
||||
|
||||
def __init__(self, name, _defaults, opts):
|
||||
self.opts = opts
|
||||
_notice(opts, 'building: ' + name)
|
||||
self.config = config.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):
|
||||
self._output('removing: ' + path)
|
||||
if not self.opts.dry_run():
|
||||
if os.path.exists(path):
|
||||
try:
|
||||
shutil.rmtree(path)
|
||||
except IOError, err:
|
||||
raise error.error('error removing: ' + path)
|
||||
|
||||
def mkdir(self, path):
|
||||
self._output('making dir: ' + path)
|
||||
if not self.opts.dry_run():
|
||||
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)[2]
|
||||
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
|
||||
except:
|
||||
if _out is not None:
|
||||
_out.close()
|
||||
raise
|
||||
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.config.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'
|
||||
elif esl[-1:][0] == 'xz':
|
||||
source['compressed'] = '%{__xz} -dc'
|
||||
source['script'] = ''
|
||||
return source
|
||||
|
||||
def source(self, package, source_tag):
|
||||
#
|
||||
# Scan the sources found in the config 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 config 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.config.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.config.expand('cd %{_builddir}'))
|
||||
if delete_before_unpack:
|
||||
self.script.append(self.config.expand('%{__rm} -rf ' + name))
|
||||
if create_dir:
|
||||
self.script.append(self.config.expand('%{__mkdir_p} ' + name))
|
||||
#
|
||||
# If -a? then change directory before unpacking.
|
||||
#
|
||||
if not unpack_before_chdir:
|
||||
self.script.append(self.config.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.config.expand(source0['script']))
|
||||
self.script.append(self.config.expand(source['script']))
|
||||
if unpack_before_chdir:
|
||||
self.script.append(self.config.expand('cd ' + name))
|
||||
self.script.append(self.config.expand('%{__setup_post}'))
|
||||
if create_dir:
|
||||
self.script.append(self.config.expand('cd ..'))
|
||||
|
||||
def run(self, command, shell_opts = '', cwd = None):
|
||||
e = execute.capture_execution(log = log.default, dump = self.opts.quiet())
|
||||
cmd = self.config.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.config.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)
|
||||
tardir = os.path.abspath(self.config.expand('%{_tardir}'))
|
||||
self.script.append('mkdir -p %s' % tardir)
|
||||
self.script.append(self.config.expand('cd ' + inpath))
|
||||
tar = os.path.join(tardir, package.long_name() + '.tar.bz2')
|
||||
cmd = self.config.expand('%{__tar} -cf - . ' + '| %{__bzip2} > ' + tar)
|
||||
self.script.append(cmd)
|
||||
self.script.append(self.config.expand('cd %{_builddir}'))
|
||||
|
||||
def clean(self, package):
|
||||
self.script.append('echo "==> %clean:"')
|
||||
_clean = package.clean()
|
||||
if _clean is not None:
|
||||
for l in _clean:
|
||||
args = l.split()
|
||||
self.script.append(' '.join(args))
|
||||
|
||||
def cleanup(self):
|
||||
if not self.opts.no_clean():
|
||||
buildroot = self.config.abspath('buildroot')
|
||||
builddir = self.config.abspath('_builddir')
|
||||
_notice(self.opts, 'cleanup: %s' % (buildroot))
|
||||
self.rmdir(buildroot)
|
||||
_notice(self.opts, 'cleanup: %s' % (builddir))
|
||||
self.rmdir(builddir)
|
||||
|
||||
def make(self):
|
||||
packages = self.config.packages()
|
||||
package = packages['main']
|
||||
name = package.name()
|
||||
_notice(self.opts, 'package: %s' % (name))
|
||||
self.script.reset()
|
||||
self.script.append(self.config.expand('%{___build_template}'))
|
||||
self.script.append('echo "=> ' + name + ':"')
|
||||
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.config.expand(os.path.join('%{_builddir}', 'doit'))
|
||||
self._output('write script: ' + sn)
|
||||
self.script.write(sn)
|
||||
_notice(self.opts, 'building: ' + name)
|
||||
self.run(sn)
|
||||
|
||||
def name(self):
|
||||
packages = self.config.packages()
|
||||
package = packages['main']
|
||||
return package.name()
|
||||
|
||||
def run(args):
|
||||
try:
|
||||
opts, _defaults = defaults.load(args)
|
||||
log.default = log.log(opts.logfiles())
|
||||
_notice(opts, 'Tools Builder, v%s' % (version))
|
||||
for config_file in opts.config_files():
|
||||
b = build(config_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 error.exit, eerr:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
_notice(opts, 'user terminated')
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
run(sys.argv)
|
858
tb/config.py
Normal file
858
tb/config.py
Normal file
@ -0,0 +1,858 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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.
|
||||
|
||||
#
|
||||
# This code is based on a tool I wrote to parse RPM spec files in the RTEMS
|
||||
# project. This is now a configuration file format that has moved away from the
|
||||
# spec file format to support the specific needs of cross-compiling GCC. This
|
||||
# module parses a configuration 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
|
||||
|
||||
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:
|
||||
if d:
|
||||
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 directive_extend(self, dir, data):
|
||||
if dir not in self.directives:
|
||||
self.directives[dir] = []
|
||||
for i in range(0, len(data)):
|
||||
data[i] = data[i].strip()
|
||||
self.directives[dir].extend(data)
|
||||
|
||||
def info_append(self, info, data):
|
||||
if info not in self.infos:
|
||||
self.infos[info] = []
|
||||
self.infos[info].append(data)
|
||||
|
||||
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):
|
||||
if il == label:
|
||||
il = label + '0'
|
||||
elif not il[len(label):].isdigit():
|
||||
continue
|
||||
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 include(self):
|
||||
return self.find_directive('%include')
|
||||
|
||||
def long_name(self):
|
||||
return self.name()
|
||||
|
||||
class file:
|
||||
"""Parse a config file."""
|
||||
|
||||
_directive = [ '%description',
|
||||
'%changelog',
|
||||
'%prep',
|
||||
'%build',
|
||||
'%check',
|
||||
'%include',
|
||||
'%install',
|
||||
'%clean',
|
||||
'%post',
|
||||
'%preun',
|
||||
'%files' ]
|
||||
|
||||
_ignore = [ re.compile('%setup'),
|
||||
re.compile('%configure'),
|
||||
re.compile('%source[0-9]*'),
|
||||
re.compile('%patch[0-9]*') ]
|
||||
|
||||
def __init__(self, name, _defaults, opts):
|
||||
self.opts = opts
|
||||
if self.opts.trace():
|
||||
print 'config: %s' % (name)
|
||||
self.configpath = []
|
||||
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_depth = 0
|
||||
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 = 'config: %s' % ('.'.join(self.configpath)) + \
|
||||
'\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
|
||||
if not self.opts.dry_run():
|
||||
print >> sys.stderr, 'warning: switched to dry run due to errors'
|
||||
self.opts.set_dry_run()
|
||||
|
||||
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, config, 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, config, 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, config, 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(config, roc = True, isvalid = this_isvalid)
|
||||
if r[0] == 'control':
|
||||
if r[1] == '%end':
|
||||
self._error(label + ' without %endif')
|
||||
raise error.general('terminating build')
|
||||
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, config, ls, isvalid, invert = False):
|
||||
|
||||
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:
|
||||
#
|
||||
# Check if '%if %{x} == %{nil}' has both parts as nothing
|
||||
# which means '%if ==' is always True and '%if !=' is always false.
|
||||
#
|
||||
if ifls[0] == '==':
|
||||
istrue = True
|
||||
elif ifls[0] == '==':
|
||||
istrue = False
|
||||
else:
|
||||
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:
|
||||
#
|
||||
# Check is something is being checked against empty,
|
||||
# ie '%if %{x} == %{nil}'
|
||||
# The logic is 'something == nothing' is False and
|
||||
# 'something != nothing' is True.
|
||||
#
|
||||
if ifls[1] == '==':
|
||||
istrue = False
|
||||
elif ifls[1] == '!=':
|
||||
istrue = True
|
||||
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 invert:
|
||||
istrue = not istrue
|
||||
if self.opts.trace():
|
||||
print '_if: ', ifls, istrue
|
||||
return self._ifs(config, ls, '%if', istrue, isvalid)
|
||||
|
||||
def _ifos(self, config, 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(config, ls, '%ifos', isos, isvalid)
|
||||
|
||||
def _ifarch(self, config, 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(config, ls, '%ifarch', isarch, isvalid)
|
||||
|
||||
def _parse(self, config, roc = False, isvalid = True):
|
||||
# roc = return on control
|
||||
|
||||
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 config:
|
||||
self.lc += 1
|
||||
l = _clean(l)
|
||||
if len(l) == 0:
|
||||
continue
|
||||
if self.opts.trace():
|
||||
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] == '%error':
|
||||
if isvalid:
|
||||
return ('data', ['%%error %s:%d: %s' % (self.name, self.lc, l[7:])])
|
||||
elif ls[0] == '%define' or ls[0] == '%global':
|
||||
if isvalid:
|
||||
self._define(config, ls)
|
||||
elif ls[0] == '%undefine':
|
||||
if isvalid:
|
||||
self._undefine(config, ls)
|
||||
elif ls[0] == '%if':
|
||||
d = self._if(config, ls, isvalid)
|
||||
if len(d):
|
||||
return ('data', d)
|
||||
elif ls[0] == '%ifn':
|
||||
d = self._if(config, ls, isvalid, True)
|
||||
if len(d):
|
||||
return ('data', d)
|
||||
elif ls[0] == '%ifos':
|
||||
d = self._ifos(config, ls, isvalid)
|
||||
if len(d):
|
||||
return ('data', d)
|
||||
elif ls[0] == '%ifarch':
|
||||
d = self._ifarch(config, True, ls, isvalid)
|
||||
if len(d):
|
||||
return ('data', d)
|
||||
elif ls[0] == '%ifnarch':
|
||||
d = self._ifarch(config, 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 if 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(config, (ls[0], 'without_' + ls[1]))
|
||||
elif ls[0] == '%bcond_without':
|
||||
if isvalid:
|
||||
if self._label('without_' + ls[1]) not in self.defines:
|
||||
self._define(config, (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:
|
||||
return ('directive', ls[0].strip(), ls[1:])
|
||||
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):
|
||||
self._packages[self.package].directive_extend(dir, data)
|
||||
|
||||
def _info_append(self, info, data):
|
||||
self._packages[self.package].info_append(info, data)
|
||||
|
||||
def load(self, name):
|
||||
|
||||
if self.load_depth == 0:
|
||||
self.in_error = False
|
||||
self.lc = 0
|
||||
self.name = name
|
||||
self.defines = self.default_defines
|
||||
self.conditionals = {}
|
||||
self._packages = {}
|
||||
self.package = 'main'
|
||||
self._packages[self.package] = package(self.package,
|
||||
self.define('%{_arch}'))
|
||||
|
||||
self.load_depth += 1
|
||||
|
||||
save_name = self.name
|
||||
save_lc = self.lc
|
||||
|
||||
self.name = name
|
||||
self.lc = 0
|
||||
|
||||
#
|
||||
# Locate the config file. Expand any macors then Add the
|
||||
# extension. Check if the file exists, therefore directly
|
||||
# referenced. If not see if the file contains ':' or the path
|
||||
# separator. If it does split the path else use the standard config dir
|
||||
# path in the defaults.
|
||||
#
|
||||
|
||||
exname = self.expand(name)
|
||||
|
||||
if exname.endswith('.cfg'):
|
||||
configname = exname
|
||||
else:
|
||||
configname = '%s.cfg' % (exname)
|
||||
|
||||
cfgname = os.path.basename(configname)
|
||||
|
||||
if not os.path.exists(configname):
|
||||
if ':' in configname:
|
||||
configdirs = os.path.dirname(configname).split(':')
|
||||
else:
|
||||
configdirs = self.define('_configdir').split(':')
|
||||
for cp in configdirs:
|
||||
configname = os.path.join(os.path.abspath(cp), cfgname)
|
||||
if os.path.exists(configname):
|
||||
break
|
||||
configname = None
|
||||
if configname is None:
|
||||
raise error.general('no config file found: %s' % (cfgname))
|
||||
|
||||
try:
|
||||
if self.opts.trace():
|
||||
print '_open: %s' % (configname)
|
||||
config = open(configname, 'r')
|
||||
except IOError, err:
|
||||
raise error.general('error opening config file: %s' % (configname))
|
||||
self.configpath += [configname]
|
||||
|
||||
try:
|
||||
dir = None
|
||||
data = []
|
||||
while True:
|
||||
r = self._parse(config)
|
||||
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':
|
||||
new_data = []
|
||||
if r[1] == '%description':
|
||||
new_data = [' '.join(r[2])]
|
||||
elif r[1] == '%include':
|
||||
self.load(r[2][0])
|
||||
continue
|
||||
else:
|
||||
if len(r[2]) == 0:
|
||||
_package = 'main'
|
||||
elif len(r[2]) == 1:
|
||||
_package = r[2][0]
|
||||
else:
|
||||
if r[2][0].strip() != '-n':
|
||||
self._warning("unknown directive option: '" + ' '.join(r[2]) + "'")
|
||||
_package = r[2][1].strip()
|
||||
self._set_package(_package)
|
||||
if dir and dir != r[1]:
|
||||
self._directive_extend(dir, data)
|
||||
dir = r[1]
|
||||
data = new_data
|
||||
elif r[0] == 'data':
|
||||
for l in r[1]:
|
||||
l = self._expand(l)
|
||||
if l.startswith('%error'):
|
||||
raise error.general('config error: %s' % (l[7:]))
|
||||
if not dir:
|
||||
ls = self.tags.split(l, 1)
|
||||
if self.opts.trace():
|
||||
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] + "'")
|
||||
if dir is not None:
|
||||
self._directive_extend(dir, data)
|
||||
except:
|
||||
config.close()
|
||||
raise
|
||||
|
||||
config.close()
|
||||
|
||||
self.name = save_name
|
||||
self.lc = save_lc
|
||||
|
||||
self.load_depth -= 1
|
||||
|
||||
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)
|
||||
if opts.trace():
|
||||
print 'config: count %d' % (len(opts.config_files()))
|
||||
for config_file in opts.config_files():
|
||||
s = file(config_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()
|
245
tb/crossgcc.py
Normal file
245
tb/crossgcc.py
Normal file
@ -0,0 +1,245 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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.
|
||||
|
||||
#
|
||||
# This code builds a cross-gcc compiler tool suite given a tool set. A tool
|
||||
# set lists the various tools. These are specific tool configurations.
|
||||
#
|
||||
|
||||
import distutils.dir_util
|
||||
import operator
|
||||
import os
|
||||
|
||||
import build
|
||||
import defaults
|
||||
import error
|
||||
import log
|
||||
|
||||
#
|
||||
# Version of Tools Builder CrossGCC Builder.
|
||||
#
|
||||
version = '0.1'
|
||||
|
||||
def _trace(opts, text):
|
||||
if opts.trace():
|
||||
print text
|
||||
|
||||
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, toolset, _defaults, opts):
|
||||
_trace(opts, '_cgcc:%s: init' % (toolset))
|
||||
self.opts = opts
|
||||
self.defaults = _defaults
|
||||
self.toolset = toolset
|
||||
self.toolset_pkg = '%s-%s-tools' % (self.opts.expand('%{_target}', _defaults),
|
||||
self.toolset)
|
||||
|
||||
def _output(self, text):
|
||||
if not self.opts.quiet():
|
||||
log.output(text)
|
||||
|
||||
def copy(self, src, dst):
|
||||
what = '%s -> %s' % (src, dst)
|
||||
_notice(self.opts, 'coping: %s' % (what))
|
||||
if not self.opts.dry_run():
|
||||
try:
|
||||
files = distutils.dir_util.copy_tree(src, dst)
|
||||
for f in files:
|
||||
self._output(f)
|
||||
except IOError, err:
|
||||
raise error.general('coping tree: %s: %s' % (what, str(err)))
|
||||
except distutils.errors.DistutilsFileError, err:
|
||||
raise error.general('coping tree: %s' % (str(err)))
|
||||
|
||||
def first_package(self, _build):
|
||||
what = _build.config.expand('crossgcc-%(%{__id_u} -n)-' + _build.name())
|
||||
path = os.path.join(_build.config.abspath('%{_tmppath}'), what)
|
||||
_build.rmdir(path)
|
||||
_build.mkdir(path)
|
||||
prefix = os.path.join(_build.config.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.config.abspath('%{buildroot}'), path)
|
||||
|
||||
def last_package(self, _build, path):
|
||||
tar = os.path.join(_build.config.expand('%{_tardir}'),
|
||||
_build.config.expand('%s.tar.bz2' % (self.toolset_pkg)))
|
||||
_notice(self.opts, 'tarball: %s' % (tar))
|
||||
if not self.opts.dry_run():
|
||||
cmd = _build.config.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 load(self):
|
||||
|
||||
def _clean(line):
|
||||
line = line[0:-1]
|
||||
b = line.find('#')
|
||||
if b >= 0:
|
||||
line = line[1:b]
|
||||
return line.strip()
|
||||
|
||||
extoolset = self.opts.expand(self.toolset, self.defaults)
|
||||
|
||||
root, ext = os.path.splitext(extoolset)
|
||||
|
||||
if extoolset.endswith('.cfg'):
|
||||
toolsetcfg = extoolset
|
||||
else:
|
||||
toolsetcfg = '%s.cfg' % (extoolset)
|
||||
|
||||
toolsetname = toolsetcfg
|
||||
|
||||
if not os.path.exists(toolsetname):
|
||||
for cp in self.opts.expand('%{_configdir}', self.defaults).split(':'):
|
||||
configdir = os.path.abspath(cp)
|
||||
toolsetname = os.path.join(configdir, toolsetcfg)
|
||||
if os.path.exists(toolsetname):
|
||||
break
|
||||
toolsetname = None
|
||||
if toolsetname is None:
|
||||
raise error.general('no tool set file found: %s' % (toolsetcfg))
|
||||
try:
|
||||
if self.opts.trace():
|
||||
print '_cgcc:%s: open: %s' % (self.toolset, toolsetname)
|
||||
toolset = open(toolsetname, 'r')
|
||||
except IOError, err:
|
||||
raise error.general('error opening toolset file: %s' + toolsetname)
|
||||
|
||||
configs = []
|
||||
|
||||
try:
|
||||
lc = 0
|
||||
for l in toolset:
|
||||
lc += 1
|
||||
l = _clean(l)
|
||||
if len(l) == 0:
|
||||
continue
|
||||
if self.opts.trace():
|
||||
print '%03d: %s' % (lc, l)
|
||||
if ':' in l:
|
||||
ls = l.split(':')
|
||||
if ls[0].strip() == 'package':
|
||||
self.toolset_pkg = self.opts.expand(ls[1].strip(), self.defaults)
|
||||
self.defaults['package'] = self.toolset_pkg
|
||||
elif l[0] == '%':
|
||||
if l.startswith('%define'):
|
||||
ls = l.split()
|
||||
self.defaults[ls[1].strip()] = ls[2].strip()
|
||||
else:
|
||||
raise error.general('invalid directive in tool set files: %s' % (l))
|
||||
else:
|
||||
configs += [l.strip()]
|
||||
except:
|
||||
toolset.close()
|
||||
raise
|
||||
|
||||
toolset.close()
|
||||
|
||||
return configs
|
||||
|
||||
def make(self):
|
||||
|
||||
def _sort(configs):
|
||||
_configs = {}
|
||||
for config in configs:
|
||||
for order in crossgcc._order:
|
||||
if config.lower().find(order) >= 0:
|
||||
_configs[config] = crossgcc._order[order]
|
||||
sorted_configs = sorted(_configs.iteritems(), key = operator.itemgetter(1))
|
||||
configs = []
|
||||
for s in range(0, len(sorted_configs)):
|
||||
configs.append(sorted_configs[s][0])
|
||||
return configs
|
||||
|
||||
_trace(self.opts, '_cgcc:%s: make' % (self.toolset))
|
||||
_notice(self.opts, 'toolset: %s' % (self.toolset))
|
||||
|
||||
configs = self.load()
|
||||
|
||||
_trace(self.opts, '_cgcc:%s: configs: %s' % (self.toolset, ','.join(configs)))
|
||||
|
||||
current_path = os.environ['PATH']
|
||||
try:
|
||||
builds = []
|
||||
for s in range(0, len(configs)):
|
||||
b = build.build(configs[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(configs) - 1:
|
||||
self.last_package(b, path)
|
||||
builds += [b]
|
||||
if not self.opts.no_clean():
|
||||
for b in builds:
|
||||
_notice(self.opts, 'cleaning: %s' % (b.name()))
|
||||
b.cleanup()
|
||||
for b in builds:
|
||||
del b
|
||||
except:
|
||||
os.environ['PATH'] = current_path
|
||||
raise
|
||||
os.environ['PATH'] = current_path
|
||||
|
||||
def run():
|
||||
import sys
|
||||
try:
|
||||
opts, _defaults = defaults.load(sys.argv)
|
||||
log.default = log.log(opts.logfiles())
|
||||
_notice(opts, 'Tools Builder - CrossGCC Tool Sets, v%s' % (version))
|
||||
for toolset in opts.params():
|
||||
c = crossgcc(toolset, _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 error.exit, eerr:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
_notice(opts, 'user terminated')
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
57
tb/darwin.py
Normal file
57
tb/darwin.py
Normal file
@ -0,0 +1,57 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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.
|
||||
|
||||
#
|
||||
# This code is based on what ever doco about spec files I could find and
|
||||
# RTEMS project's spec files.
|
||||
#
|
||||
|
||||
import pprint
|
||||
import os
|
||||
|
||||
import execute
|
||||
|
||||
def load():
|
||||
uname = os.uname()
|
||||
sysctl = '/usr/sbin/sysctl '
|
||||
e = execute.capture_execution()
|
||||
exit_code, proc, output = e.shell(sysctl + 'hw.ncpu')
|
||||
if exit_code == 0:
|
||||
smp_mflags = '-j' + output.split(' ')[1].strip()
|
||||
else:
|
||||
smp_mflags = ''
|
||||
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',
|
||||
'_smp_mflags': smp_mflags,
|
||||
'__xz': '/usr/local/bin/xz',
|
||||
'with_zlib': '--with-zlib=no',
|
||||
}
|
||||
return defines
|
||||
|
||||
if __name__ == '__main__':
|
||||
pprint.pprint(load())
|
510
tb/defaults.py
Normal file
510
tb/defaults.py
Normal file
@ -0,0 +1,510 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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.
|
||||
|
||||
#
|
||||
# Determine the defaults and load the specific file.
|
||||
#
|
||||
|
||||
import glob
|
||||
import pprint
|
||||
import re
|
||||
import os
|
||||
|
||||
import error
|
||||
import execute
|
||||
|
||||
basepath = 'tb'
|
||||
|
||||
defaults = {
|
||||
# Nothing
|
||||
'nil': '',
|
||||
|
||||
# Set to invalid values.
|
||||
'_host': '',
|
||||
'_build': '%{_host}',
|
||||
'_target': '',
|
||||
|
||||
# Paths
|
||||
'_host_platform': '%{_host_cpu}-%{_host_vendor}-%{_host_os}%{?_gnu}',
|
||||
'_build': '%{_host}',
|
||||
'_arch': '%{_host_arch}',
|
||||
'_tbdir': '',
|
||||
'_topdir': os.getcwd(),
|
||||
'_configdir': '%{_topdir}/config:%{_tbdir}/config',
|
||||
'_tardir': '%{_topdir}/tar',
|
||||
'_sourcedir': '%{_topdir}/sources',
|
||||
'_builddir': '%{_topdir}/build/%{name}-%{version}-%{release}',
|
||||
'_docdir': '%{_defaultdocdir}',
|
||||
'_tmppath': '%{_topdir}/build/tmp',
|
||||
'buildroot:': '%{_tmppath}/%{name}-root-%(%{__id_u} -n)',
|
||||
|
||||
# Defaults, override in platform specific modules.
|
||||
'___setup_shell': '/bin/sh',
|
||||
'__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',
|
||||
'__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': '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',
|
||||
'__xz': '/usr/bin/xz',
|
||||
'_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',
|
||||
'_prefix': '%{_usr}',
|
||||
'_usr': '/usr/local',
|
||||
'_usrsrc': '%{_usr}/src',
|
||||
'_var': '/usr/local/var',
|
||||
'_varrun': '%{_var}/run',
|
||||
|
||||
# Shell Build Settings.
|
||||
'___build_args': '-e',
|
||||
'___build_cmd': '%{?_sudo:%{_sudo} }%{?_remsh:%{_remsh} %{_remhost} }%{?_remsudo:%{_remsudo} }%{?_remchroot:%{_remchroot} %{_remroot} }%{___build_shell} %{___build_args}',
|
||||
'___build_post': 'exit 0',
|
||||
|
||||
# Prebuild set up script.
|
||||
'___build_pre': '''# ___build_pre in as set up in defaults.py
|
||||
# Directories
|
||||
TB_SOURCE_DIR="%{_sourcedir}"
|
||||
TB_BUILD_DIR="%{_builddir}"
|
||||
TB_OPT_FLAGS="%{optflags}"
|
||||
TB_ARCH="%{_arch}"
|
||||
TB_OS="%{_os}"
|
||||
export TB_SOURCE_DIR TB_BUILD_DIR TB_OPT_FLAGS TB_ARCH TB_OS
|
||||
# Documentation
|
||||
TB_DOC_DIR="%{_docdir}"
|
||||
export TB_DOC_DIR
|
||||
# Packages
|
||||
TB_PACKAGE_NAME="%{name}"
|
||||
TB_PACKAGE_VERSION="%{version}"
|
||||
TB_PACKAGE_RELEASE="%{release}"
|
||||
export TBPACKAGE_NAME TB_PACKAGE_VERSION TB_PACKAGE_RELEASE
|
||||
# Build root directory
|
||||
%{?buildroot:TB_BUILD_ROOT="%{buildroot}"}
|
||||
export TB_BUILD_ROOT
|
||||
# The compiler flags
|
||||
%{?_targetcflags:CFLAGS_FOR_TARGET="%{_targetcflags}"}
|
||||
%{?_targetcxxflags:CXXFLAGS_FOR_TARGET="%{_targetcxxflags}"}
|
||||
export CFLAGS_FOR_TARGET
|
||||
# Default environment set up.
|
||||
LANG=C
|
||||
export LANG
|
||||
unset DISPLAY || :
|
||||
umask 022
|
||||
cd "%{_builddir}"''',
|
||||
'___build_shell': '%{?_buildshell:%{_buildshell}}%{!?_buildshell:/bin/sh}',
|
||||
'___build_template': '''#!%{___build_shell}
|
||||
%{___build_pre}
|
||||
%{nil}''',
|
||||
|
||||
# Configure command
|
||||
'configure': '''
|
||||
CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS ;
|
||||
CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ;
|
||||
FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS ;
|
||||
./configure --build=%{_build} --host=%{_host} \
|
||||
--target=%{_target_platform} \
|
||||
--program-prefix=%{?_program_prefix} \
|
||||
--prefix=%{_prefix} \
|
||||
--exec-prefix=%{_exec_prefix} \
|
||||
--bindir=%{_bindir} \
|
||||
--sbindir=%{_sbindir} \
|
||||
--sysconfdir=%{_sysconfdir} \
|
||||
--datadir=%{_datadir} \
|
||||
--includedir=%{_includedir} \
|
||||
--libdir=%{_libdir} \
|
||||
--libexecdir=%{_libexecdir} \
|
||||
--localstatedir=%{_localstatedir} \
|
||||
--sharedstatedir=%{_sharedstatedir} \
|
||||
--mandir=%{_mandir} \
|
||||
--infodir=%{_infodir}'''
|
||||
}
|
||||
|
||||
class command_line:
|
||||
"""Process the command line in a common way for all Tool Builder commands."""
|
||||
|
||||
_defaults = { 'params' : [],
|
||||
'warn-all' : '0',
|
||||
'quiet' : '0',
|
||||
'trace' : '0',
|
||||
'dry-run' : '0',
|
||||
'no-clean' : '0',
|
||||
'no-smp' : '0',
|
||||
'rebuild' : '0' }
|
||||
|
||||
_long_opts = { '--prefix' : '_prefix',
|
||||
'--prefixbase' : '_prefixbase',
|
||||
'--topdir' : '_topdir',
|
||||
'--configdir' : '_configdir',
|
||||
'--builddir' : '_builddir',
|
||||
'--sourcedir' : '_sourcedir',
|
||||
'--usrlibrpm' : '_usrlibrpm', # XXX remove ?
|
||||
'--tmppath' : '_tmppath',
|
||||
'--log' : '_logfile',
|
||||
'--url' : '_url_base',
|
||||
'--targetcflags' : '_targetcflags',
|
||||
'--targetcxxflags' : '_targetcxxflags',
|
||||
'--libstdcxxflags' : '_libstdcxxflags' }
|
||||
|
||||
_long_true_opts = { '--trace' : '_trace',
|
||||
'--dry-run' : '_dry_run',
|
||||
'--warn-all' : '_warn_all',
|
||||
'--no-clean' : '_no_clean',
|
||||
'--no-smp' : '_no_smp',
|
||||
'--rebuild' : '_rebuild' }
|
||||
|
||||
_target_triplets = { '--host' : '_host',
|
||||
'--build' : '_build',
|
||||
'--target' : '_target' }
|
||||
|
||||
def _help(self):
|
||||
print '%s: [options] [args]' % (self.command_name)
|
||||
print 'Options and arguments:'
|
||||
print '--trace : Trace the execution (not current used)'
|
||||
print '--dry-run : Do everything but actually run the build'
|
||||
print '--warn-all : Generate warnings'
|
||||
print '--no-clean : Do not clean up the build tree'
|
||||
print '--no-smp : Run with 1 job and not as many as CPUs'
|
||||
print '--rebuild : Rebuild (not used)'
|
||||
print '--host : Set the host triplet'
|
||||
print '--build : Set the build triplet'
|
||||
print '--target : Set the target triplet'
|
||||
print '--prefix path : Tools build prefix, ie where they are installed'
|
||||
print '--prefixbase path : '
|
||||
print '--topdir path : Top of the build tree, default is $PWD'
|
||||
print '--configdir path : Path to the configuration directory, default: ./config'
|
||||
print '--builddir path : Path to the build directory, default: ./build'
|
||||
print '--sourcedir path : Path to the source directory, default: ./source'
|
||||
print '--tmppath path : Path to the temp directory, default: ./tmp'
|
||||
print '--log file : Log file where all build out is written too'
|
||||
print '--url url : URL to look for source'
|
||||
print '--targetcflags flags : List of C flags for the target code'
|
||||
print '--targetcxxflags flags : List of C++ flags for the target code'
|
||||
print '--libstdcxxflags flags : List of C++ flags to build the target libstdc++ code'
|
||||
print '--with-<label> : Add the --with-<label> to the build'
|
||||
print '--without-<label> : Add the --without-<label> to the build'
|
||||
raise error.exit()
|
||||
|
||||
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.defaults['_tbdir'] = self.command_path
|
||||
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 _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
|
||||
elif a == '--help':
|
||||
self._help()
|
||||
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,
|
||||
basepath, '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'
|
||||
elif a == '-?':
|
||||
self._help()
|
||||
else:
|
||||
self.opts['params'].append(a)
|
||||
i += 1
|
||||
|
||||
def _post_process(self, _defaults):
|
||||
if self.no_smp():
|
||||
_defaults['_smp_mflags'] = _defaults['nil']
|
||||
if _defaults['_host'] == _defaults['nil']:
|
||||
raise error.general('host not set')
|
||||
return _defaults
|
||||
|
||||
def expand(self, s, _defaults):
|
||||
"""Simple basic expander of config 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 command(self):
|
||||
return os.path.join(self.command_path, self.command_name)
|
||||
|
||||
def dry_run(self):
|
||||
return self.opts['dry-run'] != '0'
|
||||
|
||||
def set_dry_run(self):
|
||||
self.opts['dry-run'] = '1'
|
||||
|
||||
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 no_smp(self):
|
||||
return self.opts['no-smp'] != '0'
|
||||
|
||||
def rebuild(self):
|
||||
return self.opts['rebuild'] != '0'
|
||||
|
||||
def params(self):
|
||||
return self.opts['params']
|
||||
|
||||
def get_config_files(self, config):
|
||||
if config.find('*') >= 0 or config.find('?'):
|
||||
configdir = os.path.dirname(config)
|
||||
configbase = os.path.basename(config)
|
||||
if len(configbase) == 0:
|
||||
configbase = '*'
|
||||
if len(configdir) == 0:
|
||||
configdir = self.expand(defaults['_configdir'], defaults)
|
||||
if not os.path.isdir(configdir):
|
||||
raise error.general('configdir is not a directory or does not exist: ' + configdir)
|
||||
files = glob.glob(os.path.join(configdir, configbase))
|
||||
configs = files
|
||||
else:
|
||||
configs = [config]
|
||||
return configs
|
||||
|
||||
def config_files(self):
|
||||
configs = []
|
||||
for config in self.opts['params']:
|
||||
configs.extend(self.get_config_files(config))
|
||||
return configs
|
||||
|
||||
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
|
||||
if os.name == 'nt':
|
||||
import windows
|
||||
overrides = windows.load()
|
||||
else:
|
||||
uname = os.uname()
|
||||
try:
|
||||
if uname[0] == 'Darwin':
|
||||
import darwin
|
||||
overrides = darwin.load()
|
||||
elif uname[0] == 'FreeBSD':
|
||||
import freebsd
|
||||
overrides = freebsd.load()
|
||||
elif uname[0] == 'Linux':
|
||||
import linux
|
||||
overrides = linux.load()
|
||||
except:
|
||||
pass
|
||||
if overrides is None:
|
||||
raise error.general('no hosts defaults found; please add')
|
||||
for k in overrides:
|
||||
d[k] = overrides[k]
|
||||
o = command_line(args)
|
||||
for k in o.defaults:
|
||||
d[k] = o.defaults[k]
|
||||
d = 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)
|
54
tb/error.py
Normal file
54
tb/error.py
Normal file
@ -0,0 +1,54 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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.
|
||||
|
||||
#
|
||||
# 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)
|
||||
|
||||
class exit(error):
|
||||
"""Raise for to exit."""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
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
|
363
tb/execute.py
Executable file
363
tb/execute.py
Executable file
@ -0,0 +1,363 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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.
|
||||
|
||||
#
|
||||
# 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 splt 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
|
63
tb/linux.py
Normal file
63
tb/linux.py
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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.
|
||||
|
||||
#
|
||||
# This code is based on what ever doco about spec files I could find and
|
||||
# RTEMS project's spec files.
|
||||
#
|
||||
|
||||
import pprint
|
||||
import os
|
||||
|
||||
import execute
|
||||
|
||||
def load():
|
||||
uname = os.uname()
|
||||
smp_mflags = ''
|
||||
processors = '/bin/grep processor /proc/cpuinfo'
|
||||
e = execute.capture_execution()
|
||||
exit_code, proc, output = e.shell(processors)
|
||||
if exit_code == 0:
|
||||
cpus = 0
|
||||
for l in output.split('\n'):
|
||||
count = l.split(':')[1].strip()
|
||||
if count > cpus:
|
||||
cpus = int(count)
|
||||
if cpus > 0:
|
||||
smp_mflags = '-j%d' % (cpus)
|
||||
defines = {
|
||||
'_os': 'linux',
|
||||
'_host': uname[4] + '-linux-gnu',
|
||||
'_host_vendor': 'gnu',
|
||||
'_host_os': 'linux',
|
||||
'_host_cpu': uname[4],
|
||||
'_host_alias': '%{nil}',
|
||||
'_host_arch': uname[4],
|
||||
'_usr': '/usr',
|
||||
'_var': '/usr/var',
|
||||
'optflags': '-O2 -fasynchronous-unwind-tables',
|
||||
'_smp_mflags': smp_mflags,
|
||||
'__bzip2': '/usr/bin/bzip2',
|
||||
'__gzip': '/bin/gzip',
|
||||
'__tar': '/bin/tar'
|
||||
}
|
||||
return defines
|
||||
|
||||
if __name__ == '__main__':
|
||||
pprint.pprint(load())
|
111
tb/log.py
Executable file
111
tb/log.py
Executable file
@ -0,0 +1,111 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 Chris Johns (chrisj@rtems.org)
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of the RTEMS Tools package in 'rtems-testing'.
|
||||
#
|
||||
# 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.
|
||||
|
||||
#
|
||||
# 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
|
65
tb/windows.py
Normal file
65
tb/windows.py
Normal file
@ -0,0 +1,65 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2012 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.
|
||||
|
||||
#
|
||||
# Windows specific support and overrides.
|
||||
#
|
||||
|
||||
import pprint
|
||||
import os
|
||||
|
||||
import execute
|
||||
|
||||
def load():
|
||||
uname = 'win32'
|
||||
if os.environ.has_key('NUMBER_OF_PROCESSORS'):
|
||||
ncpus = int(os.environ['NUMBER_OF_PROCESSORS'])
|
||||
else:
|
||||
ncpus = 0
|
||||
if ncpus > 1:
|
||||
smp_mflags = '-j' + str(ncpus)
|
||||
else:
|
||||
smp_mflags = ''
|
||||
if os.environ.has_key('HOSTTYPE'):
|
||||
hosttype = os.environ['HOSTTYPE']
|
||||
else:
|
||||
hosttype = 'i686'
|
||||
system = 'mingw32'
|
||||
defines = {
|
||||
'_os': 'win32',
|
||||
'_host': hosttype + '-pc-' + system,
|
||||
'_host_vendor': 'microsoft',
|
||||
'_host_os': 'win32',
|
||||
'_host_cpu': hosttype,
|
||||
'_host_alias': '%{nil}',
|
||||
'_host_arch': hosttype,
|
||||
'_usr': '/opt/local',
|
||||
'_var': '/opt/local/var',
|
||||
'optflags': '-O2 -fasynchronous-unwind-tables',
|
||||
'_smp_mflags': smp_mflags,
|
||||
'__sh': 'sh',
|
||||
'_buildshell': '%{__sh}',
|
||||
'___setup_shell': '%{__sh}',
|
||||
# Build flags
|
||||
'optflags': '-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -mms-bitfields'
|
||||
}
|
||||
Return defines
|
||||
|
||||
if __name__ == '__main__':
|
||||
pprint.pprint(load())
|
Loading…
x
Reference in New Issue
Block a user