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