diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f836aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +*.pyc diff --git a/config/autoconf-2-1.cfg b/config/autoconf-2-1.cfg new file mode 100644 index 0000000..fbb1910 --- /dev/null +++ b/config/autoconf-2-1.cfg @@ -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 .. diff --git a/config/autoconf-2.68-1.cfg b/config/autoconf-2.68-1.cfg new file mode 100644 index 0000000..c01f8fc --- /dev/null +++ b/config/autoconf-2.68-1.cfg @@ -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 diff --git a/config/autoconf-2.69-1.cfg b/config/autoconf-2.69-1.cfg new file mode 100644 index 0000000..28c26c9 --- /dev/null +++ b/config/autoconf-2.69-1.cfg @@ -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 diff --git a/config/autoconf-internal-2.68-1.cfg b/config/autoconf-internal-2.68-1.cfg new file mode 100644 index 0000000..6adf097 --- /dev/null +++ b/config/autoconf-internal-2.68-1.cfg @@ -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 diff --git a/config/automake-1-1.cfg b/config/automake-1-1.cfg new file mode 100644 index 0000000..fa0fde3 --- /dev/null +++ b/config/automake-1-1.cfg @@ -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 .. diff --git a/config/automake-1.12-1.cfg b/config/automake-1.12-1.cfg new file mode 100644 index 0000000..ca04bf7 --- /dev/null +++ b/config/automake-1.12-1.cfg @@ -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 diff --git a/config/automake-internal-1.12-1.cfg b/config/automake-internal-1.12-1.cfg new file mode 100644 index 0000000..9123a48 --- /dev/null +++ b/config/automake-internal-1.12-1.cfg @@ -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 diff --git a/config/base.cfg b/config/base.cfg new file mode 100644 index 0000000..07e6b0e --- /dev/null +++ b/config/base.cfg @@ -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 diff --git a/config/binutils-2-1.cfg b/config/binutils-2-1.cfg new file mode 100644 index 0000000..415d74f --- /dev/null +++ b/config/binutils-2-1.cfg @@ -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 .. diff --git a/config/binutils-2.22-1.cfg b/config/binutils-2.22-1.cfg new file mode 100644 index 0000000..e585483 --- /dev/null +++ b/config/binutils-2.22-1.cfg @@ -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 diff --git a/config/checks.cfg b/config/checks.cfg new file mode 100644 index 0000000..9586f46 --- /dev/null +++ b/config/checks.cfg @@ -0,0 +1,11 @@ +# +# Standard checks. +# + +%if %{_target} == %{nil} +%error No 'target' defined +%endif + +%ifn %{defined release} +%error No 'release' defined +%endif diff --git a/config/expat-2-1.cfg b/config/expat-2-1.cfg new file mode 100644 index 0000000..3265752 --- /dev/null +++ b/config/expat-2-1.cfg @@ -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 .. diff --git a/config/expat-2.1.0-1.cfg b/config/expat-2.1.0-1.cfg new file mode 100644 index 0000000..7a87aab --- /dev/null +++ b/config/expat-2.1.0-1.cfg @@ -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 diff --git a/config/gcc-4.4-1.cfg b/config/gcc-4.4-1.cfg new file mode 100644 index 0000000..d2e1d32 --- /dev/null +++ b/config/gcc-4.4-1.cfg @@ -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* diff --git a/config/gcc-4.6-1.cfg b/config/gcc-4.6-1.cfg new file mode 100644 index 0000000..d2e1d32 --- /dev/null +++ b/config/gcc-4.6-1.cfg @@ -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* diff --git a/config/gcc-4.6-newlib-1.20-1.cfg b/config/gcc-4.6-newlib-1.20-1.cfg new file mode 100644 index 0000000..e5e5745 --- /dev/null +++ b/config/gcc-4.6-newlib-1.20-1.cfg @@ -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 diff --git a/config/gdb-7-1.cfg b/config/gdb-7-1.cfg new file mode 100644 index 0000000..ab3aa8f --- /dev/null +++ b/config/gdb-7-1.cfg @@ -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 .. diff --git a/config/gdb-7.5-1.cfg b/config/gdb-7.5-1.cfg new file mode 100644 index 0000000..e2d141b --- /dev/null +++ b/config/gdb-7.5-1.cfg @@ -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 diff --git a/config/gnu-tools-4.6.bset b/config/gnu-tools-4.6.bset new file mode 100644 index 0000000..591af4b --- /dev/null +++ b/config/gnu-tools-4.6.bset @@ -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 diff --git a/config/libusb-1-1.cfg b/config/libusb-1-1.cfg new file mode 100644 index 0000000..a31f218 --- /dev/null +++ b/config/libusb-1-1.cfg @@ -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 .. diff --git a/config/libusb-1.0.9-1.cfg b/config/libusb-1.0.9-1.cfg new file mode 100644 index 0000000..728a626 --- /dev/null +++ b/config/libusb-1.0.9-1.cfg @@ -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 diff --git a/config/m4-1-1.cfg b/config/m4-1-1.cfg new file mode 100644 index 0000000..64eea18 --- /dev/null +++ b/config/m4-1-1.cfg @@ -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 .. diff --git a/config/m4-1.4.16-1.cfg b/config/m4-1.4.16-1.cfg new file mode 100644 index 0000000..8753a64 --- /dev/null +++ b/config/m4-1.4.16-1.cfg @@ -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 diff --git a/config/texane-stlink-1.cfg b/config/texane-stlink-1.cfg new file mode 100644 index 0000000..335a60e --- /dev/null +++ b/config/texane-stlink-1.cfg @@ -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 .. diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..3af9e6f --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,2 @@ +.lock-* +build diff --git a/doc/images/icons/README b/doc/images/icons/README new file mode 100644 index 0000000..f12b2a7 --- /dev/null +++ b/doc/images/icons/README @@ -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 diff --git a/doc/images/icons/callouts/1.png b/doc/images/icons/callouts/1.png new file mode 100644 index 0000000..7d47343 Binary files /dev/null and b/doc/images/icons/callouts/1.png differ diff --git a/doc/images/icons/callouts/10.png b/doc/images/icons/callouts/10.png new file mode 100644 index 0000000..997bbc8 Binary files /dev/null and b/doc/images/icons/callouts/10.png differ diff --git a/doc/images/icons/callouts/11.png b/doc/images/icons/callouts/11.png new file mode 100644 index 0000000..ce47dac Binary files /dev/null and b/doc/images/icons/callouts/11.png differ diff --git a/doc/images/icons/callouts/12.png b/doc/images/icons/callouts/12.png new file mode 100644 index 0000000..31daf4e Binary files /dev/null and b/doc/images/icons/callouts/12.png differ diff --git a/doc/images/icons/callouts/13.png b/doc/images/icons/callouts/13.png new file mode 100644 index 0000000..14021a8 Binary files /dev/null and b/doc/images/icons/callouts/13.png differ diff --git a/doc/images/icons/callouts/14.png b/doc/images/icons/callouts/14.png new file mode 100644 index 0000000..64014b7 Binary files /dev/null and b/doc/images/icons/callouts/14.png differ diff --git a/doc/images/icons/callouts/15.png b/doc/images/icons/callouts/15.png new file mode 100644 index 0000000..0d65765 Binary files /dev/null and b/doc/images/icons/callouts/15.png differ diff --git a/doc/images/icons/callouts/2.png b/doc/images/icons/callouts/2.png new file mode 100644 index 0000000..5d09341 Binary files /dev/null and b/doc/images/icons/callouts/2.png differ diff --git a/doc/images/icons/callouts/3.png b/doc/images/icons/callouts/3.png new file mode 100644 index 0000000..ef7b700 Binary files /dev/null and b/doc/images/icons/callouts/3.png differ diff --git a/doc/images/icons/callouts/4.png b/doc/images/icons/callouts/4.png new file mode 100644 index 0000000..adb8364 Binary files /dev/null and b/doc/images/icons/callouts/4.png differ diff --git a/doc/images/icons/callouts/5.png b/doc/images/icons/callouts/5.png new file mode 100644 index 0000000..4d7eb46 Binary files /dev/null and b/doc/images/icons/callouts/5.png differ diff --git a/doc/images/icons/callouts/6.png b/doc/images/icons/callouts/6.png new file mode 100644 index 0000000..0ba694a Binary files /dev/null and b/doc/images/icons/callouts/6.png differ diff --git a/doc/images/icons/callouts/7.png b/doc/images/icons/callouts/7.png new file mode 100644 index 0000000..472e96f Binary files /dev/null and b/doc/images/icons/callouts/7.png differ diff --git a/doc/images/icons/callouts/8.png b/doc/images/icons/callouts/8.png new file mode 100644 index 0000000..5e60973 Binary files /dev/null and b/doc/images/icons/callouts/8.png differ diff --git a/doc/images/icons/callouts/9.png b/doc/images/icons/callouts/9.png new file mode 100644 index 0000000..a0676d2 Binary files /dev/null and b/doc/images/icons/callouts/9.png differ diff --git a/doc/images/icons/caution.png b/doc/images/icons/caution.png new file mode 100644 index 0000000..9a8c515 Binary files /dev/null and b/doc/images/icons/caution.png differ diff --git a/doc/images/icons/example.png b/doc/images/icons/example.png new file mode 100644 index 0000000..1199e86 Binary files /dev/null and b/doc/images/icons/example.png differ diff --git a/doc/images/icons/home.png b/doc/images/icons/home.png new file mode 100644 index 0000000..37a5231 Binary files /dev/null and b/doc/images/icons/home.png differ diff --git a/doc/images/icons/important.png b/doc/images/icons/important.png new file mode 100644 index 0000000..be685cc Binary files /dev/null and b/doc/images/icons/important.png differ diff --git a/doc/images/icons/next.png b/doc/images/icons/next.png new file mode 100644 index 0000000..64e126b Binary files /dev/null and b/doc/images/icons/next.png differ diff --git a/doc/images/icons/note.png b/doc/images/icons/note.png new file mode 100644 index 0000000..7c1f3e2 Binary files /dev/null and b/doc/images/icons/note.png differ diff --git a/doc/images/icons/prev.png b/doc/images/icons/prev.png new file mode 100644 index 0000000..3e8f12f Binary files /dev/null and b/doc/images/icons/prev.png differ diff --git a/doc/images/icons/tip.png b/doc/images/icons/tip.png new file mode 100644 index 0000000..f087c73 Binary files /dev/null and b/doc/images/icons/tip.png differ diff --git a/doc/images/icons/up.png b/doc/images/icons/up.png new file mode 100644 index 0000000..2db1ce6 Binary files /dev/null and b/doc/images/icons/up.png differ diff --git a/doc/images/icons/warning.png b/doc/images/icons/warning.png new file mode 100644 index 0000000..d41edb9 Binary files /dev/null and b/doc/images/icons/warning.png differ diff --git a/doc/images/rtemswhitebg.jpg b/doc/images/rtemswhitebg.jpg new file mode 100644 index 0000000..f883f2c Binary files /dev/null and b/doc/images/rtemswhitebg.jpg differ diff --git a/doc/source-builder.txt b/doc/source-builder.txt new file mode 100644 index 0000000..4558218 --- /dev/null +++ b/doc/source-builder.txt @@ -0,0 +1,214 @@ +Source Builder +============== +Chris Johns +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. + diff --git a/doc/wscript b/doc/wscript new file mode 100644 index 0000000..9685ebf --- /dev/null +++ b/doc/wscript @@ -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) diff --git a/patches/texane-stlink-3494c11-1.diff b/patches/texane-stlink-3494c11-1.diff new file mode 100644 index 0000000..e1d30f9 --- /dev/null +++ b/patches/texane-stlink-3494c11-1.diff @@ -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" diff --git a/patches/texane-stlink-3494c11-2.diff b/patches/texane-stlink-3494c11-2.diff new file mode 100644 index 0000000..fc65935 --- /dev/null +++ b/patches/texane-stlink-3494c11-2.diff @@ -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 + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. + */ + ++#include + #include + #include + #include +@@ -18,14 +19,15 @@ + #include + #include + #include +-#include + #endif ++#include + + #include + + #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; diff --git a/sb-builder b/sb-builder new file mode 100755 index 0000000..440d481 --- /dev/null +++ b/sb-builder @@ -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) diff --git a/sb-check b/sb-check new file mode 100755 index 0000000..43aae67 --- /dev/null +++ b/sb-check @@ -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) diff --git a/sb-set-builder b/sb-set-builder new file mode 100755 index 0000000..7fb4f3a --- /dev/null +++ b/sb-set-builder @@ -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) diff --git a/sb/build.py b/sb/build.py new file mode 100644 index 0000000..bd1305b --- /dev/null +++ b/sb/build.py @@ -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) diff --git a/sb/check.py b/sb/check.py new file mode 100644 index 0000000..f973683 --- /dev/null +++ b/sb/check.py @@ -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() diff --git a/sb/config.py b/sb/config.py new file mode 100644 index 0000000..a9724dc --- /dev/null +++ b/sb/config.py @@ -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() diff --git a/sb/darwin.py b/sb/darwin.py new file mode 100644 index 0000000..5f8ac7f --- /dev/null +++ b/sb/darwin.py @@ -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()) diff --git a/sb/defaults.py b/sb/defaults.py new file mode 100644 index 0000000..09b0922 --- /dev/null +++ b/sb/defaults.py @@ -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-