summaryrefslogtreecommitdiffstats
path: root/source-builder
diff options
context:
space:
mode:
Diffstat (limited to 'source-builder')
-rw-r--r--source-builder/.gitignore2
-rw-r--r--source-builder/config/autoconf-2-1.cfg69
-rw-r--r--source-builder/config/autoconf-2.68-1.cfg16
-rw-r--r--source-builder/config/autoconf-2.69-1.cfg16
-rw-r--r--source-builder/config/autoconf-internal-2.68-1.cfg8
-rw-r--r--source-builder/config/automake-1-1.cfg69
-rw-r--r--source-builder/config/automake-1.12-1.cfg16
-rw-r--r--source-builder/config/automake-internal-1.12-1.cfg8
-rw-r--r--source-builder/config/base.cfg34
-rw-r--r--source-builder/config/binutils-2-1.cfg88
-rw-r--r--source-builder/config/binutils-2.22-1.cfg17
-rw-r--r--source-builder/config/checks.cfg11
-rw-r--r--source-builder/config/expat-2-1.cfg60
-rw-r--r--source-builder/config/expat-2.1.0-1.cfg16
-rw-r--r--source-builder/config/gcc-4.4-1.cfg186
-rw-r--r--source-builder/config/gcc-4.6-1.cfg186
-rw-r--r--source-builder/config/gcc-4.6-newlib-1.20-1.cfg21
-rw-r--r--source-builder/config/gdb-7-1.cfg70
-rw-r--r--source-builder/config/gdb-7.5-1.cfg17
-rw-r--r--source-builder/config/gnu-tools-4.6.bset24
-rw-r--r--source-builder/config/libusb-1-1.cfg61
-rw-r--r--source-builder/config/libusb-1.0.9-1.cfg21
-rw-r--r--source-builder/config/m4-1-1.cfg56
-rw-r--r--source-builder/config/m4-1.4.16-1.cfg16
-rw-r--r--source-builder/config/texane-stlink-1.cfg71
-rw-r--r--source-builder/doc/.gitignore2
-rw-r--r--source-builder/doc/images/icons/README5
-rw-r--r--source-builder/doc/images/icons/callouts/1.pngbin0 -> 329 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/10.pngbin0 -> 361 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/11.pngbin0 -> 565 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/12.pngbin0 -> 617 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/13.pngbin0 -> 623 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/14.pngbin0 -> 411 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/15.pngbin0 -> 640 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/2.pngbin0 -> 353 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/3.pngbin0 -> 350 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/4.pngbin0 -> 345 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/5.pngbin0 -> 348 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/6.pngbin0 -> 355 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/7.pngbin0 -> 344 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/8.pngbin0 -> 357 bytes
-rw-r--r--source-builder/doc/images/icons/callouts/9.pngbin0 -> 357 bytes
-rw-r--r--source-builder/doc/images/icons/caution.pngbin0 -> 2734 bytes
-rw-r--r--source-builder/doc/images/icons/example.pngbin0 -> 2599 bytes
-rw-r--r--source-builder/doc/images/icons/home.pngbin0 -> 1340 bytes
-rw-r--r--source-builder/doc/images/icons/important.pngbin0 -> 2980 bytes
-rw-r--r--source-builder/doc/images/icons/next.pngbin0 -> 1302 bytes
-rw-r--r--source-builder/doc/images/icons/note.pngbin0 -> 2494 bytes
-rw-r--r--source-builder/doc/images/icons/prev.pngbin0 -> 1348 bytes
-rw-r--r--source-builder/doc/images/icons/tip.pngbin0 -> 2718 bytes
-rw-r--r--source-builder/doc/images/icons/up.pngbin0 -> 1320 bytes
-rw-r--r--source-builder/doc/images/icons/warning.pngbin0 -> 3214 bytes
-rw-r--r--source-builder/doc/images/rtemswhitebg.jpgbin0 -> 117890 bytes
-rw-r--r--source-builder/doc/source-builder.txt214
-rw-r--r--source-builder/doc/wscript20
-rw-r--r--source-builder/patches/texane-stlink-3494c11-1.diff13
-rw-r--r--source-builder/patches/texane-stlink-3494c11-2.diff577
-rwxr-xr-xsource-builder/sb-builder29
-rwxr-xr-xsource-builder/sb-check29
-rwxr-xr-xsource-builder/sb-set-builder29
-rw-r--r--source-builder/sb/build.py483
-rw-r--r--source-builder/sb/check.py157
-rw-r--r--source-builder/sb/config.py873
-rw-r--r--source-builder/sb/darwin.py59
-rw-r--r--source-builder/sb/defaults.py575
-rw-r--r--source-builder/sb/error.py54
-rwxr-xr-xsource-builder/sb/execute.py363
-rw-r--r--source-builder/sb/freebsd.py67
-rw-r--r--source-builder/sb/linux.py63
-rwxr-xr-xsource-builder/sb/log.py111
-rw-r--r--source-builder/sb/path.py95
-rw-r--r--source-builder/sb/setbuilder.py250
-rw-r--r--source-builder/sb/windows.py91
73 files changed, 5318 insertions, 0 deletions
diff --git a/source-builder/.gitignore b/source-builder/.gitignore
new file mode 100644
index 0000000..2f836aa
--- /dev/null
+++ b/source-builder/.gitignore
@@ -0,0 +1,2 @@
+*~
+*.pyc
diff --git a/source-builder/config/autoconf-2-1.cfg b/source-builder/config/autoconf-2-1.cfg
new file mode 100644
index 0000000..fbb1910
--- /dev/null
+++ b/source-builder/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/source-builder/config/autoconf-2.68-1.cfg b/source-builder/config/autoconf-2.68-1.cfg
new file mode 100644
index 0000000..c01f8fc
--- /dev/null
+++ b/source-builder/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/source-builder/config/autoconf-2.69-1.cfg b/source-builder/config/autoconf-2.69-1.cfg
new file mode 100644
index 0000000..28c26c9
--- /dev/null
+++ b/source-builder/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/source-builder/config/autoconf-internal-2.68-1.cfg b/source-builder/config/autoconf-internal-2.68-1.cfg
new file mode 100644
index 0000000..6adf097
--- /dev/null
+++ b/source-builder/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/source-builder/config/automake-1-1.cfg b/source-builder/config/automake-1-1.cfg
new file mode 100644
index 0000000..fa0fde3
--- /dev/null
+++ b/source-builder/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/source-builder/config/automake-1.12-1.cfg b/source-builder/config/automake-1.12-1.cfg
new file mode 100644
index 0000000..ca04bf7
--- /dev/null
+++ b/source-builder/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/source-builder/config/automake-internal-1.12-1.cfg b/source-builder/config/automake-internal-1.12-1.cfg
new file mode 100644
index 0000000..9123a48
--- /dev/null
+++ b/source-builder/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/source-builder/config/base.cfg b/source-builder/config/base.cfg
new file mode 100644
index 0000000..07e6b0e
--- /dev/null
+++ b/source-builder/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/source-builder/config/binutils-2-1.cfg b/source-builder/config/binutils-2-1.cfg
new file mode 100644
index 0000000..415d74f
--- /dev/null
+++ b/source-builder/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/source-builder/config/binutils-2.22-1.cfg b/source-builder/config/binutils-2.22-1.cfg
new file mode 100644
index 0000000..e585483
--- /dev/null
+++ b/source-builder/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/source-builder/config/checks.cfg b/source-builder/config/checks.cfg
new file mode 100644
index 0000000..9586f46
--- /dev/null
+++ b/source-builder/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/source-builder/config/expat-2-1.cfg b/source-builder/config/expat-2-1.cfg
new file mode 100644
index 0000000..3265752
--- /dev/null
+++ b/source-builder/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/source-builder/config/expat-2.1.0-1.cfg b/source-builder/config/expat-2.1.0-1.cfg
new file mode 100644
index 0000000..7a87aab
--- /dev/null
+++ b/source-builder/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/source-builder/config/gcc-4.4-1.cfg b/source-builder/config/gcc-4.4-1.cfg
new file mode 100644
index 0000000..d2e1d32
--- /dev/null
+++ b/source-builder/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/source-builder/config/gcc-4.6-1.cfg b/source-builder/config/gcc-4.6-1.cfg
new file mode 100644
index 0000000..d2e1d32
--- /dev/null
+++ b/source-builder/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/source-builder/config/gcc-4.6-newlib-1.20-1.cfg b/source-builder/config/gcc-4.6-newlib-1.20-1.cfg
new file mode 100644
index 0000000..e5e5745
--- /dev/null
+++ b/source-builder/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/source-builder/config/gdb-7-1.cfg b/source-builder/config/gdb-7-1.cfg
new file mode 100644
index 0000000..ab3aa8f
--- /dev/null
+++ b/source-builder/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/source-builder/config/gdb-7.5-1.cfg b/source-builder/config/gdb-7.5-1.cfg
new file mode 100644
index 0000000..e2d141b
--- /dev/null
+++ b/source-builder/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/source-builder/config/gnu-tools-4.6.bset b/source-builder/config/gnu-tools-4.6.bset
new file mode 100644
index 0000000..591af4b
--- /dev/null
+++ b/source-builder/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/source-builder/config/libusb-1-1.cfg b/source-builder/config/libusb-1-1.cfg
new file mode 100644
index 0000000..a31f218
--- /dev/null
+++ b/source-builder/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/source-builder/config/libusb-1.0.9-1.cfg b/source-builder/config/libusb-1.0.9-1.cfg
new file mode 100644
index 0000000..728a626
--- /dev/null
+++ b/source-builder/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/source-builder/config/m4-1-1.cfg b/source-builder/config/m4-1-1.cfg
new file mode 100644
index 0000000..64eea18
--- /dev/null
+++ b/source-builder/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/source-builder/config/m4-1.4.16-1.cfg b/source-builder/config/m4-1.4.16-1.cfg
new file mode 100644
index 0000000..8753a64
--- /dev/null
+++ b/source-builder/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/source-builder/config/texane-stlink-1.cfg b/source-builder/config/texane-stlink-1.cfg
new file mode 100644
index 0000000..335a60e
--- /dev/null
+++ b/source-builder/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/source-builder/doc/.gitignore b/source-builder/doc/.gitignore
new file mode 100644
index 0000000..3af9e6f
--- /dev/null
+++ b/source-builder/doc/.gitignore
@@ -0,0 +1,2 @@
+.lock-*
+build
diff --git a/source-builder/doc/images/icons/README b/source-builder/doc/images/icons/README
new file mode 100644
index 0000000..f12b2a7
--- /dev/null
+++ b/source-builder/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/source-builder/doc/images/icons/callouts/1.png b/source-builder/doc/images/icons/callouts/1.png
new file mode 100644
index 0000000..7d47343
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/1.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/10.png b/source-builder/doc/images/icons/callouts/10.png
new file mode 100644
index 0000000..997bbc8
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/10.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/11.png b/source-builder/doc/images/icons/callouts/11.png
new file mode 100644
index 0000000..ce47dac
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/11.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/12.png b/source-builder/doc/images/icons/callouts/12.png
new file mode 100644
index 0000000..31daf4e
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/12.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/13.png b/source-builder/doc/images/icons/callouts/13.png
new file mode 100644
index 0000000..14021a8
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/13.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/14.png b/source-builder/doc/images/icons/callouts/14.png
new file mode 100644
index 0000000..64014b7
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/14.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/15.png b/source-builder/doc/images/icons/callouts/15.png
new file mode 100644
index 0000000..0d65765
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/15.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/2.png b/source-builder/doc/images/icons/callouts/2.png
new file mode 100644
index 0000000..5d09341
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/2.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/3.png b/source-builder/doc/images/icons/callouts/3.png
new file mode 100644
index 0000000..ef7b700
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/3.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/4.png b/source-builder/doc/images/icons/callouts/4.png
new file mode 100644
index 0000000..adb8364
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/4.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/5.png b/source-builder/doc/images/icons/callouts/5.png
new file mode 100644
index 0000000..4d7eb46
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/5.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/6.png b/source-builder/doc/images/icons/callouts/6.png
new file mode 100644
index 0000000..0ba694a
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/6.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/7.png b/source-builder/doc/images/icons/callouts/7.png
new file mode 100644
index 0000000..472e96f
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/7.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/8.png b/source-builder/doc/images/icons/callouts/8.png
new file mode 100644
index 0000000..5e60973
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/8.png
Binary files differ
diff --git a/source-builder/doc/images/icons/callouts/9.png b/source-builder/doc/images/icons/callouts/9.png
new file mode 100644
index 0000000..a0676d2
--- /dev/null
+++ b/source-builder/doc/images/icons/callouts/9.png
Binary files differ
diff --git a/source-builder/doc/images/icons/caution.png b/source-builder/doc/images/icons/caution.png
new file mode 100644
index 0000000..9a8c515
--- /dev/null
+++ b/source-builder/doc/images/icons/caution.png
Binary files differ
diff --git a/source-builder/doc/images/icons/example.png b/source-builder/doc/images/icons/example.png
new file mode 100644
index 0000000..1199e86
--- /dev/null
+++ b/source-builder/doc/images/icons/example.png
Binary files differ
diff --git a/source-builder/doc/images/icons/home.png b/source-builder/doc/images/icons/home.png
new file mode 100644
index 0000000..37a5231
--- /dev/null
+++ b/source-builder/doc/images/icons/home.png
Binary files differ
diff --git a/source-builder/doc/images/icons/important.png b/source-builder/doc/images/icons/important.png
new file mode 100644
index 0000000..be685cc
--- /dev/null
+++ b/source-builder/doc/images/icons/important.png
Binary files differ
diff --git a/source-builder/doc/images/icons/next.png b/source-builder/doc/images/icons/next.png
new file mode 100644
index 0000000..64e126b
--- /dev/null
+++ b/source-builder/doc/images/icons/next.png
Binary files differ
diff --git a/source-builder/doc/images/icons/note.png b/source-builder/doc/images/icons/note.png
new file mode 100644
index 0000000..7c1f3e2
--- /dev/null
+++ b/source-builder/doc/images/icons/note.png
Binary files differ
diff --git a/source-builder/doc/images/icons/prev.png b/source-builder/doc/images/icons/prev.png
new file mode 100644
index 0000000..3e8f12f
--- /dev/null
+++ b/source-builder/doc/images/icons/prev.png
Binary files differ
diff --git a/source-builder/doc/images/icons/tip.png b/source-builder/doc/images/icons/tip.png
new file mode 100644
index 0000000..f087c73
--- /dev/null
+++ b/source-builder/doc/images/icons/tip.png
Binary files differ
diff --git a/source-builder/doc/images/icons/up.png b/source-builder/doc/images/icons/up.png
new file mode 100644
index 0000000..2db1ce6
--- /dev/null
+++ b/source-builder/doc/images/icons/up.png
Binary files differ
diff --git a/source-builder/doc/images/icons/warning.png b/source-builder/doc/images/icons/warning.png
new file mode 100644
index 0000000..d41edb9
--- /dev/null
+++ b/source-builder/doc/images/icons/warning.png
Binary files differ
diff --git a/source-builder/doc/images/rtemswhitebg.jpg b/source-builder/doc/images/rtemswhitebg.jpg
new file mode 100644
index 0000000..f883f2c
--- /dev/null
+++ b/source-builder/doc/images/rtemswhitebg.jpg
Binary files differ
diff --git a/source-builder/doc/source-builder.txt b/source-builder/doc/source-builder.txt
new file mode 100644
index 0000000..4558218
--- /dev/null
+++ b/source-builder/doc/source-builder.txt
@@ -0,0 +1,214 @@
+Source Builder
+==============
+Chris Johns <chrisj@rtems.org>
+1.0, November 2012
+:doctype: book
+:toc:
+:icons:
+:numbered:
+
+image:images/rtemswhitebg.jpg["RTEMS",width="20%"]
+
+Introduction
+------------
+
+The Source Builder is a tool to aid building packages from source. It is not a
+package manager. It is just helps consolidate the details that you need to know
+to build a package from source. The tool is mainly aimed at those users who
+need to maintain tool sets for embedded type development, that is
+cross-compiled compiled tool chains, debuggers, and debugging aids. It is not
+limited to this role but designed to fit with-in that specific niche.
+
+The Source Builder attempts to support any host environment that runs Python
+and you can build the package on. It is not some sort of magic that can take
+any piece of source code and make it build. Someone at some point in time has
+figured out how to build that package from source and taught this tool.
+
+The Source Builder has two types configuration data. The first is configuration
+files and these are scripts based on the RPM spec file format that detail the
+steps needed to build a package. The steps are 'preparation', 'building', and
+'installing'. The second set of configuration files are 'build sets'. A build
+set describes a collection of packages you want built together. For example the
+GNU tool set is autoconf, automake, binutils, gcc, and gdb. This is the typical
+suite of tools you need for an embedded cross-development type project.
+
+The Source Builder does not interact with any host package management
+system. There is no automatic dependence checking between various packages you
+build or your host system may have installed. We assume you know what are doing
+or the build sets and configuration files you are using have been created by
+developers who do. A buld set should provide a known working configuration.
+
+Why build from source ?
+~~~~~~~~~~~~~~~~~~~~~~~
+
+If you are developing a system or product that has a long shelf life or is used
+in a critical piece of infastructure that has a long life cycle being able to
+build from source is important. It insulates the project from the fast ever
+changing world of the host development machines. If your tool set is binary and
+you have lost the ability to build it you have lost a degree of control and
+flexibility open source gives you. Fast moving host environments are
+fantastic. We have powerful multi-core computers with huge amounts of memory
+and state of the art operating systems to running on them. The product or
+project you are part of may need to be maintained well past the life time of
+these host. Being able to build from source an important and critical part of
+this process because you can move to a newer host and create an equivalent tool
+set.
+
+Building from source provides you with control over the configuration of the
+package you are building. If all or the most important dependent parts are
+built from source you limit the exposure to host variations. For example the
+GNU C compiler (gcc) currently uses a number of 3rd party libraries internally
+(gmp, mpfr, etc). If your validated compiler generating code for your target
+processor is dynamically linked against the host's version of these libraries
+any change in the host's configuration may effect you. The changes the host's
+package management system makes may be perfectly reasonible in relation to the
+distribution being managed how-ever this may not extend to you and your
+tools. Building your tools from source and controlling the specific version of
+these dependent parts means you are not exposing yourself to unexpected and
+often difficult to resolve problems. On the other side you need to make sure
+your tools build and work with newer versions of the host operating
+sytem. Given the stability of standards based libraries like 'libc' and ever
+improving support for standard header file locations this task is becoming
+easier.
+
+History
+~~~~~~~
+
+The Source Builder is a stand alone tool based on another tool called the
+'SpecBuilder'. The SpecBuilder was written for the RTEMS project too give me a
+way to build tools on hosts that did not support RPMs. At the time the RTEMS
+tools maintainer only used spec files to create various packages. This meant I
+had either spec files, RPM files or SRPM files. The RPM and SPRM files where
+useless because you needed an 'rpm' type tool to extract and manage them. There
+are versions of 'rpm' for a number of non-RPM hosts how-ever these proved to be
+in various broken states and randomally maintained. The solution I settled on
+was to use spec files so I wrote a Python based tool that parsed the spec file
+format and allowed me to create a shell script I could run to build the
+package. This approach proved successful and I was able to track the RPM
+version of the RTEMS tools on a non-RPM host over a number of years. How-ever
+the SpecBuilder tool did not help me build tools or other packages not related
+to the RTEMS project where there was no spec file I could use so I needed
+another tool. Rather than start again I decided to take the parsing code for
+the spec file format and build a new tool called the Source Builder.
+
+Quick Start
+-----------
+
+Check out the Source Builder tool from git:
+
+-------------------------------------------------------------
+$ git clone git://git.rtems.org/source-builder.git
+-------------------------------------------------------------
+
+The first step is to check if your host is set up correctly:
+
+-------------------------------------------------------------
+$ source-builder/sb-check
+warning: exe: absolute exe found in path: (__objcopy) /usr/local/bin/objcopy <1>
+warning: exe: absolute exe found in path: (__objdump) /usr/local/bin/objdump
+error: exe: not found: (_xz) /usr/local/bin/xz <2>
+Source Builder environent is not correctly set up
+$ source-builder/sb-check
+Source Builder environent is ok <3>
+-------------------------------------------------------------
+
+<1> A tool is in the environment path but does not match the shown path.
+<2> The executable 'xz' is not found.
+<3> The host's environment is set up correct.
+
+If there are problems you are given a list of executables that cannot be
+found. You may also be given a list of warnings about executables not in the
+expected location how-ever the executable was located somewhere in your
+environment's path. You will need to check the specific host section to resolve
+these issues.
+
+Create a suitable build directory away from the Source Builder source change
+into that directory and build a GNU tool set:
+
+-------------------------------------------------------------
+$ mkdir gnu-tools <1>
+$ cd gnu-tools
+$ ../source-builder/sb-set-builder <2> --log=l.txt <3> --force <4> \
+ --prefix=$HOME/gnu-tools-1 <5> --target=arm-eabi <6> gnu-toolset-4.6 <7>
+-------------------------------------------------------------
+
+<1> Make a build directory you can delete when finished.
+<2> The Source Builder command to build a set of tools.
+<3> Capture the output to a log file.
+<4> The force option will create any needed directories and allow the build to
+proceed if your host is not set up.
+<5> Give the tools a suitable prefix. This is the location you install the
+tools into once they have built.
+<6> The gnu-toolset requires you set a target. In this case the tool set will
+be a generic unpatched version of GCC 4.6 for a bare metal the ARM processor.
+<7> The build set.
+
+To view the build sets lets change to the RTEMS project's source builder
+configuration and then list the build sets:
+
+-------------------------------------------------------------
+$ cd ../rtems-source-builder
+$ ../source-builder/sb-set-builder --list-bsets
+Source Builder - Set Builder, v0.1
+Examining: /usr/home/chris/development/rtems/src/rtems-source-builder/config <1>
+Examining: /usr/home/chris/development/rtems/src/source-builder/config <2>
+ gnu-tools-4.6 <3>
+ rtems-tools-4.10 <4>
+-------------------------------------------------------------
+
+<1> The local RTEMS configuration directory. Searched first.
+<2> The Source Builder configuration directory.
+<3> The Source Builder provided GNU tools GCC 4.6 build set.
+<4> The RTEMS Source Builder provided RTEMS 4.10 build set.
+
+And to view the configurations you can:
+
+-------------------------------------------------------------
+$ ../source-builder/sb-set-builder --list-configs
+Source Builder - Set Builder, v0.1
+Examining: /usr/home/chris/development/rtems/src/rtems-source-builder/config
+Examining: /usr/home/chris/development/rtems/src/source-builder/config
+ autoconf-2-1 <1>
+ autoconf-2.68-1
+ autoconf-2.69-1
+ autoconf-internal-2.68-1
+ automake-1-1
+ automake-1.12-1
+ automake-internal-1.12-1
+ base
+ binutils-2-1
+ binutils-2.22-1
+ checks
+ expat-2-1
+ expat-2.1.0-1
+ gcc-4.4-1
+ gcc-4.6-1
+ gcc-4.6-newlib-1.20-1
+ gdb-7-1
+ gdb-7.5-1
+ libusb-1-1
+ libusb-1.0.9-1
+ m4-1-1
+ m4-1.4.16-1
+ texane-stlink-1
+ rtems-binutils-2.20.1-1
+ rtems-gcc-4.4.7-newlib-1.18.0-1
+ rtems-gdb-7.3.1-1
+-------------------------------------------------------------
+
+<1> Configurations are built by using the builder. This creates a stand alone
+package.
+
+The Source Builder
+------------------
+
+The Source Builder provides a few generic build sets and the configuration
+support to build a number of packages. A project that uses the Source Builder
+can create a specialised set of configuration files that provides the specific
+configurations thet project uses.
+
+For example the RTEMS project provides its own set of configuration files. In
+the build set list in the 'Quick Start' section you can see a build set
++rtems-tools-4.10+. This build set defines the extact configration to use for
+the RTEMS 4.10 release.
+
diff --git a/source-builder/doc/wscript b/source-builder/doc/wscript
new file mode 100644
index 0000000..9685ebf
--- /dev/null
+++ b/source-builder/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/source-builder/patches/texane-stlink-3494c11-1.diff b/source-builder/patches/texane-stlink-3494c11-1.diff
new file mode 100644
index 0000000..e1d30f9
--- /dev/null
+++ b/source-builder/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/source-builder/patches/texane-stlink-3494c11-2.diff b/source-builder/patches/texane-stlink-3494c11-2.diff
new file mode 100644
index 0000000..fc65935
--- /dev/null
+++ b/source-builder/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 <whitequark@whitequark.org>
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file.
+ */
+
++#include <stdarg.h>
+ #include <getopt.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -18,14 +19,15 @@
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+-#include <signal.h>
+ #endif
++#include <signal.h>
+
+ #include <stlink-common.h>
+
+ #include "gdb-remote.h"
+
+-#define DEFAULT_LOGGING_LEVEL 50
++#define DEFAULT_LOGGING_LEVEL 0
++#define LOGGING_LEVEL_GDBSERVER 2
+ #define DEFAULT_GDB_LISTEN_PORT 4242
+
+ #define STRINGIFY_inner(name) #name
+@@ -40,24 +42,47 @@ static const char hex[] = "0123456789abcdef";
+
+ static const char* current_memory_map = NULL;
+
++FILE *my_stderr;
++FILE *my_stdout;
++
+ typedef struct _st_state_t {
+- // things from command line, bleh
+- int stlink_version;
+- // "/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTE531X6-if00-port0" is only 58 chars
+- char devicename[100];
+- int logging_level;
++ // things from command line, bleh
++ int pipe;
++ int stlink_version;
++ // "/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTE531X6-if00-port0" is only 58 chars
++ char devicename[100];
++ int logging_level;
+ int listen_port;
+ } st_state_t;
+
++int logging_level = DEFAULT_LOGGING_LEVEL;
++
++int remote_desc = -1;
++int remote_piping = 0;
+
+-int serve(stlink_t *sl, int port);
++int remote_open(int port);
++int serve(stlink_t *sl);
+ char* make_memory_map(stlink_t *sl);
+
++/*
++ * Own printf and redirect when piping.
++ */
++int
++printf (const char *format,...)
++{
++ int ret;
++ va_list args;
++ va_start (args, format);
++ ret = vfprintf (my_stdout, format, args);
++ fflush (my_stdout);
++ return ret;
++}
+
+ int parse_options(int argc, char** argv, st_state_t *st) {
+ static struct option long_options[] = {
+ {"help", no_argument, NULL, 'h'},
+ {"verbose", optional_argument, NULL, 'v'},
++ {"pipe", no_argument, NULL, 'P'},
+ {"device", required_argument, NULL, 'd'},
+ {"stlink_version", required_argument, NULL, 's'},
+ {"stlinkv1", no_argument, NULL, '1'},
+@@ -78,11 +103,10 @@ int parse_options(int argc, char** argv, st_state_t *st) {
+ "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n"
+ ;
+
+-
+ int option_index = 0;
+ int c;
+ int q;
+- while ((c = getopt_long(argc, argv, "hv::d:s:1p:", long_options, &option_index)) != -1) {
++ while ((c = getopt_long(argc, argv, "hv::d:s:1Pp:", long_options, &option_index)) != -1) {
+ switch (c) {
+ case 0:
+ printf("XXXXX Shouldn't really normally come here, only if there's no corresponding option\n");
+@@ -96,12 +120,16 @@ int parse_options(int argc, char** argv, st_state_t *st) {
+ printf(help_str, argv[0]);
+ exit(EXIT_SUCCESS);
+ break;
++ case 'P':
++ st->pipe = 1;
++ break;
+ case 'v':
+ if (optarg) {
+ st->logging_level = atoi(optarg);
+ } else {
+ st->logging_level = DEFAULT_LOGGING_LEVEL;
+ }
++ logging_level = st->logging_level;
+ break;
+ case 'd':
+ if (strlen(optarg) > sizeof (st->devicename)) {
+@@ -149,10 +177,21 @@ int main(int argc, char** argv) {
+ st_state_t state;
+ memset(&state, 0, sizeof(state));
+ // set defaults...
++ state.pipe = 0;
+ state.stlink_version = 2;
+ state.logging_level = DEFAULT_LOGGING_LEVEL;
+ state.listen_port = DEFAULT_GDB_LISTEN_PORT;
+ parse_options(argc, argv, &state);
++
++ my_stdout = stdout;
++ my_stderr = stderr;
++
++ if (state.pipe) {
++ my_stdout = my_stderr = stderr;
++ state.listen_port = 0;
++ remote_piping = 1;
++ }
++
+ switch (state.stlink_version) {
+ case 2:
+ sl = stlink_open_usb(state.logging_level);
+@@ -162,7 +201,18 @@ int main(int argc, char** argv) {
+ sl = stlink_v1_open(state.logging_level);
+ if(sl == NULL) return 1;
+ break;
+- }
++ }
++
++#ifdef __MINGW32__
++ if (!remote_piping) {
++ WSADATA wsadata;
++ if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0 ) {
++ goto winsock_error;
++ }
++ }
++#endif
++
++ remote_open(state.listen_port);
+
+ printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id);
+
+@@ -170,18 +220,13 @@ int main(int argc, char** argv) {
+
+ current_memory_map = make_memory_map(sl);
+
+-#ifdef __MINGW32__
+- WSADATA wsadata;
+- if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0 ) {
+- goto winsock_error;
+- }
+-#endif
+-
+- while(serve(sl, state.listen_port) == 0);
++ while(serve(sl) == 0);
+
+ #ifdef __MINGW32__
++ if (!remote_piping) {
+ winsock_error:
+- WSACleanup();
++ WSACleanup();
++ }
+ #endif
+
+ /* Switch back to mass storage mode before closing. */
+@@ -342,9 +387,8 @@ struct code_hw_watchpoint {
+ struct code_hw_watchpoint data_watches[DATA_WATCH_NUM];
+
+ static void init_data_watchpoints(stlink_t *sl) {
+- #ifdef DEBUG
+- printf("init watchpoints\n");
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("init watchpoints\n");
+
+ // set trcena in debug command to turn on dwt unit
+ stlink_write_debug32(sl, 0xE000EDFC,
+@@ -377,9 +421,8 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr
+ for(i = 0; i < DATA_WATCH_NUM; i++) {
+ // is this an empty slot ?
+ if(data_watches[i].fun == WATCHDISABLED) {
+- #ifdef DEBUG
+- printf("insert watchpoint %d addr %x wf %u mask %u len %d\n", i, addr, wf, mask, len);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("insert watchpoint %d addr %x wf %u mask %u len %d\n", i, addr, wf, mask, len);
+
+ data_watches[i].fun = wf;
+ data_watches[i].addr = addr;
+@@ -401,9 +444,10 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr
+ }
+ }
+
+- #ifdef DEBUG
+- printf("failure: add watchpoints addr %x wf %u len %u\n", addr, wf, len);
+- #endif
++
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("failure: add watchpoints addr %x wf %u len %u\n", addr, wf, len);
++
+ return -1;
+ }
+
+@@ -413,9 +457,8 @@ static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr)
+
+ for(i = 0 ; i < DATA_WATCH_NUM; i++) {
+ if((data_watches[i].addr == addr) && (data_watches[i].fun != WATCHDISABLED)) {
+- #ifdef DEBUG
+- printf("delete watchpoint %d addr %x\n", i, addr);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("delete watchpoint %d addr %x\n", i, addr);
+
+ data_watches[i].fun = WATCHDISABLED;
+ stlink_write_debug32(sl, 0xe0001028 + i * 16, 0);
+@@ -424,9 +467,8 @@ static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr)
+ }
+ }
+
+- #ifdef DEBUG
+- printf("failure: delete watchpoint addr %x\n", addr);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("failure: delete watchpoint addr %x\n", addr);
+
+ return -1;
+ }
+@@ -485,20 +527,19 @@ static int update_code_breakpoint(stlink_t *sl, stm32_addr_t addr, int set) {
+ else brk->type &= ~type;
+
+ if(brk->type == 0) {
+- #ifdef DEBUG
+- printf("clearing hw break %d\n", id);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("clearing hw break %d\n", id);
+
+ stlink_write_debug32(sl, 0xe0002008 + id * 4, 0);
+ } else {
+ uint32_t mask = (brk->addr) | 1 | (brk->type << 30);
+
+- #ifdef DEBUG
+- printf("setting hw break %d at %08x (%d)\n",
+- id, brk->addr, brk->type);
+- printf("reg %08x \n",
+- mask);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER) {
++ printf("setting hw break %d at %08x (%d)\n",
++ id, brk->addr, brk->type);
++ printf("reg %08x \n",
++ mask);
++ }
+
+ stlink_write_debug32(sl, 0xe0002008 + id * 4, mask);
+ }
+@@ -589,9 +630,8 @@ static int flash_go(stlink_t *sl) {
+ stlink_reset(sl);
+
+ for(struct flash_block* fb = flash_root; fb; fb = fb->next) {
+- #ifdef DEBUG
+- printf("flash_do: block %08x -> %04x\n", fb->addr, fb->length);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("flash_do: block %08x -> %04x\n", fb->addr, fb->length);
+
+ unsigned length = fb->length;
+ for(stm32_addr_t page = fb->addr; page < fb->addr + fb->length; page += FLASH_PAGE) {
+@@ -599,9 +639,8 @@ static int flash_go(stlink_t *sl) {
+ //Update FLASH_PAGE
+ stlink_calculate_pagesize(sl, page);
+
+- #ifdef DEBUG
+- printf("flash_do: page %08x\n", page);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("flash_do: page %08x\n", page);
+
+ if(stlink_write_flash(sl, page, fb->data + (page - fb->addr),
+ length > FLASH_PAGE ? FLASH_PAGE : length) < 0)
+@@ -625,50 +664,74 @@ error:
+ return error;
+ }
+
+-int serve(stlink_t *sl, int port) {
+- int sock = socket(AF_INET, SOCK_STREAM, 0);
+- if(sock < 0) {
+- perror("socket");
+- return 1;
+- }
+-
+- unsigned int val = 1;
+- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
++int remote_open(int port) {
++ int sock = -1;
++ if (port == 0) {
++ remote_desc = STDOUT_FILENO;
++ remote_piping = 1;
++ signal(SIGINT, SIG_IGN);
++#ifdef __MINGW32__
++ if (_setmode (_fileno( stdout ), _O_BINARY) < 0)
++ fprintf(stderr, "cannot change stdout mode to binary");
++ if (_setmode (_fileno( stdin ), _O_BINARY) < 0)
++ fprintf(stderr, "cannot change stdin mode to binary");
++#else
++ signal(SIGIO, SIG_IGN);
++ signal(SIGCHLD, SIG_IGN);
++#endif
++ }
++ else {
++ sock = socket(AF_INET, SOCK_STREAM, 0);
++ if(sock < 0) {
++ perror("socket");
++ return 1;
++ }
+
+- struct sockaddr_in serv_addr;
+- memset(&serv_addr,0,sizeof(struct sockaddr_in));
+- serv_addr.sin_family = AF_INET;
+- serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+- serv_addr.sin_port = htons(port);
++ unsigned int val = 1;
++ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
+
+- if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
+- perror("bind");
+- return 1;
+- }
++ struct sockaddr_in serv_addr;
++ memset(&serv_addr,0,sizeof(struct sockaddr_in));
++ serv_addr.sin_family = AF_INET;
++ serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
++ serv_addr.sin_port = htons(port);
+
+- if(listen(sock, 5) < 0) {
+- perror("listen");
+- return 1;
+- }
++ if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
++ perror("bind");
++ return 1;
++ }
+
+- stlink_force_debug(sl);
+- stlink_reset(sl);
+- init_code_breakpoints(sl);
+- init_data_watchpoints(sl);
++ if(listen(sock, 5) < 0) {
++ perror("listen");
++ return 1;
++ }
++ }
+
+- printf("Listening at *:%d...\n", port);
++ if (!remote_piping) {
++ printf("Listening at *:%d...\n", port);
+
+- int client = accept(sock, NULL, NULL);
+- //signal (SIGINT, SIG_DFL);
+- if(client < 0) {
+- perror("accept");
+- return 1;
+- }
++ remote_desc = accept(sock, NULL, NULL);
++ //signal (SIGINT, SIG_DFL);
++ if(remote_desc < 0) {
++ perror("accept");
++ return 1;
++ }
+
+- close(sock);
++ close(sock);
++ }
+
+ printf("GDB connected.\n");
+
++ return 0;
++}
++
++int serve(stlink_t *sl) {
++
++ stlink_force_debug(sl);
++ stlink_reset(sl);
++ init_code_breakpoints(sl);
++ init_data_watchpoints(sl);
++
+ /*
+ * To allow resetting the chip from GDB it is required to
+ * emulate attaching and detaching to target.
+@@ -678,15 +741,14 @@ int serve(stlink_t *sl, int port) {
+ while(1) {
+ char* packet;
+
+- int status = gdb_recv_packet(client, &packet);
++ int status = gdb_recv_packet(remote_desc, &packet);
+ if(status < 0) {
+ fprintf(stderr, "cannot recv: %d\n", status);
+ return 1;
+ }
+
+- #ifdef DEBUG
+- printf("recv: %s\n", packet);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("recv: %s\n", packet);
+
+ char* reply = NULL;
+ reg regp;
+@@ -709,9 +771,8 @@ int serve(stlink_t *sl, int port) {
+ char* queryName = calloc(queryNameLength + 1, 1);
+ strncpy(queryName, &packet[1], queryNameLength);
+
+- #ifdef DEBUG
+- printf("query: %s;%s\n", queryName, params);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("query: %s;%s\n", queryName, params);
+
+ if(!strcmp(queryName, "Supported")) {
+ if(sl->chip_id==STM32_CHIPID_F4) {
+@@ -734,10 +795,9 @@ int serve(stlink_t *sl, int port) {
+ unsigned addr = strtoul(__s_addr, NULL, 16),
+ length = strtoul(s_length, NULL, 16);
+
+- #ifdef DEBUG
+- printf("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n",
+- type, op, annex, addr, length);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n",
++ type, op, annex, addr, length);
+
+ const char* data = NULL;
+
+@@ -771,9 +831,8 @@ int serve(stlink_t *sl, int port) {
+
+
+ if (!strncmp(params,"726573756d65",12)) {// resume
+-#ifdef DEBUG
+- printf("Rcmd: resume\n");
+-#endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("Rcmd: resume\n");
+ stlink_run(sl);
+
+ reply = strdup("OK");
+@@ -782,9 +841,9 @@ int serve(stlink_t *sl, int port) {
+
+ stlink_force_debug(sl);
+
+-#ifdef DEBUG
+- printf("Rcmd: halt\n");
+-#endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("Rcmd: halt\n");
++
+ } else if (!strncmp(params,"6a7461675f7265736574",20)) { //jtag_reset
+ reply = strdup("OK");
+
+@@ -792,9 +851,9 @@ int serve(stlink_t *sl, int port) {
+ stlink_jtag_reset(sl, 0);
+ stlink_force_debug(sl);
+
+-#ifdef DEBUG
+- printf("Rcmd: jtag_reset\n");
+-#endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("Rcmd: jtag_reset\n");
++
+ } else if (!strncmp(params,"7265736574",10)) { //reset
+ reply = strdup("OK");
+
+@@ -803,14 +862,12 @@ int serve(stlink_t *sl, int port) {
+ init_code_breakpoints(sl);
+ init_data_watchpoints(sl);
+
+-#ifdef DEBUG
+- printf("Rcmd: reset\n");
+-#endif
+- } else {
+-#ifdef DEBUG
+- printf("Rcmd: %s\n", params);
+-#endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("Rcmd: reset\n");
+
++ } else {
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("Rcmd: %s\n", params);
+ }
+
+ }
+@@ -839,10 +896,9 @@ int serve(stlink_t *sl, int port) {
+ unsigned addr = strtoul(__s_addr, NULL, 16),
+ length = strtoul(s_length, NULL, 16);
+
+- #ifdef DEBUG
+- printf("FlashErase: addr:%08x,len:%04x\n",
+- addr, length);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("FlashErase: addr:%08x,len:%04x\n",
++ addr, length);
+
+ if(flash_add_block(addr, length, sl) < 0) {
+ reply = strdup("E00");
+@@ -877,9 +933,8 @@ int serve(stlink_t *sl, int port) {
+ if(dec_index % 2 != 0)
+ dec_index++;
+
+- #ifdef DEBUG
+- printf("binary packet %d -> %d\n", data_length, dec_index);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("binary packet %d -> %d\n", data_length, dec_index);
+
+ if(flash_populate(addr, decoded, dec_index) < 0) {
+ reply = strdup("E00");
+@@ -908,7 +963,7 @@ int serve(stlink_t *sl, int port) {
+ stlink_run(sl);
+
+ while(1) {
+- int status = gdb_check_for_interrupt(client);
++ int status = gdb_check_for_interrupt(remote_desc);
+ if(status < 0) {
+ fprintf(stderr, "cannot check for int: %d\n", status);
+ return 1;
+@@ -1190,11 +1245,10 @@ int serve(stlink_t *sl, int port) {
+ }
+
+ if(reply) {
+- #ifdef DEBUG
+- printf("send: %s\n", reply);
+- #endif
++ if (logging_level >= LOGGING_LEVEL_GDBSERVER)
++ printf("send: %s\n", reply);
+
+- int result = gdb_send_packet(client, reply);
++ int result = gdb_send_packet(remote_desc, reply);
+ if(result != 0) {
+ fprintf(stderr, "cannot send: %d\n", result);
+ return 1;
diff --git a/source-builder/sb-builder b/source-builder/sb-builder
new file mode 100755
index 0000000..440d481
--- /dev/null
+++ b/source-builder/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/source-builder/sb-check b/source-builder/sb-check
new file mode 100755
index 0000000..43aae67
--- /dev/null
+++ b/source-builder/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/source-builder/sb-set-builder b/source-builder/sb-set-builder
new file mode 100755
index 0000000..7fb4f3a
--- /dev/null
+++ b/source-builder/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/source-builder/sb/build.py b/source-builder/sb/build.py
new file mode 100644
index 0000000..bd1305b
--- /dev/null
+++ b/source-builder/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/source-builder/sb/check.py b/source-builder/sb/check.py
new file mode 100644
index 0000000..f973683
--- /dev/null
+++ b/source-builder/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/source-builder/sb/config.py b/source-builder/sb/config.py
new file mode 100644
index 0000000..a9724dc
--- /dev/null
+++ b/source-builder/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/source-builder/sb/darwin.py b/source-builder/sb/darwin.py
new file mode 100644
index 0000000..5f8ac7f
--- /dev/null
+++ b/source-builder/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/source-builder/sb/defaults.py b/source-builder/sb/defaults.py
new file mode 100644
index 0000000..09b0922
--- /dev/null
+++ b/source-builder/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-<label> : Add the --with-<label> to the build'
+ print '--without-<label> : Add the --without-<label> to the build'
+ if self.optargs:
+ for a in self.optargs:
+ print '%-22s : %s' % (a, self.optargs[a])
+ raise error.exit()
+
+ def __init__(self, argv, optargs):
+ self.command_path = path.dirname(argv[0])
+ if len(self.command_path) == 0:
+ self.command_path = '.'
+ self.command_name = path.basename(argv[0])
+ self.args = argv[1:]
+ self.optargs = optargs
+ self.defaults = {}
+ for to in command_line._long_true_opts:
+ self.defaults[command_line._long_true_opts[to]] = ('none', 'none', '0')
+ self.defaults['_sbdir'] = ('dir', 'required', path.shell(self.command_path))
+ self._process()
+
+ def __str__(self):
+ def _dict(dd):
+ s = ''
+ ddl = dd.keys()
+ ddl.sort()
+ for d in ddl:
+ s += ' ' + d + ': ' + str(dd[d]) + '\n'
+ return s
+
+ s = 'command: ' + self.command() + \
+ '\nargs: ' + str(self.args) + \
+ '\nopts:\n' + _dict(self.opts)
+
+ return s
+
+ def _process(self):
+
+ def _process_lopt(opt, arg, long_opts, args, values = False):
+ for lo in long_opts:
+ if values and opt.startswith(lo):
+ equals = opt.find('=')
+ if equals < 0:
+ if arg == len(args) - 1:
+ raise error.general('missing option value: ' + lo)
+ arg += 1
+ value = args[arg]
+ else:
+ value = opt[equals + 1:]
+ if type(long_opts[lo]) is tuple:
+ if long_opts[lo][1]:
+ value = path.shell(value)
+ macro = long_opts[lo][0]
+ else:
+ macro = long_opts[lo]
+ return lo, macro, value, arg
+ elif opt == lo:
+ return lo, long_opts[lo], True, arg
+ return None, None, None, arg
+
+ self.opts = command_line._defaults
+ i = 0
+ while i < len(self.args):
+ a = self.args[i]
+ if a.startswith('-'):
+ if a.startswith('--'):
+ if a.startswith('--warn-all'):
+ self.opts['warn-all'] = True
+ elif a == '--help':
+ self._help()
+ else:
+ lo, macro, value, i = _process_lopt(a, i,
+ command_line._long_true_opts,
+ self.args)
+ if lo:
+ self.defaults[macro] = ('none', 'none', '1')
+ self.opts[lo[2:]] = '1'
+ else:
+ lo, macro, value, i = _process_lopt(a, i,
+ command_line._long_opts,
+ self.args, True)
+ if lo:
+ self.defaults[macro] = ('none', 'none', value)
+ self.opts[lo[2:]] = value
+ else:
+ #
+ # The target triplet is 'cpu-vendor-os'.
+ #
+ lo, macro, value, i = _process_lopt(a, i,
+ command_line._target_triplets,
+ self.args, True)
+ if lo:
+ #
+ # This is a target triplet. Run it past config.sub to make
+ # make sure it is ok.
+ #
+ e = execute.capture_execution()
+ config_sub = path.join(self.command_path,
+ basepath, 'config.sub')
+ exit_code, proc, output = e.shell(config_sub + ' ' + value)
+ if exit_code == 0:
+ value = output
+ self.defaults[macro] = ('triplet', 'none', value)
+ self.opts[lo[2:]] = value
+ _arch = macro + '_cpu'
+ _vendor = macro + '_vendor'
+ _os = macro + '_os'
+ _arch_value = ''
+ _vendor_value = ''
+ _os_value = ''
+ dash = value.find('-')
+ if dash >= 0:
+ _arch_value = value[:dash]
+ value = value[dash + 1:]
+ dash = value.find('-')
+ if dash >= 0:
+ _vendor_value = value[:dash]
+ value = value[dash + 1:]
+ if len(value):
+ _os_value = value
+ self.defaults[_arch] = ('none', 'none', _arch_value)
+ self.defaults[_vendor] = ('none', 'none', _vendor_value)
+ self.defaults[_os] = ('none', 'none', _os_value)
+ if not lo and a not in self.optargs:
+ raise error.general('invalid argument (try --help): %s' % (a))
+ else:
+ if a == '-f':
+ self.opts['force'] = '1'
+ elif a == '-n':
+ self.opts['dry-run'] = '1'
+ elif a == '-q':
+ self.opts['quiet'] = '1'
+ elif a == '-?':
+ self._help()
+ else:
+ raise error.general('invalid argument (try --help): %s' % (a))
+ else:
+ self.opts['params'].append(a)
+ i += 1
+
+ def _post_process(self, _defaults):
+ if self.no_smp():
+ _defaults['_smp_mflags'] = ('none', 'none', _defaults['nil'][2])
+ if _defaults['_host'][2] == _defaults['nil'][2]:
+ raise error.general('host not set')
+ return _defaults
+
+ def expand(self, s, _defaults):
+ """Simple basic expander of config file macros."""
+ mf = re.compile(r'%{[^}]+}')
+ expanded = True
+ while expanded:
+ expanded = False
+ for m in mf.findall(s):
+ name = m[2:-1]
+ if name in _defaults:
+ s = s.replace(m, _defaults[name][2])
+ expanded = True
+ else:
+ raise error.general('cannot process default macro: ' + m)
+ return s
+
+ def command(self):
+ return path.join(self.command_path, self.command_name)
+
+ def force(self):
+ return self.opts['force'] != '0'
+
+ def dry_run(self):
+ return self.opts['dry-run'] != '0'
+
+ def set_dry_run(self):
+ self.opts['dry-run'] = '1'
+
+ def quiet(self):
+ return self.opts['quiet'] != '0'
+
+ def trace(self):
+ return self.opts['trace'] != '0'
+
+ def warn_all(self):
+ return self.opts['warn-all'] != '0'
+
+ def no_clean(self):
+ return self.opts['no-clean'] != '0'
+
+ def no_smp(self):
+ return self.opts['no-smp'] != '0'
+
+ def rebuild(self):
+ return self.opts['rebuild'] != '0'
+
+ def params(self):
+ return self.opts['params']
+
+ def get_arg(self, arg):
+ if not arg in self.optargs:
+ raise error.internal('bad arg: %s' % (arg))
+ for a in self.args:
+ if a.startswith(arg):
+ return a
+ return None
+
+ def get_config_files(self, config):
+ #
+ # Convert to shell paths and return shell paths.
+ #
+ # @fixme should this use a passed in set of defaults and not
+ # not the initial set of values ?
+ #
+ config = path.shell(config)
+ if '*' in config or '?' in config:
+ print config
+ configdir = path.dirname(config)
+ configbase = path.basename(config)
+ if len(configbase) == 0:
+ configbase = '*'
+ if not configbase.endswith('.cfg'):
+ configbase = configbase + '.cfg'
+ if len(configdir) == 0:
+ configdir = self.expand(defaults['_configdir'][2], defaults)
+ configs = []
+ for cp in configdir.split(':'):
+ hostconfigdir = path.host(cp)
+ for f in glob.glob(os.path.join(hostconfigdir, configbase)):
+ configs += path.shell(f)
+ else:
+ configs = [config]
+ return configs
+
+ def config_files(self):
+ configs = []
+ for config in self.opts['params']:
+ configs.extend(self.get_config_files(config))
+ return configs
+
+ def logfiles(self):
+ if 'log' in self.opts:
+ return self.opts['log'].split(',')
+ return ['stdout']
+
+ def urls(self):
+ if 'url' in self.opts:
+ return self.opts['url'].split(',')
+ return None
+
+ def prefixbase(self):
+ if 'prefixbase' in self.opts:
+ return self.opts['prefixbase']
+ return None
+
+def load(args, optargs = None):
+ """
+ Copy the defaults, get the host specific values and merge them overriding
+ any matching defaults, then create an options object to handle the command
+ line merging in any command line overrides. Finally post process the
+ command line.
+ """
+ d = defaults
+ overrides = None
+ if os.name == 'nt':
+ import windows
+ overrides = windows.load()
+ else:
+ uname = os.uname()
+ try:
+ if uname[0] == 'Darwin':
+ import darwin
+ overrides = darwin.load()
+ elif uname[0] == 'FreeBSD':
+ import freebsd
+ overrides = freebsd.load()
+ elif uname[0] == 'Linux':
+ import linux
+ overrides = linux.load()
+ except:
+ pass
+ if overrides is None:
+ raise error.general('no hosts defaults found; please add')
+ for k in overrides:
+ d[k] = overrides[k]
+ o = command_line(args, optargs)
+ for k in o.defaults:
+ d[k] = o.defaults[k]
+ d = o._post_process(d)
+ return o, d
+
+if __name__ == '__main__':
+ import sys
+ try:
+ _opts, _defaults = load(args = sys.argv)
+ print _opts
+ pprint.pprint(_defaults)
+ except error.general, gerr:
+ print gerr
+ sys.exit(1)
+ except error.internal, ierr:
+ print ierr
+ sys.exit(1)
+ sys.exit(0)
diff --git a/source-builder/sb/error.py b/source-builder/sb/error.py
new file mode 100644
index 0000000..5617c17
--- /dev/null
+++ b/source-builder/sb/error.py
@@ -0,0 +1,54 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# Various errors we can raise.
+#
+
+class error(Exception):
+ """Base class for Builder exceptions."""
+ def set_output(self, msg):
+ self.msg = msg
+ def __str__(self):
+ return self.msg
+
+class general(error):
+ """Raise for a general error."""
+ def __init__(self, what):
+ self.set_output('error: ' + what)
+
+class internal(error):
+ """Raise for an internal error."""
+ def __init__(self, what):
+ self.set_output('internal error: ' + what)
+
+class exit(error):
+ """Raise for to exit."""
+ def __init__(self):
+ pass
+
+if __name__ == '__main__':
+ try:
+ raise general('a general error')
+ except general, gerr:
+ print 'caught:', gerr
+ try:
+ raise internal('an internal error')
+ except internal, ierr:
+ print 'caught:', ierr
diff --git a/source-builder/sb/execute.py b/source-builder/sb/execute.py
new file mode 100755
index 0000000..ad4ffde
--- /dev/null
+++ b/source-builder/sb/execute.py
@@ -0,0 +1,363 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# Execute commands or scripts.
+#
+# Note, the subprocess module is only in Python 2.4 or higher.
+#
+
+import os
+import re
+import sys
+import subprocess
+import threading
+
+import error
+import log
+
+# Redefine the PIPE from subprocess
+PIPE = subprocess.PIPE
+
+# Regular expression to find quotes.
+qstr = re.compile('[rR]?\'([^\\n\'\\\\]|\\\\.)*\'|[rR]?"([^\\n"\\\\]|\\\\.)*"')
+
+def check_type(command):
+ """Checks the type of command we have. The types are spawn and
+ shell."""
+ if command in ['spawn', 'shell']:
+ return True
+ return False
+
+def arg_list(args):
+ """Turn a string of arguments into a list suitable for
+ spawning a command. If the args are already a list return
+ it."""
+ if type(args) is list:
+ return args
+ argstr = args
+ args = []
+ while len(argstr):
+ qs = qstr.search(argstr)
+ if not qs:
+ args.extend(argstr.split())
+ argstr= ''
+ else:
+ # We have a quoted string. Get the string before
+ # the quoted string and splt on white space then
+ # add the quoted string as an option then remove
+ # the first + quoted string and try again
+ front = argstr[:qs.start()]
+ args.extend(front.split())
+ args.append(argstr[qs.start() + 1:qs.end() - 1])
+ argstr = argstr[qs.end():]
+ return args
+
+def arg_subst(command, substs):
+ """Substitute the %[0-9] in the command with the subst values."""
+ args = arg_list(command)
+ if substs:
+ for a in range(0, len(args)):
+ for r in range(0, len(substs)):
+ args[a] = re.compile(('%%%d' % (r))).sub(substs[r], args[a])
+ return args
+
+def arg_subst_str(command, subst):
+ cmd = arg_subst(command, subst)
+ def add(x, y): return x + ' ' + str(y)
+ return reduce(add, cmd, '')
+
+class execute:
+ """Execute commands or scripts. The 'output' is a funtion
+ that handles the output from the process."""
+ def __init__(self, output = None, error_prefix = '', verbose = False):
+ self.output = output
+ self.error_prefix = error_prefix
+ self.verbose = verbose
+ self.shell_exe = None
+ self.shell_commands = False
+ self.path = None
+ self.environment = None
+
+ def capture(self, proc, timeout = None):
+ """Create 2 threads to read stdout and stderr and send to the
+ output handler. Based on the 'communicate' code in the subprocess
+ module."""
+ def _readthread(fh, out, prefix = ''):
+ """Read from a file handle and write to the output handler
+ until the file closes."""
+ while True:
+ line = fh.readline()
+ if len(line) == 0:
+ break
+ if out:
+ out(prefix + line)
+ else:
+ log.output(prefix + line)
+ def _timerthread(proc, timer):
+ """Timer thread calls the timer handler if one
+ is present once a second. The user provides a handler
+ and returns False to kill the process or True continue."""
+ while True:
+ time.sleep(1)
+ if not timer(proc):
+ proc.stdout.close()
+ proc.stderr.close()
+
+ if proc.stdout:
+ stdout_thread = threading.Thread(target = _readthread,
+ args = (proc.stdout,
+ self.output,
+ ''))
+ stdout_thread.setDaemon(True)
+ stdout_thread.start()
+ if proc.stderr:
+ stderr_thread = threading.Thread(target = _readthread,
+ args = (proc.stderr,
+ self.output,
+ self.error_prefix))
+ stderr_thread.setDaemon(True)
+ stderr_thread.start()
+ if proc.stdout:
+ stdout_thread.join()
+ if proc.stderr:
+ stderr_thread.join()
+ return proc.wait()
+
+ def open(self, command, capture = True, shell = False,
+ cwd = None, env = None,
+ stdin = None, stdout = None, stderr = None):
+ """Open a command with arguments. Provide the arguments as a list or
+ a string."""
+ if self.verbose:
+ s = command
+ if type(command) is list:
+ def add(x, y): return x + ' ' + str(y)
+ s = reduce(add, command, '')[1:]
+ what = 'spawn'
+ if shell:
+ what = 'shell'
+ log.output(what + ': ' + s)
+ if shell and self.shell_exe:
+ command = arg_list(command)
+ command[:0] = self.shell_exe
+ if not stdout:
+ stdout = subprocess.PIPE
+ if not stderr:
+ stderr = subprocess.PIPE
+ proc = None
+ if cwd is None:
+ cwd = self.path
+ if env is None:
+ env = self.environment
+ try:
+ # Work around a problem on Windows with commands that
+ # have a '.' and no extension. Windows needs the full
+ # command name.
+ if sys.platform == "win32" and type(command) is list:
+ if command[0].find('.') >= 0:
+ r, e = os.path.splitext(command[0])
+ if e not in ['.exe', '.com', '.bat']:
+ command[0] = command[0] + '.exe'
+ proc = subprocess.Popen(command, shell = shell,
+ cwd = cwd, env = env,
+ stdin = stdin, stdout = stdout,
+ stderr = stderr)
+ if not capture:
+ return (0, proc)
+ exit_code = self.capture(proc)
+ if self.verbose:
+ log.output('exit: ' + str(exit_code))
+ except OSError, ose:
+ exit_code = ose.errno
+ if self.verbose:
+ log.output('exit: ' + str(ose))
+ return (exit_code, proc)
+
+ def spawn(self, command, capture = True, cwd = None, env = None,
+ stdin = None, stdout = None, stderr = None):
+ """Spawn a command with arguments. Provide the arguments as a list or
+ a string."""
+ return self.open(command, capture, False, cwd, env,
+ stdin, stdout, stderr)
+
+ def shell(self, command, capture = True, cwd = None, env = None,
+ stdin = None, stdout = None, stderr = None):
+ """Execute a command within a shell context. The command can contain
+ argumments. The shell is specific to the operating system. For example
+ it is cmd.exe on Windows XP."""
+ return self.open(command, capture, True, cwd, env,
+ stdin, stdout, stderr)
+
+ def command(self, command, args = None, capture = True, shell = False,
+ cwd = None, env = None,
+ stdin = None, stdout = None, stderr = None):
+ """Run the command with the args. The args can be a list
+ or a string."""
+ if args and not type(args) is list:
+ args = arg_list(args)
+ cmd = [command]
+ if args:
+ cmd.extend(args)
+ return self.open(cmd, capture = capture, shell = shell,
+ cwd = cwd, env = env,
+ stdin = stdin, stdout = stdout, stderr = stderr)
+
+ def command_subst(self, command, substs, capture = True, shell = False,
+ cwd = None, env = None,
+ stdin = None, stdout = None, stderr = None):
+ """Run the command from the config data with the
+ option format string subsituted with the subst variables."""
+ args = arg_subst(command, substs)
+ return self.command(args[0], args[1:], capture = capture,
+ shell = shell or self.shell_commands,
+ cwd = cwd, env = env,
+ stdin = stdin, stdout = stdout, stderr = stderr)
+
+ def set_shell(self, execute):
+ """Set the shell to execute when issuing a shell command."""
+ args = arg_list(execute)
+ if len(args) == 0 or not os.path.isfile(args[0]):
+ raise error.general('could find shell: ' + execute)
+ self.shell_exe = args
+
+ def command_use_shell(self):
+ """Force all commands to use a shell. This can be used with set_shell
+ to allow Unix commands be executed on Windows with a Unix shell such
+ as Cygwin or MSYS. This may cause piping to fail."""
+ self.shell_commands = True
+
+ def set_output(self, output):
+ """Set the output handler. The stdout of the last process in a pipe
+ line is passed to this handler."""
+ old_output = self.output
+ self.output = output
+ return old_output
+
+ def set_path(self, path):
+ """Set the path changed to before the child process is created."""
+ old_path = self.path
+ self.path = path
+ return old_path
+
+ def set_environ(self, environment):
+ """Set the environment passed to the child process when created."""
+ old_environment = self.environment
+ self.environment = environment
+ return old_environment
+
+class capture_execution(execute):
+ """Capture all output as a string and return it."""
+
+ class _output_snapper:
+ def __init__(self, log = None, dump = False):
+ self.output = ''
+ self.log = log
+ self.dump = dump
+
+ def handler(self, text):
+ if not self.dump:
+ if self.log is not None:
+ self.log.output(text)
+ else:
+ self.output += text
+
+ def get_and_clear(self):
+ text = self.output
+ self.output = ''
+ return text.strip()
+
+ def __init__(self, log = None, dump = False, error_prefix = '', verbose = False):
+ self.snapper = capture_execution._output_snapper(log = log, dump = dump)
+ execute.__init__(self, output = self.snapper.handler,
+ error_prefix = error_prefix,
+ verbose = verbose)
+
+ def open(self, command, capture = True, shell = False, cwd = None, env = None,
+ stdin = None, stdout = None, stderr = None):
+ if not capture:
+ raise error.general('output capture must be true; leave as default')
+ #self.snapper.get_and_clear()
+ exit_code, proc = execute.open(self, command, capture = True, shell = shell,
+ cwd = cwd, env = env,
+ stdin = stdin, stdout = stdout, stderr = stderr)
+ return (exit_code, proc, self.snapper.get_and_clear())
+
+ def set_output(self, output):
+ raise error.general('output capture cannot be overrided')
+
+if __name__ == "__main__":
+ def run_tests(e, commands, use_shell):
+ for c in commands['shell']:
+ e.shell(c)
+ for c in commands['spawn']:
+ e.spawn(c)
+ for c in commands['cmd']:
+ if type(c) is str:
+ e.command(c, shell = use_shell)
+ else:
+ e.command(c[0], c[1], shell = use_shell)
+ for c in commands['csubsts']:
+ e.command_subst(c[0], c[1], shell = use_shell)
+ ec, proc = e.command(commands['pipe'][0], commands['pipe'][1],
+ capture = False, stdin = subprocess.PIPE)
+ if ec == 0:
+ print 'piping input into ' + commands['pipe'][0] + ': ' + \
+ commands['pipe'][2]
+ proc.stdin.write(commands['pipe'][2])
+ proc.stdin.close()
+ e.capture(proc)
+ del proc
+
+ cmd_shell_test = 'if "%OS%" == "Windows_NT" (echo It is WinNT) else echo Is is not WinNT'
+ sh_shell_test = 'x="me"; if [ $x = "me" ]; then echo "It was me"; else "It was him"; fi'
+
+ commands = {}
+ commands['windows'] = {}
+ commands['unix'] = {}
+ commands['windows']['shell'] = ['cd', 'dir /w', '.\\xyz', cmd_shell_test]
+ commands['windows']['spawn'] = ['hostname', 'hostnameZZ', ['netstat', '/e']]
+ commands['windows']['cmd'] = [('ipconfig'), ('nslookup', 'www.python.org')]
+ commands['windows']['csubsts'] = [('netstat %0', ['-a']),
+ ('netstat %0 %1', ['-a', '-n'])]
+ commands['windows']['pipe'] = ('ftp', None, 'help\nquit')
+ commands['unix']['shell'] = ['pwd', 'ls -las', './xyz', sh_shell_test]
+ commands['unix']['spawn'] = ['ls', 'execute.pyc', ['ls', '-i']]
+ commands['unix']['cmd'] = [('date'), ('date', '-R'), ('date', ['-u', '+%d %D']),
+ ('date', '-u "+%d %D %S"')]
+ commands['unix']['csubsts'] = [('date %0 "+%d %D %S"', ['-u']),
+ ('date %0 %1', ['-u', '+%d %D %S'])]
+ commands['unix']['pipe'] = ('grep', 'hello', 'hello world')
+
+ print arg_list('cmd a1 a2 "a3 is a string" a4')
+ print arg_list('cmd b1 b2 "b3 is a string a4')
+ print arg_subst(['nothing', 'xx-%0-yyy', '%1', '%2-something'],
+ ['subst0', 'subst1', 'subst2'])
+
+ e = execute(error_prefix = 'ERR: ', verbose = True)
+ if sys.platform == "win32":
+ run_tests(e, commands['windows'], False)
+ if os.path.exists('c:\\msys\\1.0\\bin\\sh.exe'):
+ e.set_shell('c:\\msys\\1.0\\bin\\sh.exe --login -c')
+ commands['unix']['pipe'] = ('c:\\msys\\1.0\\bin\\grep',
+ 'hello', 'hello world')
+ run_tests(e, commands['unix'], True)
+ else:
+ run_tests(e, commands['unix'], False)
+ del e
diff --git a/source-builder/sb/freebsd.py b/source-builder/sb/freebsd.py
new file mode 100644
index 0000000..18a2c84
--- /dev/null
+++ b/source-builder/sb/freebsd.py
@@ -0,0 +1,67 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# RTEMS Tools is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# RTEMS Tools is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with RTEMS Tools. If not, see <http://www.gnu.org/licenses/>.
+#
+
+#
+# This code is based on what ever doco about spec files I could find and
+# RTEMS project's spec files.
+#
+
+import pprint
+import os
+
+import execute
+
+def load():
+ uname = os.uname()
+ sysctl = '/sbin/sysctl '
+ e = execute.capture_execution()
+ exit_code, proc, output = e.shell(sysctl + 'hw.ncpu')
+ if exit_code == 0:
+ smp_mflags = '-j' + output.split(' ')[1].strip()
+ else:
+ smp_mflags = ''
+ if uname[4] == 'amd64':
+ cpu = 'x86_64'
+ else:
+ cpu = uname[4]
+ version = uname[2]
+ if version.find('-') > 0:
+ version = version.split('-')[0]
+ defines = {
+ '_os': ('none', 'none', 'freebsd'),
+ '_host': ('triplet', 'required', cpu + '-freebsd' + version),
+ '_host_vendor': ('none', 'none', 'pc'),
+ '_host_os': ('none', 'none', 'freebsd'),
+ '_host_cpu': ('none', 'none', cpu),
+ '_host_alias': ('none', 'none', '%{nil}'),
+ '_host_arch': ('none', 'none', cpu),
+ '_usr': ('dir', 'required', '/usr/local'),
+ '_var': ('dir', 'optional', '/usr/local/var'),
+ 'optflags': ('none', 'none', '-O2 -I/usr/local/include -L/usr/local/lib'),
+ '_smp_mflags': ('none', 'none', smp_mflags),
+ '__bash': ('exe', 'optional', '/usr/local//bin/bash'),
+ '__xz': ('exe', 'optional', '/usr/bin/xz'),
+ '__make': ('exe', 'required', 'gmake')
+ }
+ return defines
+
+if __name__ == '__main__':
+ pprint.pprint(load())
diff --git a/source-builder/sb/linux.py b/source-builder/sb/linux.py
new file mode 100644
index 0000000..cbc1cb9
--- /dev/null
+++ b/source-builder/sb/linux.py
@@ -0,0 +1,63 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# This code is based on what ever doco about spec files I could find and
+# RTEMS project's spec files.
+#
+
+import pprint
+import os
+
+import execute
+
+def load():
+ uname = os.uname()
+ smp_mflags = ''
+ processors = '/bin/grep processor /proc/cpuinfo'
+ e = execute.capture_execution()
+ exit_code, proc, output = e.shell(processors)
+ if exit_code == 0:
+ cpus = 0
+ for l in output.split('\n'):
+ count = l.split(':')[1].strip()
+ if count > cpus:
+ cpus = int(count)
+ if cpus > 0:
+ smp_mflags = '-j%d' % (cpus)
+ defines = {
+ '_os': ('none', 'none', 'linux'),
+ '_host': ('triplet', 'required', uname[4] + '-linux-gnu'),
+ '_host_vendor': ('none', 'none', 'gnu'),
+ '_host_os': ('none', 'none', 'linux'),
+ '_host_cpu': ('none', 'none', uname[4]),
+ '_host_alias': ('none', 'none', '%{nil}'),
+ '_host_arch': ('none', 'none', uname[4]),
+ '_usr': ('dir', 'required', '/usr'),
+ '_var': ('dir', 'required', '/usr/var'),
+ 'optflags': ('none', 'none', '-O2 -fasynchronous-unwind-tables'),
+ '_smp_mflags': ('none', 'none', smp_mflags),
+ '__bzip2': ('exe', 'required', '/usr/bin/bzip2'),
+ '__gzip': ('exe', 'required', '/bin/gzip'),
+ '__tar': ('exe', 'required', '/bin/tar')
+ }
+ return defines
+
+if __name__ == '__main__':
+ pprint.pprint(load())
diff --git a/source-builder/sb/log.py b/source-builder/sb/log.py
new file mode 100755
index 0000000..71c77f0
--- /dev/null
+++ b/source-builder/sb/log.py
@@ -0,0 +1,111 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-testing'.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# Log output to stdout and/or a file.
+#
+
+import os
+import sys
+
+import error
+
+#
+# A global log.
+#
+default = None
+
+def set_default_once(log):
+ if default is None:
+ default = log
+
+def output(text = os.linesep, log = None):
+ """Output the text to a log if provided else send it to stdout."""
+ if text is None:
+ text = os.linesep
+ if type(text) is list:
+ _text = ''
+ for l in text:
+ _text += l + os.linesep
+ text = _text
+ if log:
+ log.output(text)
+ elif default is not None:
+ default.output(text)
+ else:
+ for l in text.replace(chr(13), '').splitlines():
+ print l
+
+def flush(log = None):
+ if log:
+ log.flush()
+ elif default is not None:
+ default.flush()
+
+class log:
+ """Log output to stdout or a file."""
+ def __init__(self, streams = None):
+ self.fhs = [None, None]
+ if streams:
+ for s in streams:
+ if s == 'stdout':
+ self.fhs[0] = sys.stdout
+ elif s == 'stderr':
+ self.fhs[1] = sys.stderr
+ else:
+ try:
+ self.fhs.append(file(s, 'w'))
+ except IOError, ioe:
+ raise error.general("creating log file '" + s + \
+ "': " + str(ioe))
+
+ def __del__(self):
+ for f in range(2, len(self.fhs)):
+ self.fhs[f].close()
+
+ def has_stdout(self):
+ return self.fhs[0] is not None
+
+ def has_stderr(self):
+ return self.fhs[1] is not None
+
+ def output(self, text):
+ """Output the text message to all the logs."""
+ # Reformat the text to have local line types.
+ out = ''
+ for l in text.replace(chr(13), '').splitlines():
+ out += l + os.linesep
+ for f in range(0, len(self.fhs)):
+ if self.fhs[f] is not None:
+ self.fhs[f].write(out)
+
+ def flush(self):
+ """Flush the output."""
+ for f in range(0, len(self.fhs)):
+ if self.fhs[f] is not None:
+ self.fhs[f].flush()
+
+if __name__ == "__main__":
+ l = log(['stdout', 'log.txt'])
+ for i in range(0, 10):
+ l.output('hello world: %d\n' % (i))
+ l.output('hello world CRLF\r\n')
+ l.output('hello world NONE')
+ l.flush()
+ del l
diff --git a/source-builder/sb/path.py b/source-builder/sb/path.py
new file mode 100644
index 0000000..0a5f84c
--- /dev/null
+++ b/source-builder/sb/path.py
@@ -0,0 +1,95 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# Manage paths locally. The internally the path is in Unix or shell format and
+# we convert to the native format when performing operations at the Python
+# level. This allows macro expansion to work.
+#
+
+import os
+import string
+
+windows = os.name == 'nt'
+
+def host(path):
+ if path is not None:
+ while '//' in path:
+ path = path.replace('//', '/')
+ if windows and len(path) > 2:
+ if path[0] == '/' and path[2] == '/' and \
+ (path[1] in string.ascii_lowercase or \
+ path[1] in string.ascii_uppercase):
+ path = ('%s:%s' % (path[1], path[2:])).replace('/', '\\')
+ return path
+
+def shell(path):
+ if path is not None:
+ if windows and len(path) > 1 and path[1] == ':':
+ path = ('/%s%s' % (path[0], path[2:])).replace('\\', '/')
+ while '//' in path:
+ path = path.replace('//', '/')
+ return path
+
+def basename(path):
+ return shell(os.path.basename(path))
+
+def dirname(path):
+ return shell(os.path.dirname(path))
+
+def join(path, *args):
+ path = shell(path)
+ for arg in args:
+ path += '/' + shell(arg)
+ return shell(path)
+
+def abspath(path):
+ return shell(os.path.abspath(host(path)))
+
+def splitext(path):
+ root, ext = os.path.splitext(host(path))
+ return shell(root), ext
+
+def exists(path):
+ return os.path.exists(host(path))
+
+def isdir(path):
+ return os.path.isdir(host(path))
+
+def isfile(path):
+ return os.path.isfile(host(path))
+
+def isabspath(path):
+ return path[0] == '/'
+
+if __name__ == '__main__':
+ print host('/a/b/c/d-e-f')
+ print host('//a/b//c/d-e-f')
+ print shell('/w/x/y/z')
+ print basename('/as/sd/df/fg/me.txt')
+ print dirname('/as/sd/df/fg/me.txt')
+ print join('/d', 'g', '/tyty/fgfg')
+ windows = True
+ print host('/a/b/c/d-e-f')
+ print host('//a/b//c/d-e-f')
+ print shell('/w/x/y/z')
+ print shell('w:/x/y/z')
+ print basename('x:/sd/df/fg/me.txt')
+ print dirname('x:/sd/df/fg/me.txt')
+ print join('s:/d/', '/g', '/tyty/fgfg')
diff --git a/source-builder/sb/setbuilder.py b/source-builder/sb/setbuilder.py
new file mode 100644
index 0000000..eca60e4
--- /dev/null
+++ b/source-builder/sb/setbuilder.py
@@ -0,0 +1,250 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# This code builds a cross-gcc compiler tool suite given a tool set. A tool
+# set lists the various tools. These are specific tool configurations.
+#
+
+import distutils.dir_util
+import glob
+import operator
+import os
+
+import build
+import check
+import defaults
+import error
+import log
+import path
+
+#
+# Version of Source Builder Set Builder.
+#
+version = '0.1'
+
+def _trace(opts, text):
+ if opts.trace():
+ print text
+
+def _notice(opts, text):
+ if not opts.quiet() and not log.default.has_stdout():
+ print text
+ log.output(text)
+ log.flush()
+
+class buildset:
+ """Build a set builds a set of packages."""
+
+ def __init__(self, bset, _defaults, opts):
+ _trace(opts, '_bset:%s: init' % (bset))
+ self.opts = opts
+ self.defaults = _defaults
+ self.bset = bset
+ self.bset_pkg = '%s-%s-set' % (self.opts.expand('%{_target}', _defaults),
+ self.bset)
+
+ def _output(self, text):
+ if not self.opts.quiet():
+ log.output(text)
+
+ def copy(self, src, dst):
+ if os.path.isdir(path.host(src)):
+ topdir = self.opts.expand('%{_topdir}', self.defaults)
+ what = '%s -> %s' % \
+ (path.host(src[len(topdir) + 1:]), path.host(dst[len(topdir) + 1:]))
+ _notice(self.opts, 'installing: %s' % (what))
+ if not self.opts.dry_run():
+ try:
+ files = distutils.dir_util.copy_tree(path.host(src),
+ path.host(dst))
+ for f in files:
+ self._output(f)
+ except IOError, err:
+ raise error.general('installing tree: %s: %s' % (what, str(err)))
+ except distutils.errors.DistutilsFileError, err:
+ raise error.general('installing tree: %s' % (str(err)))
+
+ def first_package(self, _build):
+ tmproot = path.abspath(_build.config.expand('%{_tmproot}'))
+ _build.rmdir(tmproot)
+ _build.mkdir(tmproot)
+ prefix = _build.config.expand('%{_prefix}')
+ if prefix[0] == os.sep:
+ prefix = prefix[1:]
+ tmpprefix = path.join(tmproot, prefix)
+ tmpbindir = path.join(tmpprefix, 'bin')
+ # exporting to the environment
+ os.environ['SB_TMPPREFIX'] = tmpprefix
+ os.environ['SB_TMPBINDIR'] = tmpbindir
+ os.environ['PATH'] = path.host(tmpbindir) + os.pathsep + os.environ['PATH']
+ self._output('path: ' + os.environ['PATH'])
+ # shell format
+ return tmproot
+
+ def every_package(self, _build, tmproot):
+ self.copy(_build.config.abspath('%{buildroot}'), tmproot)
+
+ def last_package(self, _build, tmproot):
+ tar = path.join(_build.config.expand('%{_tardir}'),
+ _build.config.expand('%s.tar.bz2' % (self.bset_pkg)))
+ _notice(self.opts, 'tarball: %s' % path.host(tar))
+ if not self.opts.dry_run():
+ cmd = _build.config.expand("'cd " + tmproot + \
+ " && %{__tar} -cf - . | %{__bzip2} > " + tar + "'")
+ _build.run(cmd, shell_opts = '-c', cwd = tmproot)
+
+ def load(self):
+
+ def _clean(line):
+ line = line[0:-1]
+ b = line.find('#')
+ if b >= 0:
+ line = line[1:b]
+ return line.strip()
+
+ exbset = self.opts.expand(self.bset, self.defaults)
+
+ self.defaults['_bset'] = ('none', 'none', exbset)
+
+ root, ext = path.splitext(exbset)
+
+ if exbset.endswith('.bset'):
+ bset = exbset
+ else:
+ bset = '%s.bset' % (exbset)
+
+ bsetname = bset
+
+ if not path.exists(bsetname):
+ for cp in self.opts.expand('%{_configdir}', self.defaults).split(':'):
+ configdir = path.abspath(cp)
+ bsetname = path.join(configdir, bset)
+ if path.exists(bsetname):
+ break
+ bsetname = None
+ if bsetname is None:
+ raise error.general('no build set file found: %s' % (bset))
+ try:
+ if self.opts.trace():
+ print '_bset:%s: open: %s' % (self.bset, bsetname)
+ bset = open(path.host(bsetname), 'r')
+ except IOError, err:
+ raise error.general('error opening bset file: %s' % (bsetname))
+
+ configs = []
+
+ try:
+ lc = 0
+ for l in bset:
+ lc += 1
+ l = _clean(l)
+ if len(l) == 0:
+ continue
+ if self.opts.trace():
+ print '%03d: %s' % (lc, l)
+ if ':' in l:
+ ls = l.split(':')
+ if ls[0].strip() == 'package':
+ self.bset_pkg = self.opts.expand(ls[1].strip(), self.defaults)
+ self.defaults['package'] = ('none', 'none', self.bset_pkg)
+ elif l[0] == '%':
+ if l.startswith('%define'):
+ ls = l.split()
+ self.defaults[ls[1].strip()] = ('none', 'none', ls[2].strip())
+ else:
+ raise error.general('invalid directive in build set files: %s' % (l))
+ else:
+ configs += [l.strip()]
+ except:
+ bset.close()
+ raise
+
+ bset.close()
+
+ return configs
+
+ def make(self):
+
+ _trace(self.opts, '_bset:%s: make' % (self.bset))
+ _notice(self.opts, 'Build Set: %s' % (self.bset))
+
+ configs = self.load()
+
+ _trace(self.opts, '_bset:%s: configs: %s' % (self.bset, ','.join(configs)))
+
+ current_path = os.environ['PATH']
+ try:
+ builds = []
+ for s in range(0, len(configs)):
+ b = build.build(configs[s], _defaults = self.defaults, opts = self.opts)
+ if s == 0:
+ tmproot = self.first_package(b)
+ b.make()
+ self.every_package(b, tmproot)
+ if s == len(configs) - 1:
+ self.last_package(b, tmproot)
+ builds += [b]
+ if not self.opts.no_clean():
+ for b in builds:
+ _notice(self.opts, 'cleaning: %s' % (b.name()))
+ b.cleanup()
+ for b in builds:
+ del b
+ except:
+ os.environ['PATH'] = current_path
+ raise
+ os.environ['PATH'] = current_path
+
+def run():
+ import sys
+ try:
+ optargs = { '--list-configs': 'List available configurations',
+ '--list-bsets': 'List available build sets'}
+ opts, _defaults = defaults.load(sys.argv, optargs)
+ log.default = log.log(opts.logfiles())
+ _notice(opts, 'Source Builder - Set Builder, v%s' % (version))
+ if not check.host_setup(opts, _defaults):
+ if not opts.force():
+ raise error.general('host build environment is not set up correctly (use --force to proceed)')
+ _notice(opts, 'warning: forcing build with known host setup problems')
+ if opts.get_arg('--list-configs'):
+ build.list_configs(opts, _defaults)
+ elif opts.get_arg('--list-bsets'):
+ build.list_configs(opts, _defaults, ext = '.bset')
+ else:
+ for bset in opts.params():
+ c = buildset(bset, _defaults = _defaults, opts = opts)
+ c.make()
+ del c
+ except error.general, gerr:
+ print gerr
+ sys.exit(1)
+ except error.internal, ierr:
+ print ierr
+ sys.exit(1)
+ except error.exit, eerr:
+ pass
+ except KeyboardInterrupt:
+ _notice(opts, 'user terminated')
+ sys.exit(1)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ run()
diff --git a/source-builder/sb/windows.py b/source-builder/sb/windows.py
new file mode 100644
index 0000000..50f2052
--- /dev/null
+++ b/source-builder/sb/windows.py
@@ -0,0 +1,91 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj@rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# Windows specific support and overrides.
+#
+
+import pprint
+import os
+
+import execute
+
+def load():
+ uname = 'win32'
+ if os.environ.has_key('NUMBER_OF_PROCESSORS'):
+ ncpus = int(os.environ['NUMBER_OF_PROCESSORS'])
+ else:
+ ncpus = 0
+ if ncpus > 1:
+ smp_mflags = '-j' + str(ncpus)
+ else:
+ smp_mflags = ''
+ if os.environ.has_key('HOSTTYPE'):
+ hosttype = os.environ['HOSTTYPE']
+ else:
+ hosttype = 'i686'
+ system = 'mingw32'
+ defines = {
+ '_os': ('none', 'none', 'win32'),
+ '_host': ('triplet', 'required', hosttype + '-pc-' + system),
+ '_host_vendor': ('none', 'none', 'microsoft'),
+ '_host_os': ('none', 'none', 'win32'),
+ '_host_cpu': ('none', 'none', hosttype),
+ '_host_alias': ('none', 'none', '%{nil}'),
+ '_host_arch': ('none', 'none', hosttype),
+ '_usr': ('dir', 'optional', '/opt/local'),
+ '_var': ('dir', 'optional', '/opt/local/var'),
+ '_smp_mflags': ('none', 'none', smp_mflags),
+ '__bash': ('exe', 'required', 'bash'),
+ '__bzip2': ('exe', 'required', 'bzip2'),
+ '__cat': ('exe', 'required', 'cat'),
+ '__cc': ('exe', 'required', 'gcc'),
+ '__chgrp': ('exe', 'required', 'chgrp'),
+ '__chmod': ('exe', 'required', 'chmod'),
+ '__chown': ('exe', 'required', 'chown'),
+ '__cp': ('exe', 'required', 'cp'),
+ '__cxx': ('exe', 'required', 'g++'),
+ '__grep': ('exe', 'required', 'grep'),
+ '__gzip': ('exe', 'required', 'gzip'),
+ '__id': ('exe', 'required', 'id'),
+ '__install': ('exe', 'required', 'install'),
+ '__install_info': ('exe', 'required', 'install-info'),
+ '__ld': ('exe', 'required', 'ld'),
+ '__ldconfig': ('exe', 'none', ''),
+ '__mkdir': ('exe', 'required', 'mkdir'),
+ '__mv': ('exe', 'required', 'mv'),
+ '__nm': ('exe', 'required', 'nm'),
+ '__nm': ('exe', 'required', 'nm'),
+ '__objcopy': ('exe', 'required', 'objcopy'),
+ '__objdump': ('exe', 'required', 'objdump'),
+ '__patch': ('exe', 'required', 'patch'),
+ '__rm': ('exe', 'required', 'rm'),
+ '__sed': ('exe', 'required', 'sed'),
+ '__sh': ('exe', 'required', 'sh'),
+ '__tar': ('exe', 'required', 'bsdtar'),
+ '__unzip': ('exe', 'required', 'unzip'),
+ '__xz': ('exe', 'required', 'xz'),
+ '_buildshell': ('exe', 'required', '%{__sh}'),
+ '___setup_shell': ('exe', 'required', '%{__sh}'),
+ 'optflags': ('none', 'none', '-O2 -pipe'),
+ }
+ return defines
+
+if __name__ == '__main__':
+ pprint.pprint(load())