Merge branch 'master' of ssh://kiwi/opt/work/sw/rtems/tb/source-builder

Merge the separate repo into a single master with the RTEMS source
builder.
This commit is contained in:
Chris Johns 2012-11-06 10:06:59 +11:00
commit c798ce46a1
73 changed files with 5318 additions and 0 deletions

2
.gitignore vendored Normal file
View File

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

69
config/autoconf-2-1.cfg Normal file
View File

@ -0,0 +1,69 @@
#
# Autoconf 2.xx Version 1.
#
# This configuration file configure's, make's and install's autoconf
#
ifn %{defined _internal_autotools}
%define _internal_autotools no
%endfi
Name: autoconf-%{autoconf_version}-%{_host}-%{release}
Summary: Autoconf v%{autoconf_version} for host %{_host}
Version: %{autoconf_version}
Release: %{release}
URL: http://www.gnu.org/software/autoconf/
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
#
# Source
#
Source0: ftp://ftp.gnu.org/gnu/autoconf/autoconf-%{autoconf_version}.tar.gz
VersionControl0: git clone git://git.sv.gnu.org/autoconf
#
# Prepare the source code.
#
%prep
%setup -q -c -T -n %{name}-%{version}
cd autoconf-%{autoconf_version}
%{?patch0:%patch0 -p1}
cd ..
%build
export PATH="%{_bindir}:${PATH}"
cd autoconf-%{autoconf_version}
if "%{_internal_autotools}" == "yes"; then
ac_prefix=$SB_TMPPREFIX
else
ac_prefix=%{_prefix}
fi
%if "%{_build}" != "%{_host}"
CFLAGS_FOR_BUILD="-g -O2 -Wall" \
%endif
CFLAGS="$SB_OPT_FLAGS" \
./configure \
--build=%{_build} --host=%{_host} \
--verbose --disable-nls \
--without-included-gettext \
--prefix=${ac_prefix}
%{__make} %{?_smp_mflags} all
cd ..
%install
export PATH="%{_bindir}:${PATH}"
rm -rf $SB_BUILD_ROOT
cd autoconf-%{autoconf_version}
if "%{_internal_autotools}" == "yes"; then
%{__make} install
else
%{__make} DESTDIR=$SB_BUILD_ROOT install
fi
cd ..

View File

@ -0,0 +1,16 @@
#
# Autoconf 2.68.
#
%if %{release} == %{nil}
%define release 1
%endif
%include %{_configdir}/base.cfg
%define autoconf_version 2.68
#
# The autoconf build instructions. We use 2.xx Release 1.
#
%include %{_configdir}/autoconf-2-1.cfg

View File

@ -0,0 +1,16 @@
#
# Autoconf 2.22.
#
%if %{release} == %{nil}
%define release 1
%endif
%include %{_configdir}/base.cfg
%define autoconf_version 2.69
#
# The autoconf build instructions. We use 2.xx Release 1.
#
%include %{_configdir}/autoconf-2-1.cfg

View File

@ -0,0 +1,8 @@
#
# Internal Autoconf 2.68.
#
%warning This autoconf build is for internal bootstraps, no package created
%define _internal_autotools yes
%include %{_configdir}/autoconf-2.68-1.cfg

69
config/automake-1-1.cfg Normal file
View File

@ -0,0 +1,69 @@
#
# Automake 1.xx Version 1.
#
# This configuration file configure's, make's and install's automake
#
ifn %{defined _internal_autotools}
%define _internal_autotools no
%endfi
Name: automake-%{automake_version}-%{_host}-%{release}
Summary: Automake v%{automake_version} for host %{_host}
Version: %{automake_version}
Release: %{release}
URL: http://www.gnu.org/software/automake/
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
#
# Source
#
Source0: ftp://ftp.gnu.org/gnu/automake/automake-%{automake_version}.tar.gz
VersionControl0: git clone git://git.savannah.gnu.org/automake.git
#
# Prepare the source code.
#
%prep
%setup -q -c -T -n %{name}-%{version}
cd automake-%{automake_version}
%{?patch0:%patch0 -p1}
cd ..
%build
export PATH="%{_bindir}:${PATH}"
cd automake-%{automake_version}
if "%{_internal_autotools}" == "yes"; then
am_prefix=$SB_TMPPREFIX
else
am_prefix=%{_prefix}
fi
%if "%{_build}" != "%{_host}"
CFLAGS_FOR_BUILD="-g -O2 -Wall" \
%endif
CFLAGS="$SB_OPT_FLAGS" \
./configure \
--build=%{_build} --host=%{_host} \
--verbose \
--prefix=${am_prefix}
%{__make} %{?_smp_mflags} all
cd ..
%install
export PATH="%{_bindir}:${PATH}"
rm -rf $SB_BUILD_ROOT
cd automake-%{automake_version}
if "%{_internal_autotools}" == "yes"; then
%{__make} install
else
%{__make} DESTDIR=$SB_BUILD_ROOT install
fi
cd ..

View File

@ -0,0 +1,16 @@
#
# Automake 1.12
#
%if %{release} == %{nil}
%define release 1
%endif
%include %{_configdir}/base.cfg
%define automake_version 1.12
#
# The automake build instructions. We use 1.xx Release 1.
#
%include %{_configdir}/automake-1-1.cfg

View File

@ -0,0 +1,8 @@
#
# Internal Automake 1.12
#
%warning This automake build is for internal bootstraps, no package created
%define _internal_autotools yes
%include %{_configdir}/automake-1.12-1.cfg

34
config/base.cfg Normal file
View 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

88
config/binutils-2-1.cfg Normal file
View File

@ -0,0 +1,88 @@
#
# Binutils 2.xx Version 1.
#
# This configuration file configure's, make's and install's binutils.
#
%include %{_configdir}/checks.cfg
Name: %{_target}-binutils-%{binutils_version}-%{release}
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
VersionControl0: cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src co binutils
#
# 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="$SB_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 $SB_BUILD_ROOT
cd build
%{__make} DESTDIR=$SB_BUILD_ROOT install
# Dropped in FSF-binutils-2.9.5, but Cygwin still ships it.
rm -rf $SB_BUILD_ROOT%{_infodir}/configure.info*
rm -f $SB_BUILD_ROOT%{_infodir}/dir
touch $SB_BUILD_ROOT%{_infodir}/dir
# binutils does not install share/locale, however it uses it
mkdir -p $SB_BUILD_ROOT%{_prefix}/share/locale
# We don't ship host files
rm -f ${SB_BUILD_ROOT}%{_libdir}/libiberty*
# manpages without corresponding tools
if test ! -f ${SB_BUILD_ROOT}%{_bindir}/%{_target}-dlltool%{_exeext}; then
rm -f ${SB_BUILD_ROOT}%{_mandir}/man1/%{_target}-dlltool*
fi
if test ! -f ${SB_BUILD_ROOT}%{_bindir}/%{_target}-nlmconv%{_exeext}; then
rm -f ${SB_BUILD_ROOT}%{_mandir}/man1/%{_target}-nlmconv*
fi
if test ! -f ${SB_BUILD_ROOT}%{_bindir}/%{_target}-windres%{_exeext}; then
rm -f ${SB_BUILD_ROOT}%{_mandir}/man1/%{_target}-windres*
fi
if test ! -f ${SB_BUILD_ROOT}%{_bindir}/%{_target}-windmc%{_exeext}; then
rm -f ${SB_BUILD_ROOT}%{_mandir}/man1/%{_target}-windmc*
fi
cd ..

View File

@ -0,0 +1,17 @@
#
# Binutils 2.22.
#
%if %{release} == %{nil}
%define release 1
%endif
%include %{_configdir}/checks.cfg
%include %{_configdir}/base.cfg
%define binutils_version 2.22
#
# The binutils build instructions. We use 2.xx Release 1.
#
%include %{_configdir}/binutils-2-1.cfg

11
config/checks.cfg Normal file
View File

@ -0,0 +1,11 @@
#
# Standard checks.
#
%if %{_target} == %{nil}
%error No 'target' defined
%endif
%ifn %{defined release}
%error No 'release' defined
%endif

60
config/expat-2-1.cfg Normal file
View File

@ -0,0 +1,60 @@
#
# Expat 2.xx Version 1.
#
# This configuration file configure's, make's and install's expat.
#
%if %{release} == %{nil}
%define release 1
%endif
Name: expat-%{expat_version}-%{_host}-%{release}
Summary: Expat XML Parser v%{expat_version} for target %{_target} on host %{_host}
Version: %{expat_version}
Release: %{release}
URL: http://expat.sourceforge.net/
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
#
# Source
#
Source0: http://downloads.sourceforge.net/project/expat/expat/%{expat_version}/expat-%{expat_version}.tar.gz
#
# Prepare the source code.
#
%prep
%setup -q -c -T -n %{name}-%{version}
cd expat-%{expat_version}
%{?patch0:%patch0 -p1}
cd ..
%build
export PATH="%{_bindir}:${PATH}"
cd expat-%{expat_version}
%if "%{_build}" != "%{_host}"
CFLAGS_FOR_BUILD="-g -O2 -Wall" \
%endif
CFLAGS="$SB_OPT_FLAGS" \
./configure \
--build=%{_build} --host=%{_host} \
--verbose --disable-nls \
--without-included-gettext \
--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 $SB_BUILD_ROOT
cd expat-%{expat_version}
%{__make} DESTDIR=$SB_BUILD_ROOT install
cd ..

16
config/expat-2.1.0-1.cfg Normal file
View File

@ -0,0 +1,16 @@
#
# Expat 2.1.0
#
%if %{release} == %{nil}
%define release 1
%endif
%include %{_configdir}/base.cfg
%define expat_version 2.1.0
#
# The Expat build instructions. We use 2.xx Release 1.
#
%include %{_configdir}/expat-2-1.cfg

186
config/gcc-4.4-1.cfg Normal file
View File

@ -0,0 +1,186 @@
#
# 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.
#
#
# Default to C++ on.
#
%ifn %{defined enable_cxx}
%define enable_cxx 1
%endif
%include %{_configdir}/checks.cfg
%ifn %{defined gcc_version_message}
%error No GCC Version message defined.
%endif
Name: %{_target}-gcc-%{gcc_version}-newlib-%{newlib_version}-%{release}
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
VersionContro0: git clone git://gcc.gnu.org/git/gcc.git
%if %{enable_cxx}
Source1: ftp://ftp.gnu.org/gnu/gcc/gcc-%{gcc_version}/gcc-g++-%{gcc_version}.tar.gz
%endif
#
# Newlib
#
Source10: ftp://sourceware.org/pub/newlib/newlib-%{newlib_version}.tar.gz
VersionControl10: cvs -z 9 -d :pserver:anoncvs@sources.redhat.com:/cvs/src co newlib
#
# 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 ${SB_OPT_FLAGS}" \
%else
# gcc is not ready to be compiled with -std=gnu99
CC=$(echo "%{__cc} ${SB_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 $SB_BUILD_ROOT
cd build
%{__make} DESTDIR=$SB_BUILD_ROOT install
cd ..
# libiberty doesn't honor --libdir, but always installs to a
# magically guessed _libdir
rm -f ${SB_BUILD_ROOT}%{_libdir}/libiberty.a
# We use the version from binutils
rm -f $SB_BUILD_ROOT%{_bindir}/%{_target}-c++filt%{_exeext}
# We don't ship info/dir
rm -f $SB_BUILD_ROOT%{_infodir}/dir
# Don't want libffi's man-pages
rm -f $SB_BUILD_ROOT%{_mandir}/man3/*ffi*

186
config/gcc-4.6-1.cfg Normal file
View File

@ -0,0 +1,186 @@
#
# 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.
#
#
# Default to C++ on.
#
%ifn %{defined enable_cxx}
%define enable_cxx 1
%endif
%include %{_configdir}/checks.cfg
%ifn %{defined gcc_version_message}
%error No GCC Version message defined.
%endif
Name: %{_target}-gcc-%{gcc_version}-newlib-%{newlib_version}-%{release}
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
VersionContro0: git clone git://gcc.gnu.org/git/gcc.git
%if %{enable_cxx}
Source1: ftp://ftp.gnu.org/gnu/gcc/gcc-%{gcc_version}/gcc-g++-%{gcc_version}.tar.gz
%endif
#
# Newlib
#
Source10: ftp://sourceware.org/pub/newlib/newlib-%{newlib_version}.tar.gz
VersionControl10: cvs -z 9 -d :pserver:anoncvs@sources.redhat.com:/cvs/src co newlib
#
# 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 ${SB_OPT_FLAGS}" \
%else
# gcc is not ready to be compiled with -std=gnu99
CC=$(echo "%{__cc} ${SB_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 $SB_BUILD_ROOT
cd build
%{__make} DESTDIR=$SB_BUILD_ROOT install
cd ..
# libiberty doesn't honor --libdir, but always installs to a
# magically guessed _libdir
rm -f ${SB_BUILD_ROOT}%{_libdir}/libiberty.a
# We use the version from binutils
rm -f $SB_BUILD_ROOT%{_bindir}/%{_target}-c++filt%{_exeext}
# We don't ship info/dir
rm -f $SB_BUILD_ROOT%{_infodir}/dir
# Don't want libffi's man-pages
rm -f $SB_BUILD_ROOT%{_mandir}/man3/*ffi*

View File

@ -0,0 +1,21 @@
#
# GCC 2.6, Newlib 1.20
#
%if %{release} == %{nil}
%define release 1
%endif
%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
#
# The gcc/newlib build instructions. We use 4.6 Release 1.
#
%include %{_configdir}/gcc-4.6-1.cfg

70
config/gdb-7-1.cfg Normal file
View File

@ -0,0 +1,70 @@
#
# GDB 7.xx Version 1.
#
# This configuration file configure's, make's and install's gdb.
#
%include %{_configdir}/checks.cfg
Name: %{_target}-gdb-%{gdb_version}-%{release}
Summary: GDB v%{gdb_version} for target %{_target} on host %{_host}
Version: %{gdb_version}
Release: %{release}
URL: http://www.gnu.org/software/gdb/
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
#
# Source
#
Source0: http://ftp.gnu.org/gnu/gdb/gdb-%{gdb_version}.tar.bz2
VersionControl0 git clone git://sourceware.org/git/gdb.git
#
# Prepare the source code.
#
%prep
%setup -q -c -T -n %{name}-%{version}
cd gdb-%{gdb_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="$SB_OPT_FLAGS" \
../gdb-%{gdb_version}/configure \
--build=%{_build} --host=%{_host} \
--target=%{_target} \
--verbose --disable-nls \
--without-included-gettext \
--disable-win32-registry \
--disable-werror \
--enable-sim \
--with-expat \
--with-python \
--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 $SB_BUILD_ROOT
cd build
%{__make} DESTDIR=$SB_BUILD_ROOT install
# Dropped in FSF-binutils-2.9.5, but Cygwin still ships it.
rm -rf $SB_BUILD_ROOT%{_infodir}/configure.info*
rm -f $SB_BUILD_ROOT%{_infodir}/dir
touch $SB_BUILD_ROOT%{_infodir}/dir
cd ..

17
config/gdb-7.5-1.cfg Normal file
View File

@ -0,0 +1,17 @@
#
# GDB 7.5.
#
%if %{release} == %{nil}
%define release 1
%endif
%include %{_configdir}/checks.cfg
%include %{_configdir}/base.cfg
%define gdb_version 7.5
#
# The gdb build instructions. We use 7.xx Release 1.
#
%include %{_configdir}/gdb-7-1.cfg

24
config/gnu-tools-4.6.bset Normal file
View File

@ -0,0 +1,24 @@
#
# GNU Tools Set
#
%define release 1
package: gnu-tool-%{_target}-%{release}
#
# Project custom message
#
%define gcc_version_message SB-%{release},gcc-%{gcc_version}/newlib-%{newlib_version}
#
# Enable G++
#
%define enable_cxx 1
#
# Tool configuration.
#
binutils-2.22-1
gcc-4.6-newlib-1.20-1
gdb-7.5-1

61
config/libusb-1-1.cfg Normal file
View File

@ -0,0 +1,61 @@
#
# LibUSB 1.xx Version 1.
#
# This configuration file configure's, make's and install's libusb.
#
%if %{release} == %{nil}
%define release 1
%endif
Summary: LibUSB v%{libusb_version} for target %{_target} on host %{_host}
Version: %{libusb_version}
Release: %{release}
URL: http://libusb.org/
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
#
# Source
#
Source0: http://downloads.sourceforge.net/project/libusb/libusb-1.0/libusb-%{libusb_version}/libusb-%{libusb_version}.tar.bz2
VersionControl0: git clone git://git.libusb.org/libusb.git
#
# Prepare the source code.
#
%prep
%setup -q -c -T -n %{name}-%{version}
%setup -q -D -T -n %{name}-%{version} -a0
cd libusb-%{libusb_version}
%{?patch0:%patch0 -p1}
cd ..
%build
export PATH="%{_bindir}:${PATH}"
cd libusb-%{libusb_version}
%if "%{_build}" != "%{_host}"
CFLAGS_FOR_BUILD="-g -O2 -Wall" \
%endif
CFLAGS="$SB_OPT_FLAGS" \
./configure \
--build=%{_build} --host=%{_host} \
--verbose --disable-nls \
--without-included-gettext \
--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 $SB_BUILD_ROOT
cd libusb-%{libusb_version}
%{__make} DESTDIR=$SB_BUILD_ROOT install
cd ..

21
config/libusb-1.0.9-1.cfg Normal file
View File

@ -0,0 +1,21 @@
#
# LibUSB 1.0.9
#
%ifn %{defined release}
%error No 'release' defined
%endif
%include %{_configdir}/base.cfg
%define libusb_version 1.0.9
Name: libusb-%{libusb_version}-%{_host}-%{release}
%description
LibUSB for host %{_host}.
#
# The Libuxb build instructions. We use 1.xx Release 1.
#
%include %{_configdir}/libusb-1-1.cfg

56
config/m4-1-1.cfg Normal file
View File

@ -0,0 +1,56 @@
#
# M4 1.xx Version 1.
#
# This configuration file configure's, make's and install's m4
#
# Warning: this package is only for bootstrapping within a build.
#
Name: m4-%{m4_version}-%{_host}-%{release}
Summary: M4 v%{m4_version} for host %{_host}
Version: %{m4_version}
Release: %{release}
URL: http://www.gnu.org/software/m4/
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
#
# Source
#
Source0: ftp://ftp.gnu.org/gnu/m4/m4-%{m4_version}.tar.gz
#
# Prepare the source code.
#
%prep
%setup -q -c -T -n %{name}-%{version}
cd m4-%{m4_version}
%{?patch0:%patch0 -p1}
cd ..
%build
export PATH="%{_bindir}:${PATH}"
cd m4-%{m4_version}
%if "%{_build}" != "%{_host}"
CFLAGS_FOR_BUILD="-g -O2 -Wall" \
%endif
CFLAGS="$SB_OPT_FLAGS" \
./configure \
--build=%{_build} --host=%{_host} \
--verbose --disable-nls \
--without-included-gettext \
--prefix=$SB_TMPPREFIX
%{__make} %{?_smp_mflags} all
cd ..
%install
export PATH="%{_bindir}:${PATH}"
rm -rf $SB_BUILD_ROOT
cd m4-%{m4_version}
%{__make} install
cd ..

16
config/m4-1.4.16-1.cfg Normal file
View File

@ -0,0 +1,16 @@
#
# M4 1.4.16
#
%if %{release} == %{nil}
%define release 1
%endif
%include %{_configdir}/base.cfg
%define m4_version 1.4.16
#
# The m4 build instructions. We use 1.x.x Release 1.
#
%include %{_configdir}/m4-1-1.cfg

View File

@ -0,0 +1,71 @@
#
# ST-Link Version 1.
#
# This configuration file configure's, make's and install's SL-Link.
#
%if %{release} == %{nil}
%define release 1
%endif
%include %{_configdir}/base.cfg
%define stlink_version 3494c11
Name: texane-stlink-%{stlink_version}-%{release}
Summary: ST-Link v%{stlink_version} for host %{_host}
Version: %{stlink_version}
Release: %{release}
URL: https://github.com/texane/stlink/
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
#
# Source
#
Source0: https://api.github.com/repos/texane/stlink/texane-stlink-%{stlink_version}.tar.gz
VersionControl0: git clone https://github.com/texane/stlink.git
Patch0: texane-stlink-3494c11-1.diff
#
# Prepare the source code.
#
%prep
%setup -q -c -T -n %{name}-%{version}
%setup -q -D -T -n %{name}-%{version} -a0
cd texane-stlink-%{stlink_version}
%{?patch0:%patch0 -p1}
cd ..
%build
export PATH="%{_bindir}:${PATH}"
cd texane-stlink-%{stlink_version}
./autogen.sh
%if "%{_build}" != "%{_host}"
CFLAGS_FOR_BUILD="-g -O2 -Wall" \
%endif
CPPFLAGS="-I $SB_TMPPREFIX/include/libusb-1.0" \
CFLAGS="$SB_OPT_FLAGS" \
LDFLAGS="-L $SB_TMPPREFIX/lib" \
./configure \
--build=%{_build} --host=%{_host} \
--verbose \
--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 texane-stlink-%{stlink_version}
%{__make} DESTDIR=$TB_BUILD_ROOT install
cd ..

2
doc/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.lock-*
build

5
doc/images/icons/README Normal file
View File

@ -0,0 +1,5 @@
Replaced the plain DocBook XSL admonition icons with Jimmac's DocBook
icons (http://jimmac.musichall.cz/ikony.php3). I dropped transparency
from the Jimmac icons to get round MS IE and FOP PNG incompatibilies.
Stuart Rackham

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
doc/images/icons/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
doc/images/icons/next.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
doc/images/icons/note.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
doc/images/icons/prev.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
doc/images/icons/tip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
doc/images/icons/up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
doc/images/rtemswhitebg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

214
doc/source-builder.txt Normal file
View File

@ -0,0 +1,214 @@
Source Builder
==============
Chris Johns <chrisj@rtems.org>
1.0, November 2012
:doctype: book
:toc:
:icons:
:numbered:
image:images/rtemswhitebg.jpg["RTEMS",width="20%"]
Introduction
------------
The Source Builder is a tool to aid building packages from source. It is not a
package manager. It is just helps consolidate the details that you need to know
to build a package from source. The tool is mainly aimed at those users who
need to maintain tool sets for embedded type development, that is
cross-compiled compiled tool chains, debuggers, and debugging aids. It is not
limited to this role but designed to fit with-in that specific niche.
The Source Builder attempts to support any host environment that runs Python
and you can build the package on. It is not some sort of magic that can take
any piece of source code and make it build. Someone at some point in time has
figured out how to build that package from source and taught this tool.
The Source Builder has two types configuration data. The first is configuration
files and these are scripts based on the RPM spec file format that detail the
steps needed to build a package. The steps are 'preparation', 'building', and
'installing'. The second set of configuration files are 'build sets'. A build
set describes a collection of packages you want built together. For example the
GNU tool set is autoconf, automake, binutils, gcc, and gdb. This is the typical
suite of tools you need for an embedded cross-development type project.
The Source Builder does not interact with any host package management
system. There is no automatic dependence checking between various packages you
build or your host system may have installed. We assume you know what are doing
or the build sets and configuration files you are using have been created by
developers who do. A buld set should provide a known working configuration.
Why build from source ?
~~~~~~~~~~~~~~~~~~~~~~~
If you are developing a system or product that has a long shelf life or is used
in a critical piece of infastructure that has a long life cycle being able to
build from source is important. It insulates the project from the fast ever
changing world of the host development machines. If your tool set is binary and
you have lost the ability to build it you have lost a degree of control and
flexibility open source gives you. Fast moving host environments are
fantastic. We have powerful multi-core computers with huge amounts of memory
and state of the art operating systems to running on them. The product or
project you are part of may need to be maintained well past the life time of
these host. Being able to build from source an important and critical part of
this process because you can move to a newer host and create an equivalent tool
set.
Building from source provides you with control over the configuration of the
package you are building. If all or the most important dependent parts are
built from source you limit the exposure to host variations. For example the
GNU C compiler (gcc) currently uses a number of 3rd party libraries internally
(gmp, mpfr, etc). If your validated compiler generating code for your target
processor is dynamically linked against the host's version of these libraries
any change in the host's configuration may effect you. The changes the host's
package management system makes may be perfectly reasonible in relation to the
distribution being managed how-ever this may not extend to you and your
tools. Building your tools from source and controlling the specific version of
these dependent parts means you are not exposing yourself to unexpected and
often difficult to resolve problems. On the other side you need to make sure
your tools build and work with newer versions of the host operating
sytem. Given the stability of standards based libraries like 'libc' and ever
improving support for standard header file locations this task is becoming
easier.
History
~~~~~~~
The Source Builder is a stand alone tool based on another tool called the
'SpecBuilder'. The SpecBuilder was written for the RTEMS project too give me a
way to build tools on hosts that did not support RPMs. At the time the RTEMS
tools maintainer only used spec files to create various packages. This meant I
had either spec files, RPM files or SRPM files. The RPM and SPRM files where
useless because you needed an 'rpm' type tool to extract and manage them. There
are versions of 'rpm' for a number of non-RPM hosts how-ever these proved to be
in various broken states and randomally maintained. The solution I settled on
was to use spec files so I wrote a Python based tool that parsed the spec file
format and allowed me to create a shell script I could run to build the
package. This approach proved successful and I was able to track the RPM
version of the RTEMS tools on a non-RPM host over a number of years. How-ever
the SpecBuilder tool did not help me build tools or other packages not related
to the RTEMS project where there was no spec file I could use so I needed
another tool. Rather than start again I decided to take the parsing code for
the spec file format and build a new tool called the Source Builder.
Quick Start
-----------
Check out the Source Builder tool from git:
-------------------------------------------------------------
$ git clone git://git.rtems.org/source-builder.git
-------------------------------------------------------------
The first step is to check if your host is set up correctly:
-------------------------------------------------------------
$ source-builder/sb-check
warning: exe: absolute exe found in path: (__objcopy) /usr/local/bin/objcopy <1>
warning: exe: absolute exe found in path: (__objdump) /usr/local/bin/objdump
error: exe: not found: (_xz) /usr/local/bin/xz <2>
Source Builder environent is not correctly set up
$ source-builder/sb-check
Source Builder environent is ok <3>
-------------------------------------------------------------
<1> A tool is in the environment path but does not match the shown path.
<2> The executable 'xz' is not found.
<3> The host's environment is set up correct.
If there are problems you are given a list of executables that cannot be
found. You may also be given a list of warnings about executables not in the
expected location how-ever the executable was located somewhere in your
environment's path. You will need to check the specific host section to resolve
these issues.
Create a suitable build directory away from the Source Builder source change
into that directory and build a GNU tool set:
-------------------------------------------------------------
$ mkdir gnu-tools <1>
$ cd gnu-tools
$ ../source-builder/sb-set-builder <2> --log=l.txt <3> --force <4> \
--prefix=$HOME/gnu-tools-1 <5> --target=arm-eabi <6> gnu-toolset-4.6 <7>
-------------------------------------------------------------
<1> Make a build directory you can delete when finished.
<2> The Source Builder command to build a set of tools.
<3> Capture the output to a log file.
<4> The force option will create any needed directories and allow the build to
proceed if your host is not set up.
<5> Give the tools a suitable prefix. This is the location you install the
tools into once they have built.
<6> The gnu-toolset requires you set a target. In this case the tool set will
be a generic unpatched version of GCC 4.6 for a bare metal the ARM processor.
<7> The build set.
To view the build sets lets change to the RTEMS project's source builder
configuration and then list the build sets:
-------------------------------------------------------------
$ cd ../rtems-source-builder
$ ../source-builder/sb-set-builder --list-bsets
Source Builder - Set Builder, v0.1
Examining: /usr/home/chris/development/rtems/src/rtems-source-builder/config <1>
Examining: /usr/home/chris/development/rtems/src/source-builder/config <2>
gnu-tools-4.6 <3>
rtems-tools-4.10 <4>
-------------------------------------------------------------
<1> The local RTEMS configuration directory. Searched first.
<2> The Source Builder configuration directory.
<3> The Source Builder provided GNU tools GCC 4.6 build set.
<4> The RTEMS Source Builder provided RTEMS 4.10 build set.
And to view the configurations you can:
-------------------------------------------------------------
$ ../source-builder/sb-set-builder --list-configs
Source Builder - Set Builder, v0.1
Examining: /usr/home/chris/development/rtems/src/rtems-source-builder/config
Examining: /usr/home/chris/development/rtems/src/source-builder/config
autoconf-2-1 <1>
autoconf-2.68-1
autoconf-2.69-1
autoconf-internal-2.68-1
automake-1-1
automake-1.12-1
automake-internal-1.12-1
base
binutils-2-1
binutils-2.22-1
checks
expat-2-1
expat-2.1.0-1
gcc-4.4-1
gcc-4.6-1
gcc-4.6-newlib-1.20-1
gdb-7-1
gdb-7.5-1
libusb-1-1
libusb-1.0.9-1
m4-1-1
m4-1.4.16-1
texane-stlink-1
rtems-binutils-2.20.1-1
rtems-gcc-4.4.7-newlib-1.18.0-1
rtems-gdb-7.3.1-1
-------------------------------------------------------------
<1> Configurations are built by using the builder. This creates a stand alone
package.
The Source Builder
------------------
The Source Builder provides a few generic build sets and the configuration
support to build a number of packages. A project that uses the Source Builder
can create a specialised set of configuration files that provides the specific
configurations thet project uses.
For example the RTEMS project provides its own set of configuration files. In
the build set list in the 'Quick Start' section you can see a build set
+rtems-tools-4.10+. This build set defines the extact configration to use for
the RTEMS 4.10 release.

20
doc/wscript Normal file
View File

@ -0,0 +1,20 @@
#
# Waf build script to build the Source Builder Documentation.
#
version = "1.0.0"
def configure(ctx):
ctx.env.ASCIIDOC = ctx.find_program(['asciidoc.py'], mandatory = True)
ctx.env.ASCIIDOC_FLAGS = ['-b', 'html', '-a', 'data-uri', '-a', 'icons', '-a', 'max-width=55em-a']
def build(ctx):
ctx(target = 'source-builder.html', source = 'source-builder.txt')
import waflib.TaskGen
waflib.TaskGen.declare_chain(name = 'html',
rule = '${ASCIIDOC} ${ASCIIDOC_FLAGS} -o ${TGT} ${SRC}',
shell = False,
ext_in = '.txt',
ext_out = '.html',
reentrant = False)

View File

@ -0,0 +1,13 @@
--- texane-stlink-3494c11.orig/configure.ac 2012-10-31 11:40:49.000000000 +1100
+++ texane-stlink-3494c11/configure.ac 2012-10-31 10:34:57.000000000 +1100
@@ -21,9 +21,7 @@
AC_REPLACE_FUNCS(mmap)
# Checks for libraries.
-PKG_CHECK_MODULES(USB, libusb-1.0 >= 1.0.0,,
- AC_MSG_ERROR([*** Required libusb-1.0 >= 1.0.0 not installed ***]))
-AC_CHECK_LIB([usbpath],[usb_path2devnum],,,-lusb)
+AC_CHECK_HEADER([libusb.h], [USB_LIBS="-lusb-1.0"])
LIBS="$LIBS $USB_LIBS"
CFLAGS="$CFLAGS $USB_CFLAGS"

View File

@ -0,0 +1,577 @@
diff --git a/configure.ac b/configure.ac
index 1f00f3a..eb140e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,9 +21,7 @@ AC_CHECK_HEADERS(sys/poll.h)
AC_REPLACE_FUNCS(mmap)
# Checks for libraries.
-PKG_CHECK_MODULES(USB, libusb-1.0 >= 1.0.0,,
- AC_MSG_ERROR([*** Required libusb-1.0 >= 1.0.0 not installed ***]))
-AC_CHECK_LIB([usbpath],[usb_path2devnum],,,-lusb)
+AC_CHECK_HEADER([libusb.h], [USB_LIBS="-lusb-1.0"])
LIBS="$LIBS $USB_LIBS"
CFLAGS="$CFLAGS $USB_CFLAGS"
diff --git a/gdbserver/gdb-server.c b/gdbserver/gdb-server.c
index 9d27ae4..fd25e8b 100644
--- a/gdbserver/gdb-server.c
+++ b/gdbserver/gdb-server.c
@@ -1,11 +1,12 @@
/* -*- tab-width:8 -*- */
-#define DEBUG 0
+
/*
Copyright (C) 2011 Peter Zotov <whitequark@whitequark.org>
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
*/
+#include <stdarg.h>
#include <getopt.h>
#include <stdio.h>
#include <string.h>
@@ -18,14 +19,15 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <signal.h>
#endif
+#include <signal.h>
#include <stlink-common.h>
#include "gdb-remote.h"
-#define DEFAULT_LOGGING_LEVEL 50
+#define DEFAULT_LOGGING_LEVEL 0
+#define LOGGING_LEVEL_GDBSERVER 2
#define DEFAULT_GDB_LISTEN_PORT 4242
#define STRINGIFY_inner(name) #name
@@ -40,24 +42,47 @@ static const char hex[] = "0123456789abcdef";
static const char* current_memory_map = NULL;
+FILE *my_stderr;
+FILE *my_stdout;
+
typedef struct _st_state_t {
- // things from command line, bleh
- int stlink_version;
- // "/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTE531X6-if00-port0" is only 58 chars
- char devicename[100];
- int logging_level;
+ // things from command line, bleh
+ int pipe;
+ int stlink_version;
+ // "/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTE531X6-if00-port0" is only 58 chars
+ char devicename[100];
+ int logging_level;
int listen_port;
} st_state_t;
+int logging_level = DEFAULT_LOGGING_LEVEL;
+
+int remote_desc = -1;
+int remote_piping = 0;
-int serve(stlink_t *sl, int port);
+int remote_open(int port);
+int serve(stlink_t *sl);
char* make_memory_map(stlink_t *sl);
+/*
+ * Own printf and redirect when piping.
+ */
+int
+printf (const char *format,...)
+{
+ int ret;
+ va_list args;
+ va_start (args, format);
+ ret = vfprintf (my_stdout, format, args);
+ fflush (my_stdout);
+ return ret;
+}
int parse_options(int argc, char** argv, st_state_t *st) {
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"verbose", optional_argument, NULL, 'v'},
+ {"pipe", no_argument, NULL, 'P'},
{"device", required_argument, NULL, 'd'},
{"stlink_version", required_argument, NULL, 's'},
{"stlinkv1", no_argument, NULL, '1'},
@@ -78,11 +103,10 @@ int parse_options(int argc, char** argv, st_state_t *st) {
"(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n"
;
-
int option_index = 0;
int c;
int q;
- while ((c = getopt_long(argc, argv, "hv::d:s:1p:", long_options, &option_index)) != -1) {
+ while ((c = getopt_long(argc, argv, "hv::d:s:1Pp:", long_options, &option_index)) != -1) {
switch (c) {
case 0:
printf("XXXXX Shouldn't really normally come here, only if there's no corresponding option\n");
@@ -96,12 +120,16 @@ int parse_options(int argc, char** argv, st_state_t *st) {
printf(help_str, argv[0]);
exit(EXIT_SUCCESS);
break;
+ case 'P':
+ st->pipe = 1;
+ break;
case 'v':
if (optarg) {
st->logging_level = atoi(optarg);
} else {
st->logging_level = DEFAULT_LOGGING_LEVEL;
}
+ logging_level = st->logging_level;
break;
case 'd':
if (strlen(optarg) > sizeof (st->devicename)) {
@@ -149,10 +177,21 @@ int main(int argc, char** argv) {
st_state_t state;
memset(&state, 0, sizeof(state));
// set defaults...
+ state.pipe = 0;
state.stlink_version = 2;
state.logging_level = DEFAULT_LOGGING_LEVEL;
state.listen_port = DEFAULT_GDB_LISTEN_PORT;
parse_options(argc, argv, &state);
+
+ my_stdout = stdout;
+ my_stderr = stderr;
+
+ if (state.pipe) {
+ my_stdout = my_stderr = stderr;
+ state.listen_port = 0;
+ remote_piping = 1;
+ }
+
switch (state.stlink_version) {
case 2:
sl = stlink_open_usb(state.logging_level);
@@ -162,7 +201,18 @@ int main(int argc, char** argv) {
sl = stlink_v1_open(state.logging_level);
if(sl == NULL) return 1;
break;
- }
+ }
+
+#ifdef __MINGW32__
+ if (!remote_piping) {
+ WSADATA wsadata;
+ if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0 ) {
+ goto winsock_error;
+ }
+ }
+#endif
+
+ remote_open(state.listen_port);
printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id);
@@ -170,18 +220,13 @@ int main(int argc, char** argv) {
current_memory_map = make_memory_map(sl);
-#ifdef __MINGW32__
- WSADATA wsadata;
- if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0 ) {
- goto winsock_error;
- }
-#endif
-
- while(serve(sl, state.listen_port) == 0);
+ while(serve(sl) == 0);
#ifdef __MINGW32__
+ if (!remote_piping) {
winsock_error:
- WSACleanup();
+ WSACleanup();
+ }
#endif
/* Switch back to mass storage mode before closing. */
@@ -342,9 +387,8 @@ struct code_hw_watchpoint {
struct code_hw_watchpoint data_watches[DATA_WATCH_NUM];
static void init_data_watchpoints(stlink_t *sl) {
- #ifdef DEBUG
- printf("init watchpoints\n");
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("init watchpoints\n");
// set trcena in debug command to turn on dwt unit
stlink_write_debug32(sl, 0xE000EDFC,
@@ -377,9 +421,8 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr
for(i = 0; i < DATA_WATCH_NUM; i++) {
// is this an empty slot ?
if(data_watches[i].fun == WATCHDISABLED) {
- #ifdef DEBUG
- printf("insert watchpoint %d addr %x wf %u mask %u len %d\n", i, addr, wf, mask, len);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("insert watchpoint %d addr %x wf %u mask %u len %d\n", i, addr, wf, mask, len);
data_watches[i].fun = wf;
data_watches[i].addr = addr;
@@ -401,9 +444,10 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr
}
}
- #ifdef DEBUG
- printf("failure: add watchpoints addr %x wf %u len %u\n", addr, wf, len);
- #endif
+
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("failure: add watchpoints addr %x wf %u len %u\n", addr, wf, len);
+
return -1;
}
@@ -413,9 +457,8 @@ static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr)
for(i = 0 ; i < DATA_WATCH_NUM; i++) {
if((data_watches[i].addr == addr) && (data_watches[i].fun != WATCHDISABLED)) {
- #ifdef DEBUG
- printf("delete watchpoint %d addr %x\n", i, addr);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("delete watchpoint %d addr %x\n", i, addr);
data_watches[i].fun = WATCHDISABLED;
stlink_write_debug32(sl, 0xe0001028 + i * 16, 0);
@@ -424,9 +467,8 @@ static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr)
}
}
- #ifdef DEBUG
- printf("failure: delete watchpoint addr %x\n", addr);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("failure: delete watchpoint addr %x\n", addr);
return -1;
}
@@ -485,20 +527,19 @@ static int update_code_breakpoint(stlink_t *sl, stm32_addr_t addr, int set) {
else brk->type &= ~type;
if(brk->type == 0) {
- #ifdef DEBUG
- printf("clearing hw break %d\n", id);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("clearing hw break %d\n", id);
stlink_write_debug32(sl, 0xe0002008 + id * 4, 0);
} else {
uint32_t mask = (brk->addr) | 1 | (brk->type << 30);
- #ifdef DEBUG
- printf("setting hw break %d at %08x (%d)\n",
- id, brk->addr, brk->type);
- printf("reg %08x \n",
- mask);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER) {
+ printf("setting hw break %d at %08x (%d)\n",
+ id, brk->addr, brk->type);
+ printf("reg %08x \n",
+ mask);
+ }
stlink_write_debug32(sl, 0xe0002008 + id * 4, mask);
}
@@ -589,9 +630,8 @@ static int flash_go(stlink_t *sl) {
stlink_reset(sl);
for(struct flash_block* fb = flash_root; fb; fb = fb->next) {
- #ifdef DEBUG
- printf("flash_do: block %08x -> %04x\n", fb->addr, fb->length);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("flash_do: block %08x -> %04x\n", fb->addr, fb->length);
unsigned length = fb->length;
for(stm32_addr_t page = fb->addr; page < fb->addr + fb->length; page += FLASH_PAGE) {
@@ -599,9 +639,8 @@ static int flash_go(stlink_t *sl) {
//Update FLASH_PAGE
stlink_calculate_pagesize(sl, page);
- #ifdef DEBUG
- printf("flash_do: page %08x\n", page);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("flash_do: page %08x\n", page);
if(stlink_write_flash(sl, page, fb->data + (page - fb->addr),
length > FLASH_PAGE ? FLASH_PAGE : length) < 0)
@@ -625,50 +664,74 @@ error:
return error;
}
-int serve(stlink_t *sl, int port) {
- int sock = socket(AF_INET, SOCK_STREAM, 0);
- if(sock < 0) {
- perror("socket");
- return 1;
- }
-
- unsigned int val = 1;
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
+int remote_open(int port) {
+ int sock = -1;
+ if (port == 0) {
+ remote_desc = STDOUT_FILENO;
+ remote_piping = 1;
+ signal(SIGINT, SIG_IGN);
+#ifdef __MINGW32__
+ if (_setmode (_fileno( stdout ), _O_BINARY) < 0)
+ fprintf(stderr, "cannot change stdout mode to binary");
+ if (_setmode (_fileno( stdin ), _O_BINARY) < 0)
+ fprintf(stderr, "cannot change stdin mode to binary");
+#else
+ signal(SIGIO, SIG_IGN);
+ signal(SIGCHLD, SIG_IGN);
+#endif
+ }
+ else {
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if(sock < 0) {
+ perror("socket");
+ return 1;
+ }
- struct sockaddr_in serv_addr;
- memset(&serv_addr,0,sizeof(struct sockaddr_in));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
- serv_addr.sin_port = htons(port);
+ unsigned int val = 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
- if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
- perror("bind");
- return 1;
- }
+ struct sockaddr_in serv_addr;
+ memset(&serv_addr,0,sizeof(struct sockaddr_in));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ serv_addr.sin_port = htons(port);
- if(listen(sock, 5) < 0) {
- perror("listen");
- return 1;
- }
+ if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
+ perror("bind");
+ return 1;
+ }
- stlink_force_debug(sl);
- stlink_reset(sl);
- init_code_breakpoints(sl);
- init_data_watchpoints(sl);
+ if(listen(sock, 5) < 0) {
+ perror("listen");
+ return 1;
+ }
+ }
- printf("Listening at *:%d...\n", port);
+ if (!remote_piping) {
+ printf("Listening at *:%d...\n", port);
- int client = accept(sock, NULL, NULL);
- //signal (SIGINT, SIG_DFL);
- if(client < 0) {
- perror("accept");
- return 1;
- }
+ remote_desc = accept(sock, NULL, NULL);
+ //signal (SIGINT, SIG_DFL);
+ if(remote_desc < 0) {
+ perror("accept");
+ return 1;
+ }
- close(sock);
+ close(sock);
+ }
printf("GDB connected.\n");
+ return 0;
+}
+
+int serve(stlink_t *sl) {
+
+ stlink_force_debug(sl);
+ stlink_reset(sl);
+ init_code_breakpoints(sl);
+ init_data_watchpoints(sl);
+
/*
* To allow resetting the chip from GDB it is required to
* emulate attaching and detaching to target.
@@ -678,15 +741,14 @@ int serve(stlink_t *sl, int port) {
while(1) {
char* packet;
- int status = gdb_recv_packet(client, &packet);
+ int status = gdb_recv_packet(remote_desc, &packet);
if(status < 0) {
fprintf(stderr, "cannot recv: %d\n", status);
return 1;
}
- #ifdef DEBUG
- printf("recv: %s\n", packet);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("recv: %s\n", packet);
char* reply = NULL;
reg regp;
@@ -709,9 +771,8 @@ int serve(stlink_t *sl, int port) {
char* queryName = calloc(queryNameLength + 1, 1);
strncpy(queryName, &packet[1], queryNameLength);
- #ifdef DEBUG
- printf("query: %s;%s\n", queryName, params);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("query: %s;%s\n", queryName, params);
if(!strcmp(queryName, "Supported")) {
if(sl->chip_id==STM32_CHIPID_F4) {
@@ -734,10 +795,9 @@ int serve(stlink_t *sl, int port) {
unsigned addr = strtoul(__s_addr, NULL, 16),
length = strtoul(s_length, NULL, 16);
- #ifdef DEBUG
- printf("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n",
- type, op, annex, addr, length);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n",
+ type, op, annex, addr, length);
const char* data = NULL;
@@ -771,9 +831,8 @@ int serve(stlink_t *sl, int port) {
if (!strncmp(params,"726573756d65",12)) {// resume
-#ifdef DEBUG
- printf("Rcmd: resume\n");
-#endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("Rcmd: resume\n");
stlink_run(sl);
reply = strdup("OK");
@@ -782,9 +841,9 @@ int serve(stlink_t *sl, int port) {
stlink_force_debug(sl);
-#ifdef DEBUG
- printf("Rcmd: halt\n");
-#endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("Rcmd: halt\n");
+
} else if (!strncmp(params,"6a7461675f7265736574",20)) { //jtag_reset
reply = strdup("OK");
@@ -792,9 +851,9 @@ int serve(stlink_t *sl, int port) {
stlink_jtag_reset(sl, 0);
stlink_force_debug(sl);
-#ifdef DEBUG
- printf("Rcmd: jtag_reset\n");
-#endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("Rcmd: jtag_reset\n");
+
} else if (!strncmp(params,"7265736574",10)) { //reset
reply = strdup("OK");
@@ -803,14 +862,12 @@ int serve(stlink_t *sl, int port) {
init_code_breakpoints(sl);
init_data_watchpoints(sl);
-#ifdef DEBUG
- printf("Rcmd: reset\n");
-#endif
- } else {
-#ifdef DEBUG
- printf("Rcmd: %s\n", params);
-#endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("Rcmd: reset\n");
+ } else {
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("Rcmd: %s\n", params);
}
}
@@ -839,10 +896,9 @@ int serve(stlink_t *sl, int port) {
unsigned addr = strtoul(__s_addr, NULL, 16),
length = strtoul(s_length, NULL, 16);
- #ifdef DEBUG
- printf("FlashErase: addr:%08x,len:%04x\n",
- addr, length);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("FlashErase: addr:%08x,len:%04x\n",
+ addr, length);
if(flash_add_block(addr, length, sl) < 0) {
reply = strdup("E00");
@@ -877,9 +933,8 @@ int serve(stlink_t *sl, int port) {
if(dec_index % 2 != 0)
dec_index++;
- #ifdef DEBUG
- printf("binary packet %d -> %d\n", data_length, dec_index);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("binary packet %d -> %d\n", data_length, dec_index);
if(flash_populate(addr, decoded, dec_index) < 0) {
reply = strdup("E00");
@@ -908,7 +963,7 @@ int serve(stlink_t *sl, int port) {
stlink_run(sl);
while(1) {
- int status = gdb_check_for_interrupt(client);
+ int status = gdb_check_for_interrupt(remote_desc);
if(status < 0) {
fprintf(stderr, "cannot check for int: %d\n", status);
return 1;
@@ -1190,11 +1245,10 @@ int serve(stlink_t *sl, int port) {
}
if(reply) {
- #ifdef DEBUG
- printf("send: %s\n", reply);
- #endif
+ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
+ printf("send: %s\n", reply);
- int result = gdb_send_packet(client, reply);
+ int result = gdb_send_packet(remote_desc, reply);
if(result != 0) {
fprintf(stderr, "cannot send: %d\n", result);
return 1;

29
sb-builder Executable file
View 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 + '/sb')
try:
import build
build.run(sys.argv)
except ImportError:
print >> sys.stderr, "Incorrect Source Builder installation"
sys.exit(1)

29
sb-check Executable file
View 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 + '/sb')
try:
import check
check.run()
except ImportError:
print >> sys.stderr, "Incorrect Set Bulder installation"
sys.exit(1)

29
sb-set-builder Executable file
View 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 + '/sb')
try:
import setbuilder
setbuilder.run()
except ImportError:
print >> sys.stderr, "Incorrect Set Bulder installation"
sys.exit(1)

483
sb/build.py Normal file
View File

@ -0,0 +1,483 @@
#
# 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 glob
import os
import shutil
import stat
import sys
import urllib2
import urlparse
import check
import config
import defaults
import error
import execute
import log
import path
#
# Version of Sourcer Builder Build.
#
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(path.host(name), 'w')
s.write('\n'.join(self.body))
s.close()
os.chmod(path.host(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, rmpath):
self._output('removing: %s' % (path.host(rmpath)))
if not self.opts.dry_run():
if path.exists(rmpath):
try:
shutil.rmtree(path.host(rmpath))
except IOError, err:
raise error.error('error removing: %s' % (rmpath))
except WindowsError, err:
_notice(self.opts, 'warning: cannot remove: %s' % (rmpath))
def mkdir(self, mkpath):
self._output('making dir: %s' % (path.host(mkpath)))
if not self.opts.dry_run():
try:
os.makedirs(path.host(mkpath))
except IOError, err:
_notice(self.opts, 'warning: cannot make directory: %s' % (mkpath))
except WindowsError, err:
_notice(self.opts, 'warning: cannot make directory: %s' % (mkpath))
def get_file(self, url, local):
if local is None:
raise error.general('source/patch path invalid')
if not path.isdir(path.dirname(local)):
if not self.opts.force():
raise error.general('source path not found: %s; (--force to create)' \
% (path.host(path.dirname(local))))
self.mkdir(path.host(path.dirname(local)))
if not 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)
if self.opts.trace():
print '_url:', ','.join(urls), '->', local
for url in urls:
#
# Hack for GitHub.
#
if url.startswith('https://api.github.com'):
url = urlparse.urljoin(url, self.config.expand('tarball/%{version}'))
_notice(self.opts, 'download: %s -> %s' % (url, path.host(local)))
if not self.opts.dry_run():
failed = False
_in = None
_out = None
try:
_in = urllib2.urlopen(url)
_out = open(path.host(local), 'wb')
_out.write(_in.read())
except IOError, err:
msg = 'download: %s: error: %s' % (url, str(err))
_notice(self.opts, msg)
if path.exists(local):
os.remove(path.host(local))
failed = True
except:
print >> sys.stderr, msg
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 path.isfile(local):
raise error.general('source is not a file: %s' % (path.host(local)))
return
if not self.opts.dry_run():
raise error.general('downloading %s: all paths have failed, giving up' % (url))
def parse_url(self, url, pathkey):
#
# Split the source up into the parts we need.
#
source = {}
source['url'] = url
source['path'] = path.dirname(url)
source['file'] = path.basename(url)
source['name'], source['ext'] = path.splitext(source['file'])
#
# Get the file. Checks the local source directory first.
#
source['local'] = None
for p in self.config.define(pathkey).split(':'):
local = path.join(path.abspath(p), source['file'])
if source['local'] is None or path.exists(local):
source['local'] = local
break
#
# 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%d' % (source_tag))
source = self.parse_url(url, '_sourcedir')
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: %s' % (args[0]))
#
# Parse the URL first in the source builder's patch directory.
#
patch = self.parse_url(url, '_patchdir')
#
# If not in the source builder package check the source directory.
#
if not path.exists(patch['local']):
patch = self.parse_url(url, '_sourcedir')
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: %s: %s' % (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: %s' % (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 = path.host(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 = path.join('%{buildroot}', prefixbase)
tardir = path.abspath(self.config.expand('%{_tardir}'))
self.script.append(self.config.expand('if test -d %s; then' % (inpath)))
self.script.append(' mkdir -p %s' % tardir)
self.script.append(self.config.expand(' cd ' + inpath))
tar = 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}'))
self.script.append('fi')
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 = path.join(self.config.expand('%{_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 list_configs(opts, _defaults, ext = '.cfg'):
configs = []
for cp in opts.expand('%{_configdir}', _defaults).split(':'):
print 'Examining: %s' % (path.host(path.abspath(cp)))
configs += glob.glob(path.host(path.join(cp, '*%s' % (ext))))
for c in sorted(configs):
config = path.basename(c)
if config.endswith(ext):
config = config[:0 - len(ext)]
print ' ', config
def run(args):
try:
optargs = { '--list-configs': 'List available configurations' }
opts, _defaults = defaults.load(args, optargs)
log.default = log.log(opts.logfiles())
_notice(opts, 'Source Builder, Package Builder v%s' % (version))
if not check.host_setup(opts, _defaults):
if not opts.force():
raise error.general('host build environment is not set up correctly (use --force to proceed)')
_notice(opts, 'warning: forcing build with known host setup problems')
if opts.get_arg('--list-configs'):
list_configs(opts, _defaults)
else:
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)

157
sb/check.py Normal file
View File

@ -0,0 +1,157 @@
#
# 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.
#
# Check the defaults for a specific host.
#
import os
import defaults
import error
import execute
import log
import path
#
# Version of Sourcer Builder Check.
#
version = '0.1'
def _notice(opts, text):
if not opts.quiet() and log.default and not log.default.has_stdout():
print text
log.output(text)
log.flush()
def _check_none(_opts, macro, value, constraint):
return True
def _check_triplet(_opts, macro, value, constraint):
return True
def _check_dir(_opts, macro, value, constraint):
if constraint != 'none' and not path.isdir(value):
if constraint == 'required':
_notice(_opts, 'error: dir: not found: (%s) %s' % (macro, value))
return False
if _opts.warn_all():
_notice(_opts, 'warning: dir: not found: (%s) %s' % (macro, value))
return True
def _check_exe(_opts, macro, value, constraint):
if len(value) == 0 or constraint == 'none':
return True
orig_value = value
if path.isabspath(value):
if path.isfile(value):
return True
if os.name == 'nt':
if path.isfile('%s.exe' % (value)):
return True
value = path.basename(value)
absexe = True
else:
absexe = False
paths = os.environ['PATH'].split(os.pathsep)
if _check_paths(value, paths):
if absexe:
_notice(_opts,
'warning: exe: absolute exe found in path: (%s) %s' % (macro, orig_value))
return True
if constraint == 'optional':
if _opts.trace():
_notice(_opts, 'warning: exe: optional exe not found: (%s) %s' % (macro, orig_value))
return True
_notice(_opts, 'error: exe: not found: (%s) %s' % (macro, orig_value))
return False
def _check_paths(name, paths):
for p in paths:
exe = path.join(p, name)
if path.isfile(exe):
return True
if os.name == 'nt':
if path.isfile('%s.exe' % (exe)):
return True
return False
def host_setup(_opts, _defaults):
""" Basic sanity check. All executables and directories must exist."""
checks = { 'none': _check_none,
'triplet': _check_triplet,
'dir': _check_dir,
'exe': _check_exe }
sane = True
for d in sorted(_defaults.iterkeys()):
try:
(test, constraint, value) = _defaults[d]
except:
raise error.general('invalid default: %s [%r]' % (d, _defaults[d]))
if test != 'none':
value = _opts.expand(value, _defaults)
if test not in checks:
raise error.general('invalid check test: %s [%r]' % (test, _defaults[d]))
ok = checks[test](_opts, d, value, constraint)
if _opts.trace():
if ok:
tag = ' '
else:
tag = '*'
_notice(_opts, '%c %15s: %r -> "%s"' % (tag, d, _defaults[d], value))
if sane and not ok:
sane = False
return sane
def run():
import sys
try:
_opts, _defaults = defaults.load(args = sys.argv)
if host_setup(_opts, _defaults):
print 'Source Builder environent is ok'
else:
print 'Source Builder environent is not correctly set up'
except error.general, gerr:
print gerr
sys.exit(1)
except error.internal, ierr:
print ierr
sys.exit(1)
sys.exit(0)
if __name__ == '__main__':
run()

873
sb/config.py Normal file
View File

@ -0,0 +1,873 @@
#
# 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
import path
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 %s in package "%s"' % (info, 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][2]
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 _name_line_msg(self, msg):
return '%s:%d: %s' % (path.basename(self.name), self.lc, msg)
def _output(self, text):
if not self.opts.quiet():
log.output(text)
def _warning(self, msg):
self._output('warning: %s' % (self._name_line_msg(msg)))
def _error(self, msg):
err = 'error: %s' % (self._name_line_msg(msg))
print >> sys.stderr, err
self._output(err)
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: %s' % (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 '%s'" % (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 '%s' not found" % (mn))
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) or \
(d in self.defines and len(self.defines[d]) == 0):
if len(ls) == 2:
self.defines[d] = '1'
else:
self.defines[d] = ls[2].strip()
else:
if self.opts.warn_all():
self._warning("macro '%s' already defined" % (d))
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 '%s' not defined" % (mn))
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' % (self._name_line_msg(l[7:]))])
elif ls[0] == '%warning':
if isvalid:
return ('data', ['%%warning %s' % (self._name_line_msg(l[9:]))])
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 = path.basename(configname)
if not path.exists(configname):
if ':' in configname:
configdirs = path.dirname(configname).split(':')
else:
configdirs = self.define('_configdir').split(':')
for cp in configdirs:
configname = path.join(path.abspath(cp), cfgname)
if 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' % (path.host(configname))
config = open(path.host(configname), 'r')
except IOError, err:
raise error.general('error opening config file: %s' % (path.host(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: '%s'" % (' '.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:]))
elif l.startswith('%warning'):
print >> sys.stderr, 'warning: %s' % (l[9:])
self._warning(l[9:])
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 set_define(self, name, value):
self.defines[name.lower()] = value
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, rpath):
return path.abspath(self.define(rpath))
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()

59
sb/darwin.py Normal file
View File

@ -0,0 +1,59 @@
#
# 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': ('none', 'none', 'darwin'),
'_host': ('triplet', 'required', uname[4] + '-apple-darwin' + uname[2]),
'_host_vendor': ('none', 'none', 'apple'),
'_host_os': ('none', 'none', 'darwin'),
'_host_cpu': ('none', 'none', uname[4]),
'_host_alias': ('none', 'none', '%{nil}'),
'_host_arch': ('none', 'none', uname[4]),
'_usr': ('dir', 'optional', '/usr/local'),
'_var': ('dir', 'optional', '/usr/local/var'),
'_prefix': ('dir', 'optional', '%{_usr}'),
'optflags': ('none', 'none', '-O2'),
'_smp_mflags': ('none', 'none', smp_mflags),
'__ldconfig': ('exe', 'none', ''),
'__xz': ('exe', 'required', '%{_usr}/bin/xz'),
'with_zlib': ('none', 'none', '--with-zlib=no')
}
return defines
if __name__ == '__main__':
pprint.pprint(load())

575
sb/defaults.py Normal file
View File

@ -0,0 +1,575 @@
#
# 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
import path
basepath = 'sb'
#
# All paths in defaults must be Unix format. Do not store any Windows format
# paths in the defaults.
#
# Every entry must describe the type of checking a host must pass.
#
defaults = {
# Nothing
'nil': ('none', 'none', ''),
# Set to invalid values.
'_bset': ('none', 'none', ''),
'name': ('none', 'none', ''),
'version': ('none', 'none', ''),
'release': ('none', 'none', ''),
# GNU triples needed to build packages
'_host': ('triplet', 'required', ''),
'_build': ('triplet', 'required', '%{_host}'),
'_target': ('none', 'optional', ''),
# Paths
'_host_platform': ('none', 'none', '%{_host_cpu}-%{_host_vendor}-%{_host_os}%{?_gnu}'),
'_build': ('none', 'none', '%{_host}'),
'_arch': ('none', 'none', '%{_host_arch}'),
'_sbdir': ('none', 'none', ''),
'_topdir': ('dir', 'required', path.shell(os.getcwd())),
'_configdir': ('dir', 'optional', '%{_topdir}/config:%{_sbdir}/config'),
'_tardir': ('dir', 'optional', '%{_topdir}/tar'),
'_sourcedir': ('dir', 'optional', '%{_topdir}/sources'),
'_patchdir': ('dir', 'optional', '%{_topdir}/patches:%{_sbdir}/patches'),
'_builddir': ('dir', 'optional', '%{_topdir}/build/%{name}-%{version}-%{release}'),
'_docdir': ('dir', 'none', '%{_defaultdocdir}'),
'_tmppath': ('dir', 'none', '%{_topdir}/build/tmp'),
'_tmproot': ('dir', 'none', '%{_tmppath}/source-build-%(%{__id_u} -n)/%{_bset}'),
'buildroot:': ('dir', 'none', '%{_tmppath}/%{name}-root-%(%{__id_u} -n)'),
'_datadir': ('dir', 'none', '%{_prefix}/share'),
'_defaultdocdir': ('dir', 'none', '%{_prefix}/share/doc'),
'_exeext': ('none', 'none', ''),
'_exec_prefix': ('dir', 'none', '%{_prefix}'),
'_bindir': ('dir', 'none', '%{_exec_prefix}/bin'),
'_sbindir': ('dir', 'none', '%{_exec_prefix}/sbin'),
'_libexecdir': ('dir', 'none', '%{_exec_prefix}/libexec'),
'_datarootdir': ('dir', 'none', '%{_prefix}/share'),
'_datadir': ('dir', 'none', '%{_datarootdir}'),
'_sysconfdir': ('dir', 'none', '%{_prefix}/etc'),
'_sharedstatedir': ('dir', 'none', '%{_prefix}/com'),
'_localstatedir': ('dir', 'none', '%{prefix}/var'),
'_includedir': ('dir', 'none', '%{_prefix}/include'),
'_lib': ('dir', 'none', 'lib'),
'_libdir': ('dir', 'none', '%{_exec_prefix}/%{_lib}'),
'_libexecdir': ('dir', 'none', '%{_exec_prefix}/libexec'),
'_mandir': ('dir', 'none', '%{_datarootdir}/man'),
'_infodir': ('dir', 'none', '%{_datarootdir}/info'),
'_localedir': ('dir', 'none', '%{_datarootdir}/locale'),
'_localedir': ('dir', 'none', '%{_datadir}/locale'),
'_localstatedir': ('dir', 'none', '%{_prefix}/var'),
'_prefix': ('dir', 'none', '%{_usr}'),
'_usr': ('dir', 'none', '/usr/local'),
'_usrsrc': ('dir', 'none', '%{_usr}/src'),
'_var': ('dir', 'none', '/usr/local/var'),
'_varrun': ('dir', 'none', '%{_var}/run'),
# Defaults, override in platform specific modules.
'___setup_shell': ('exe', 'required', '/bin/sh'),
'__aclocal': ('exe', 'optional', 'aclocal'),
'__ar': ('exe', 'required', 'ar'),
'__arch_install_post': ('exe', 'none', '%{nil}'),
'__as': ('exe', 'required', 'as'),
'__autoconf': ('exe', 'required', 'autoconf'),
'__autoheader': ('exe', 'required', 'autoheader'),
'__automake': ('exe', 'required', 'automake'),
'__awk': ('exe', 'required', 'awk'),
'__bash': ('exe', 'optional', '/bin/bash'),
'__bzip2': ('exe', 'required', '/usr/bin/bzip2'),
'__cat': ('exe', 'required', '/bin/cat'),
'__cc': ('exe', 'required', '/usr/bin/gcc'),
'__chgrp': ('exe', 'required', '/usr/bin/chgrp'),
'__chmod': ('exe', 'required', '/bin/chmod'),
'__chown': ('exe', 'required', '/usr/sbin/chown'),
'__cp': ('exe', 'required', '/bin/cp'),
'__cpp': ('exe', 'none', '%{__cc} -E'),
'__cxx': ('exe', 'required', '/usr/bin/g++'),
'__grep': ('exe', 'required', '/usr/bin/grep'),
'__gzip': ('exe', 'required', '/usr/bin/gzip'),
'__id': ('exe', 'required', '/usr/bin/id'),
'__id_u': ('exe', 'none', '%{__id} -u'),
'__install': ('exe', 'required', '/usr/bin/install'),
'__install_info': ('exe', 'optional', '/usr/bin/install-info'),
'__ld': ('exe', 'required', '/usr/bin/ld'),
'__ldconfig': ('exe', 'required', '/sbin/ldconfig'),
'__ln_s': ('exe', 'none', 'ln -s'),
'__make': ('exe', 'required', 'make'),
'__mkdir': ('exe', 'required', '/bin/mkdir'),
'__mkdir_p': ('exe', 'none', '/bin/mkdir -p'),
'__mv': ('exe', 'required', '/bin/mv'),
'__nm': ('exe', 'required', '/usr/bin/nm'),
'__objcopy': ('exe', 'optional', '/usr/bin//objcopy'),
'__objdump': ('exe', 'optional', '/usr/bin/objdump'),
'__patch': ('exe', 'required', '/usr/bin/patch'),
'__perl': ('exe', 'optional', 'perl'),
'__ranlib': ('exe', 'required', 'ranlib'),
'__rm': ('exe', 'required', '/bin/rm'),
'__sed': ('exe', 'required', '/usr/bin/sed'),
'__setup_post': ('exe', 'none', '%{__chmod} -R a+rX,g-w,o-w .'),
'__sh': ('exe', 'required', '/bin/sh'),
'__tar': ('exe', 'required', '/usr/bin/tar'),
'__tar_extract': ('exe', 'none', '%{__tar} -xvvf'),
'__unzip': ('exe', 'required', '/usr/bin/unzip'),
'__xz': ('exe', 'required', '/usr/bin/xz'),
# Shell Build Settings.
'___build_args': ('none', 'none', '-e'),
'___build_cmd': ('none', 'none', '%{?_sudo:%{_sudo} }%{?_remsh:%{_remsh} %{_remhost} }%{?_remsudo:%{_remsudo} }%{?_remchroot:%{_remchroot} %{_remroot} }%{___build_shell} %{___build_args}'),
'___build_post': ('none', 'none', 'exit 0'),
# Prebuild set up script.
'___build_pre': ('none', 'none', '''# ___build_pre in as set up in defaults.py
# Directories
SB_SOURCE_DIR="%{_sourcedir}"
SB_BUILD_DIR="%{_builddir}"
SB_OPT_FLAGS="%{optflags}"
SB_ARCH="%{_arch}"
SB_OS="%{_os}"
export SB_SOURCE_DIR SB_BUILD_DIR SB_OPT_FLAGS SB_ARCH SB_OS
# Documentation
SB_DOC_DIR="%{_docdir}"
export SB_DOC_DIR
# Packages
SB_PACKAGE_NAME="%{name}"
SB_PACKAGE_VERSION="%{version}"
SB_PACKAGE_RELEASE="%{release}"
export SBPACKAGE_NAME SB_PACKAGE_VERSION SB_PACKAGE_RELEASE
# Build root directory
%{?buildroot:SB_BUILD_ROOT="%{buildroot}"}
export SB_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': ('none', 'none', '%{?_buildshell:%{_buildshell}}%{!?_buildshell:/bin/sh}'),
'___build_template': ('none', 'none', '''#!%{___build_shell}
%{___build_pre}
%{nil}'''),
# Configure command
'configure': ('none', 'none', '''
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',
'force' : '0',
'trace' : '0',
'dry-run' : '0',
'no-clean' : '0',
'no-smp' : '0',
'rebuild' : '0' }
#
# The define and if it is a path and needs conversion.
#
_long_opts = { '--prefix' : ('_prefix', True),
'--prefixbase' : ('_prefixbase', True),
'--topdir' : ('_topdir', True),
'--configdir' : ('_configdir', True),
'--builddir' : ('_builddir', True),
'--sourcedir' : ('_sourcedir', True),
'--tmppath' : ('_tmppath', True),
'--log' : ('_logfile', False),
'--url' : ('_url_base', False),
'--targetcflags' : ('_targetcflags', False),
'--targetcxxflags' : ('_targetcxxflags', False),
'--libstdcxxflags' : ('_libstdcxxflags', False) }
_long_true_opts = { '--force' : '_force',
'--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 'Source Builder, an RTEMS Tools Project (c) 2012 Chris Johns'
print 'Options and arguments:'
print '--force : Create directories that are not present'
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'
if self.optargs:
for a in self.optargs:
print '%-22s : %s' % (a, self.optargs[a])
raise error.exit()
def __init__(self, argv, optargs):
self.command_path = path.dirname(argv[0])
if len(self.command_path) == 0:
self.command_path = '.'
self.command_name = path.basename(argv[0])
self.args = argv[1:]
self.optargs = optargs
self.defaults = {}
for to in command_line._long_true_opts:
self.defaults[command_line._long_true_opts[to]] = ('none', 'none', '0')
self.defaults['_sbdir'] = ('dir', 'required', path.shell(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:]
if type(long_opts[lo]) is tuple:
if long_opts[lo][1]:
value = path.shell(value)
macro = long_opts[lo][0]
else:
macro = long_opts[lo]
return lo, macro, 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] = ('none', 'none', '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] = ('none', 'none', 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 = 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] = ('triplet', 'none', 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] = ('none', 'none', _arch_value)
self.defaults[_vendor] = ('none', 'none', _vendor_value)
self.defaults[_os] = ('none', 'none', _os_value)
if not lo and a not in self.optargs:
raise error.general('invalid argument (try --help): %s' % (a))
else:
if a == '-f':
self.opts['force'] = '1'
elif a == '-n':
self.opts['dry-run'] = '1'
elif a == '-q':
self.opts['quiet'] = '1'
elif a == '-?':
self._help()
else:
raise error.general('invalid argument (try --help): %s' % (a))
else:
self.opts['params'].append(a)
i += 1
def _post_process(self, _defaults):
if self.no_smp():
_defaults['_smp_mflags'] = ('none', 'none', _defaults['nil'][2])
if _defaults['_host'][2] == _defaults['nil'][2]:
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][2])
expanded = True
else:
raise error.general('cannot process default macro: ' + m)
return s
def command(self):
return path.join(self.command_path, self.command_name)
def force(self):
return self.opts['force'] != '0'
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_arg(self, arg):
if not arg in self.optargs:
raise error.internal('bad arg: %s' % (arg))
for a in self.args:
if a.startswith(arg):
return a
return None
def get_config_files(self, config):
#
# Convert to shell paths and return shell paths.
#
# @fixme should this use a passed in set of defaults and not
# not the initial set of values ?
#
config = path.shell(config)
if '*' in config or '?' in config:
print config
configdir = path.dirname(config)
configbase = path.basename(config)
if len(configbase) == 0:
configbase = '*'
if not configbase.endswith('.cfg'):
configbase = configbase + '.cfg'
if len(configdir) == 0:
configdir = self.expand(defaults['_configdir'][2], defaults)
configs = []
for cp in configdir.split(':'):
hostconfigdir = path.host(cp)
for f in glob.glob(os.path.join(hostconfigdir, configbase)):
configs += path.shell(f)
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, optargs = None):
"""
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, optargs)
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
sb/error.py Normal file
View 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
sb/execute.py Executable file
View 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

67
sb/freebsd.py Normal file
View File

@ -0,0 +1,67 @@
#
# 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'.
#
# RTEMS Tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RTEMS Tools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
#
#
# This code is based on what ever doco about spec files I could find and
# RTEMS project's spec files.
#
import pprint
import os
import execute
def load():
uname = os.uname()
sysctl = '/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 = ''
if uname[4] == 'amd64':
cpu = 'x86_64'
else:
cpu = uname[4]
version = uname[2]
if version.find('-') > 0:
version = version.split('-')[0]
defines = {
'_os': ('none', 'none', 'freebsd'),
'_host': ('triplet', 'required', cpu + '-freebsd' + version),
'_host_vendor': ('none', 'none', 'pc'),
'_host_os': ('none', 'none', 'freebsd'),
'_host_cpu': ('none', 'none', cpu),
'_host_alias': ('none', 'none', '%{nil}'),
'_host_arch': ('none', 'none', cpu),
'_usr': ('dir', 'required', '/usr/local'),
'_var': ('dir', 'optional', '/usr/local/var'),
'optflags': ('none', 'none', '-O2 -I/usr/local/include -L/usr/local/lib'),
'_smp_mflags': ('none', 'none', smp_mflags),
'__bash': ('exe', 'optional', '/usr/local//bin/bash'),
'__xz': ('exe', 'optional', '/usr/bin/xz'),
'__make': ('exe', 'required', 'gmake')
}
return defines
if __name__ == '__main__':
pprint.pprint(load())

63
sb/linux.py Normal file
View 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': ('none', 'none', 'linux'),
'_host': ('triplet', 'required', uname[4] + '-linux-gnu'),
'_host_vendor': ('none', 'none', 'gnu'),
'_host_os': ('none', 'none', 'linux'),
'_host_cpu': ('none', 'none', uname[4]),
'_host_alias': ('none', 'none', '%{nil}'),
'_host_arch': ('none', 'none', uname[4]),
'_usr': ('dir', 'required', '/usr'),
'_var': ('dir', 'required', '/usr/var'),
'optflags': ('none', 'none', '-O2 -fasynchronous-unwind-tables'),
'_smp_mflags': ('none', 'none', smp_mflags),
'__bzip2': ('exe', 'required', '/usr/bin/bzip2'),
'__gzip': ('exe', 'required', '/bin/gzip'),
'__tar': ('exe', 'required', '/bin/tar')
}
return defines
if __name__ == '__main__':
pprint.pprint(load())

111
sb/log.py Executable file
View 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

95
sb/path.py Normal file
View File

@ -0,0 +1,95 @@
#
# 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.
#
# Manage paths locally. The internally the path is in Unix or shell format and
# we convert to the native format when performing operations at the Python
# level. This allows macro expansion to work.
#
import os
import string
windows = os.name == 'nt'
def host(path):
if path is not None:
while '//' in path:
path = path.replace('//', '/')
if windows and len(path) > 2:
if path[0] == '/' and path[2] == '/' and \
(path[1] in string.ascii_lowercase or \
path[1] in string.ascii_uppercase):
path = ('%s:%s' % (path[1], path[2:])).replace('/', '\\')
return path
def shell(path):
if path is not None:
if windows and len(path) > 1 and path[1] == ':':
path = ('/%s%s' % (path[0], path[2:])).replace('\\', '/')
while '//' in path:
path = path.replace('//', '/')
return path
def basename(path):
return shell(os.path.basename(path))
def dirname(path):
return shell(os.path.dirname(path))
def join(path, *args):
path = shell(path)
for arg in args:
path += '/' + shell(arg)
return shell(path)
def abspath(path):
return shell(os.path.abspath(host(path)))
def splitext(path):
root, ext = os.path.splitext(host(path))
return shell(root), ext
def exists(path):
return os.path.exists(host(path))
def isdir(path):
return os.path.isdir(host(path))
def isfile(path):
return os.path.isfile(host(path))
def isabspath(path):
return path[0] == '/'
if __name__ == '__main__':
print host('/a/b/c/d-e-f')
print host('//a/b//c/d-e-f')
print shell('/w/x/y/z')
print basename('/as/sd/df/fg/me.txt')
print dirname('/as/sd/df/fg/me.txt')
print join('/d', 'g', '/tyty/fgfg')
windows = True
print host('/a/b/c/d-e-f')
print host('//a/b//c/d-e-f')
print shell('/w/x/y/z')
print shell('w:/x/y/z')
print basename('x:/sd/df/fg/me.txt')
print dirname('x:/sd/df/fg/me.txt')
print join('s:/d/', '/g', '/tyty/fgfg')

250
sb/setbuilder.py Normal file
View File

@ -0,0 +1,250 @@
#
# 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 glob
import operator
import os
import build
import check
import defaults
import error
import log
import path
#
# Version of Source Builder Set 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 buildset:
"""Build a set builds a set of packages."""
def __init__(self, bset, _defaults, opts):
_trace(opts, '_bset:%s: init' % (bset))
self.opts = opts
self.defaults = _defaults
self.bset = bset
self.bset_pkg = '%s-%s-set' % (self.opts.expand('%{_target}', _defaults),
self.bset)
def _output(self, text):
if not self.opts.quiet():
log.output(text)
def copy(self, src, dst):
if os.path.isdir(path.host(src)):
topdir = self.opts.expand('%{_topdir}', self.defaults)
what = '%s -> %s' % \
(path.host(src[len(topdir) + 1:]), path.host(dst[len(topdir) + 1:]))
_notice(self.opts, 'installing: %s' % (what))
if not self.opts.dry_run():
try:
files = distutils.dir_util.copy_tree(path.host(src),
path.host(dst))
for f in files:
self._output(f)
except IOError, err:
raise error.general('installing tree: %s: %s' % (what, str(err)))
except distutils.errors.DistutilsFileError, err:
raise error.general('installing tree: %s' % (str(err)))
def first_package(self, _build):
tmproot = path.abspath(_build.config.expand('%{_tmproot}'))
_build.rmdir(tmproot)
_build.mkdir(tmproot)
prefix = _build.config.expand('%{_prefix}')
if prefix[0] == os.sep:
prefix = prefix[1:]
tmpprefix = path.join(tmproot, prefix)
tmpbindir = path.join(tmpprefix, 'bin')
# exporting to the environment
os.environ['SB_TMPPREFIX'] = tmpprefix
os.environ['SB_TMPBINDIR'] = tmpbindir
os.environ['PATH'] = path.host(tmpbindir) + os.pathsep + os.environ['PATH']
self._output('path: ' + os.environ['PATH'])
# shell format
return tmproot
def every_package(self, _build, tmproot):
self.copy(_build.config.abspath('%{buildroot}'), tmproot)
def last_package(self, _build, tmproot):
tar = path.join(_build.config.expand('%{_tardir}'),
_build.config.expand('%s.tar.bz2' % (self.bset_pkg)))
_notice(self.opts, 'tarball: %s' % path.host(tar))
if not self.opts.dry_run():
cmd = _build.config.expand("'cd " + tmproot + \
" && %{__tar} -cf - . | %{__bzip2} > " + tar + "'")
_build.run(cmd, shell_opts = '-c', cwd = tmproot)
def load(self):
def _clean(line):
line = line[0:-1]
b = line.find('#')
if b >= 0:
line = line[1:b]
return line.strip()
exbset = self.opts.expand(self.bset, self.defaults)
self.defaults['_bset'] = ('none', 'none', exbset)
root, ext = path.splitext(exbset)
if exbset.endswith('.bset'):
bset = exbset
else:
bset = '%s.bset' % (exbset)
bsetname = bset
if not path.exists(bsetname):
for cp in self.opts.expand('%{_configdir}', self.defaults).split(':'):
configdir = path.abspath(cp)
bsetname = path.join(configdir, bset)
if path.exists(bsetname):
break
bsetname = None
if bsetname is None:
raise error.general('no build set file found: %s' % (bset))
try:
if self.opts.trace():
print '_bset:%s: open: %s' % (self.bset, bsetname)
bset = open(path.host(bsetname), 'r')
except IOError, err:
raise error.general('error opening bset file: %s' % (bsetname))
configs = []
try:
lc = 0
for l in bset:
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.bset_pkg = self.opts.expand(ls[1].strip(), self.defaults)
self.defaults['package'] = ('none', 'none', self.bset_pkg)
elif l[0] == '%':
if l.startswith('%define'):
ls = l.split()
self.defaults[ls[1].strip()] = ('none', 'none', ls[2].strip())
else:
raise error.general('invalid directive in build set files: %s' % (l))
else:
configs += [l.strip()]
except:
bset.close()
raise
bset.close()
return configs
def make(self):
_trace(self.opts, '_bset:%s: make' % (self.bset))
_notice(self.opts, 'Build Set: %s' % (self.bset))
configs = self.load()
_trace(self.opts, '_bset:%s: configs: %s' % (self.bset, ','.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:
tmproot = self.first_package(b)
b.make()
self.every_package(b, tmproot)
if s == len(configs) - 1:
self.last_package(b, tmproot)
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:
optargs = { '--list-configs': 'List available configurations',
'--list-bsets': 'List available build sets'}
opts, _defaults = defaults.load(sys.argv, optargs)
log.default = log.log(opts.logfiles())
_notice(opts, 'Source Builder - Set Builder, v%s' % (version))
if not check.host_setup(opts, _defaults):
if not opts.force():
raise error.general('host build environment is not set up correctly (use --force to proceed)')
_notice(opts, 'warning: forcing build with known host setup problems')
if opts.get_arg('--list-configs'):
build.list_configs(opts, _defaults)
elif opts.get_arg('--list-bsets'):
build.list_configs(opts, _defaults, ext = '.bset')
else:
for bset in opts.params():
c = buildset(bset, _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()

91
sb/windows.py Normal file
View File

@ -0,0 +1,91 @@
#
# 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': ('none', 'none', 'win32'),
'_host': ('triplet', 'required', hosttype + '-pc-' + system),
'_host_vendor': ('none', 'none', 'microsoft'),
'_host_os': ('none', 'none', 'win32'),
'_host_cpu': ('none', 'none', hosttype),
'_host_alias': ('none', 'none', '%{nil}'),
'_host_arch': ('none', 'none', hosttype),
'_usr': ('dir', 'optional', '/opt/local'),
'_var': ('dir', 'optional', '/opt/local/var'),
'_smp_mflags': ('none', 'none', smp_mflags),
'__bash': ('exe', 'required', 'bash'),
'__bzip2': ('exe', 'required', 'bzip2'),
'__cat': ('exe', 'required', 'cat'),
'__cc': ('exe', 'required', 'gcc'),
'__chgrp': ('exe', 'required', 'chgrp'),
'__chmod': ('exe', 'required', 'chmod'),
'__chown': ('exe', 'required', 'chown'),
'__cp': ('exe', 'required', 'cp'),
'__cxx': ('exe', 'required', 'g++'),
'__grep': ('exe', 'required', 'grep'),
'__gzip': ('exe', 'required', 'gzip'),
'__id': ('exe', 'required', 'id'),
'__install': ('exe', 'required', 'install'),
'__install_info': ('exe', 'required', 'install-info'),
'__ld': ('exe', 'required', 'ld'),
'__ldconfig': ('exe', 'none', ''),
'__mkdir': ('exe', 'required', 'mkdir'),
'__mv': ('exe', 'required', 'mv'),
'__nm': ('exe', 'required', 'nm'),
'__nm': ('exe', 'required', 'nm'),
'__objcopy': ('exe', 'required', 'objcopy'),
'__objdump': ('exe', 'required', 'objdump'),
'__patch': ('exe', 'required', 'patch'),
'__rm': ('exe', 'required', 'rm'),
'__sed': ('exe', 'required', 'sed'),
'__sh': ('exe', 'required', 'sh'),
'__tar': ('exe', 'required', 'bsdtar'),
'__unzip': ('exe', 'required', 'unzip'),
'__xz': ('exe', 'required', 'xz'),
'_buildshell': ('exe', 'required', '%{__sh}'),
'___setup_shell': ('exe', 'required', '%{__sh}'),
'optflags': ('none', 'none', '-O2 -pipe'),
}
return defines
if __name__ == '__main__':
pprint.pprint(load())