[PATCH v2] sb: Add support to search for a suitable version of python.

chrisj at rtems.org chrisj at rtems.org
Thu Oct 18 22:48:16 UTC 2018


From: Chris Johns <chrisj at rtems.org>

The command python has been removed from upstream python and python2
and python3 is now used. This patch wraps the commands in a shell
script that locates a suitable python to run.

Updates #3537
---
 source-builder/config/gdb-common-1.cfg | 105 +++++++++++++-
 source-builder/defaults.mc             |   6 +-
 source-builder/pkg-config              | 241 +++------------------------------
 source-builder/sb-bootstrap            |  24 ++--
 source-builder/sb-builder              |  24 ++--
 source-builder/sb-check                |  24 ++--
 source-builder/sb-defaults             |  24 ++--
 source-builder/sb-reports              |  24 ++--
 source-builder/sb-rtems-config         |  24 ++--
 source-builder/sb-set-builder          |  25 ++--
 source-builder/sb/build.py             |   8 ++
 source-builder/sb/cmd-bootstrap.py     |  29 ++++
 source-builder/sb/cmd-builder.py       |  29 ++++
 source-builder/sb/cmd-check.py         |  29 ++++
 source-builder/sb/cmd-defaults.py      |  29 ++++
 source-builder/sb/cmd-pkg-config.py    | 220 ++++++++++++++++++++++++++++++
 source-builder/sb/cmd-reports.py       |  29 ++++
 source-builder/sb/cmd-rtems-config.py  |  29 ++++
 source-builder/sb/cmd-set-builder.py   |  29 ++++
 source-builder/sb/config.py            |  48 ++++---
 source-builder/sb/freebsd.py           |   6 +-
 source-builder/sb/macros.py            |   9 +-
 source-builder/sb/options.py           |   7 +-
 source-builder/sb/path.py              |  11 +-
 source-builder/sb/python-wrapper.sh    |  39 ++++++
 source-builder/sb/rtems-build-dep      | 170 +++++++++++++++++++++++
 source-builder/sb/windows.py           |  46 ++++---
 27 files changed, 917 insertions(+), 371 deletions(-)
 create mode 100755 source-builder/sb/cmd-bootstrap.py
 create mode 100755 source-builder/sb/cmd-builder.py
 create mode 100755 source-builder/sb/cmd-check.py
 create mode 100755 source-builder/sb/cmd-defaults.py
 create mode 100755 source-builder/sb/cmd-pkg-config.py
 create mode 100755 source-builder/sb/cmd-reports.py
 create mode 100755 source-builder/sb/cmd-rtems-config.py
 create mode 100755 source-builder/sb/cmd-set-builder.py
 create mode 100644 source-builder/sb/python-wrapper.sh
 create mode 100755 source-builder/sb/rtems-build-dep

diff --git a/source-builder/config/gdb-common-1.cfg b/source-builder/config/gdb-common-1.cfg
index fe4dbaf..30fdf90 100644
--- a/source-builder/config/gdb-common-1.cfg
+++ b/source-builder/config/gdb-common-1.cfg
@@ -4,6 +4,103 @@
 # This configuration file configure's, make's and install's gdb.
 #
 
+#
+# Python
+#
+# GDB uses python internally so we need to link to a suitable python
+# dev kit. The dev kit for python is the header and a library. These
+# files are versioned where the header file is located in a directory
+# based on:
+#
+#  pythonM.m/Python.h
+#
+# where 'M' is the major version number and 'm' is the minor verison
+# number. The library is:
+#
+#  libpythonM.m.a
+#
+# The python command is 'pythonM' which means we need to query it for
+# the minor number.
+#
+# The python running the RSB may not be suitable, for example a MSC,
+# MSYS or Cygwin version on Windows when we want the MinGW python dev
+# file. A specific version cannot be forced because older versions of
+# GDB can only link to 'python2'.
+#
+# Host support can perform a complex query of the system, for example
+# Windows and set '%{gdb_python2}' and '%{gdb_python3}' with the full
+# path to that version's executable.
+#
+# A configuration of GDB can set the version required by setting
+# '%{gdb-python-version}' to the versions command, eg python2.
+#
+# The procedure is:
+#
+# 1. If the macros '%{gdb_python2}' or '%{gdb_python3}' are present
+#    use that path they contain. Assume the path is valid.
+#
+# 2. Does the version of gdb specify a version of python that must be
+#    used. Override with '%define gdb-python-version python2'.
+#
+# 3. Search for 'python2' and if not found search for 'python3'.
+#
+%if %{defined gdb-python2}
+  %define gdb-enable-python %{gdb_python2}
+%else
+  %if %{defined gdb-python3}
+    %define gdb-enable-python %{gdb_python3}
+  %else
+    %if %{defined gdb-python-version}
+      %define gdb-enable-python %(command -v %{gdb-python-version || true})
+    %else
+      %define gdb-enable-python %(command -v python2 || true)
+      %if %{gdb-enable-python} == %{nil}
+        %define gdb-enable-python %(command -v python3 || true)
+      %endif
+      %if %{gdb-enable-python} == %{nil}
+          %define gdb-enable-python %(command -v python || true})
+      %endif
+    %endif
+    %if %{gdb-enable-python} == %{nil}
+      %error "gdb: python: no valid version of python found"
+    %endif
+  %endif
+%endif
+
+#
+# Get the Python's major and minor version from the python
+# command. The headers and libraries are installed under a major/minor
+# (mm) version path and name.
+#
+# The library file name can vary across the hosts so wildcard the search.
+#
+%define gdb-python-ver-mm %(%{gdb-enable-python} --version 2>&1 | sed -e 's/.* //g' | rev | cut -d'.' -f2- | rev)
+%define gdb-python-ver-header python%{gdb-python-ver-mm}/Python.h
+%define gdb-python-ver-lib libpython%{gdb-python-ver-mm}.*
+%if %{host_includes} == %{nil}
+  %define gdb-host-incs %{nil}
+%else
+  %define gdb-host-incs -I '%{host_includes}'
+%endif
+%define gdb-python-header-check %(%{_sbdir}/sb/rtems-build-dep -c %{__cc} %{gdb-host-incs} -H %{gdb-python-ver-header})
+%if %{gdb-python-header-check} == not-found
+  %error "gdb: python: header file not found: %{gdb-python-ver-header}, please install"
+%endif
+#
+# Too hard to find on MacOS (darwin), the header is good enough.
+#
+%ifnos darwin
+  %if %{host_ldflags} == %{nil}
+    %define gdb-host-libs %{nil}
+  %else
+    %define gdb-host-libs -L '%{host_ldflags}'
+  %endif
+  %define gdb-python-lib-check %(%{_sbdir}/sb/rtems-build-dep -c %{__cc} %{gdb-host-libs} -l %{gdb-python-ver-lib})
+  %if %{gdb-python-lib-check} == not-found
+    %error "gdb: python: library file not found: %{gdb-python-ver-lib}, please install"
+  %endif
+%endif
+
 #
 # See if the simulator has been disabled for Windows.
 #
@@ -41,7 +138,7 @@ Name:      %{_target}-gdb-%{gdb_version}-%{_host}-%{release}
 Summary:   GDB v%{gdb_version} for target %{_target} on host %{_host}
 Version:   %{gdb_version}
 Release:   %{release}
-URL: 	   http://www.gnu.org/software/gdb/
+URL:       http://www.gnu.org/software/gdb/
 BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
 
 #
@@ -70,7 +167,11 @@ BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
 %if %{defined with_python_path}
   %define with_python_option --with-python=%{with_python_path}
 %else
-  %define with_python_option --with-python
+  %if %{defined gdb-enable-python}
+    %define with_python_option --with-python=%{gdb-enable-python}
+  %else
+    %define with_python_option --with-python
+  %endif
 %endif
 
 #
diff --git a/source-builder/defaults.mc b/source-builder/defaults.mc
index 3f9ff9f..aa1a5e6 100644
--- a/source-builder/defaults.mc
+++ b/source-builder/defaults.mc
@@ -65,9 +65,11 @@ _uid:                none,    convert,  '%(%{__id_u} -n)'
 # the tools will run on and build is the host building the tools.
 host_cflags:         none,    convert,  '-O2 -pipe'
 host_cxxflags:       none,    convert,  '-O2 -pipe'
+host_ldflags:        none,    convert,  ''
 host_includes:       none,    convert,  ''
 build_cflags:        none,    convert,  '-O2 -pipe'
 build_cxxflags:      none,    convert,  '-O2 -pipe'
+build_ldflags:       none,    convert,  ''
 build_includes:      none,    convert,  ''
 
 # Extra path a platform can override.
@@ -202,10 +204,10 @@ SB_BUILD_DIR="%{_builddir}"
 SB_HOST_CPPFLAGS="%{host_includes}"
 SB_HOST_CFLAGS="%{host_cflags} %{host_includes}"
 SB_HOST_CXXFLAGS="%{host_cxxflags} %{host_includes}"
-SB_HOST_LDFLAGS="%{?host_ldflags:%{host_ldflags}} %{?_tmproot:-L%{_tmproot}/${SB_PREFIX_CLEAN}/lib}"
+SB_HOST_LDFLAGS="%{host_ldflags} %{?_tmproot:-L%{_tmproot}/${SB_PREFIX_CLEAN}/lib}"
 SB_BUILD_CFLAGS="%{build_cflags} %{?_tmproot:-I%{_tmproot}/${SB_PREFIX_CLEAN}/include}"
 SB_BUILD_CXXFLAGS="%{build_cxxflags} %{?_tmproot:-I%{_tmproot}/${SB_PREFIX_CLEAN}/include}"
-SB_BUILD_LDFLAGS="%{?build_ldflags:%{build_ldflags}} %{?_tmproot:-L%{_tmproot}/${SB_PREFIX_CLEAN}/lib}"
+SB_BUILD_LDFLAGS="%{build_ldflags} %{?_tmproot:-L%{_tmproot}/${SB_PREFIX_CLEAN}/lib}"
 SB_CFLAGS="${SB_BUILD_CFLAGS} %{build_includes}"
 SB_CXXFLAGS="${SB_BUILD_CXXFLAGS} %{build_includes}"
 SB_ARCH="%{_arch}"
diff --git a/source-builder/pkg-config b/source-builder/pkg-config
index fa251e5..65ee307 100755
--- a/source-builder/pkg-config
+++ b/source-builder/pkg-config
@@ -1,226 +1,27 @@
-#! /usr/bin/env python
+#! /bin/sh
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2014-2016 Chris Johns (chrisj at rtems.org)
+# Copyright 2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
 #
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-
-from __future__ import print_function
-
-import os
-import sys
-
-base = os.path.dirname(sys.argv[0])
-sys.path.insert(0, base + '/sb')
-
-try:
-    import argparse
-except:
-    sys.path.insert(0, base + '/sb/imports')
-    try:
-        import argparse
-    except:
-        print("Incorrect Source Builder installation", file = sys.stderr)
-        sys.exit(1)
-
-try:
-    import pkgconfig
-except ImportError:
-    print("Incorrect Source Builder installation", file = sys.stderr)
-    sys.exit(1)
-
-#
-# Make trace true to get a file of what happens and what is being asked.
-#
-trace = True
-trace_stdout = False
-logfile = 'pkg-config.log'
-out = None
-srcfd = None
-
-#
-# Write all the package source parsed to a single file.
-#
-trace_src = True
-if trace_src:
-    srcfd = open('pkg-src.txt', 'w')
-
-def src(text):
-    if srcfd:
-        srcfd.writelines(text)
-
-def log(s, lf = True):
-    global trace, logfile, out
-    if trace:
-        if out is None:
-            if logfile:
-                out = open(logfile, 'a')
-            else:
-                out = sys.stdout
-        if lf:
-            if out != sys.stdout and trace_stdout:
-                print(s)
-            print(s, file = out)
-        else:
-            if out != sys.stdout and trace_stdout:
-                print(s, end = '')
-                sys.stdout.flush()
-            print(s, end = '', file = out)
-
-def run(argv):
-
-    class version_action(argparse.Action):
-        def __call__(self, parser, namespace, values, option_string = None):
-            parts = values[0].strip().split('.')
-            for p in parts:
-                if not p.isdigit():
-                    raise error('invalid version value: %s' % (values))
-            setattr(namespace, self.dest, '.'.join(parts))
-
-    ec = 0
-
-    opts = argparse.ArgumentParser(prog = 'pkg-config', description = 'Package Configuration.')
-    opts.add_argument('libraries', metavar='lib', type = str,  help = 'a library', nargs = '*')
-    opts.add_argument('--modversion', dest = 'modversion', action = 'store', default = None,
-                      help = 'Requests that the version information of the libraries.')
-    opts.add_argument('--print-errors', dest = 'print_errors', action = 'store_true',
-                      default = False,
-                      help = 'Print any errors.')
-    opts.add_argument('--short-errors', dest = 'short_errors', action = 'store_true',
-                      default = False,
-                      help = 'Make error messages short.')
-    opts.add_argument('--silence-errors', dest = 'silence_errors', action = 'store_true',
-                      default = False,
-                      help = 'Do not print any errors.')
-    opts.add_argument('--errors-to-stdout', dest = 'errors_to_stdout', action = 'store_true',
-                      default = False,
-                      help = 'Print errors to stdout rather than stderr.')
-    opts.add_argument('--cflags', dest = 'cflags', action = 'store_true',
-                      default = False,
-                      help = 'This prints pre-processor and compile flags required to' \
-                             ' compile the package(s)')
-    opts.add_argument('--libs', dest = 'libs', action = 'store_true',
-                      default = False,
-                      help = 'This option is identical to "--cflags", only it prints the' \
-                             ' link flags.')
-    opts.add_argument('--libs-only-L', dest = 'libs_only_L', action = 'store_true',
-                      default = False,
-                      help = 'This prints the -L/-R part of "--libs".')
-    opts.add_argument('--libs-only-l', dest = 'libs_only_l', action = 'store_true',
-                      default = False,
-                      help = 'This prints the -l part of "--libs".')
-    opts.add_argument('--variable', dest = 'variable', action = 'store',
-                      nargs = 1, default = None,
-                      help = 'This returns the value of a variable.')
-    opts.add_argument('--define-variable', dest = 'define_variable', action = 'store',
-                      nargs = 1, default = None,
-                      help = 'This sets a global value for a variable')
-    opts.add_argument('--uninstalled', dest = 'uninstalled', action = 'store_true',
-                      default = False,
-                      help = 'Ignored')
-    opts.add_argument('--atleast-pkgconfig-version', dest = 'atleast_pkgconfig_version',
-                      action = 'store', nargs = 1, default = None,
-                      help = 'Check the version of package config. Always ok.')
-    opts.add_argument('--exists', dest = 'exists', action = 'store_true',
-                      default = False,
-                      help = 'Test if a library is present')
-    opts.add_argument('--atleast-version', dest = 'atleast_version',
-                      action = version_action, nargs = 1, default = None,
-                      help = 'The package is at least this version.')
-    opts.add_argument('--exact-version', dest = 'exact_version', action = version_action,
-                       nargs = 1, default = None,
-                        help = 'The package is the exact version.')
-    opts.add_argument('--max-version', dest = 'max_version', action = version_action,
-                      nargs = 1, default = None,
-                      help = 'The package is no later than this version.')
-    opts.add_argument('--msvc-syntax', dest = 'msvc_syntax', action = 'store_true',
-                      default = False,
-                      help = 'Ignored')
-    opts.add_argument('--dont-define-prefix', dest = 'dont_define_prefix', action = 'store_true',
-                      default = False,
-                      help = 'Ignored')
-    opts.add_argument('--prefix-variable', dest = 'prefix', action = 'store',
-                      nargs = 1, default = pkgconfig.default_prefix(),
-                      help = 'Define the prefix.')
-    opts.add_argument('--static', dest = 'static', action = 'store_true',
-                      default = False,
-                      help = 'Output libraries suitable for static linking')
-    opts.add_argument('--dump', dest = 'dump', action = 'store_true',
-                      default = False,
-                      help = 'Dump the package if one is found.')
-
-    args = opts.parse_args(argv[1:])
-
-    if (args.exists and (args.exact_version or args.max_version)) or \
-            (args.exact_version and (args.exists or args.max_version)) or \
-            (args.max_version and (args.exists or args.exact_version)):
-        raise error('only one of --exists, --exact-version, or --max-version')
-
-    if args.dont_define_prefix:
-        args.prefix = pkgconfig.default_prefix(False)
-
-    exists = False
-
-    ec = 1
-
-    if args.atleast_pkgconfig_version:
-        ec = 0
-    else:
-        ec, pkg, flags = pkgconfig.check_package(args.libraries, args, log, src)
-        if ec == 0:
-            if args.cflags:
-                if len(flags['cflags']):
-                    print(flags['cflags'])
-                    log('cflags: %s' % (flags['cflags']))
-                else:
-                    log('cflags: empty')
-            if args.libs:
-                if len(flags['libs']):
-                    print(flags['libs'])
-                    log('libs: %s' % (flags['libs']))
-                else:
-                    log('libs: empty')
-
-    #pkgconfig.package.dump_loaded()
-
-    return ec
-
-try:
-    log('-' * 40)
-    log('pkg-config', lf = False)
-    for a in sys.argv[1:]:
-        log(' "%s"' % (a), lf = False)
-    log('')
-    ec = run(sys.argv)
-    log('ec = %d' % (ec))
-except ImportError:
-    print("incorrect package config installation", file = sys.stderr)
-    sys.exit(1)
-except pkgconfig.error as e:
-    print('error: %s' % (e), file = sys.stderr)
-    sys.exit(1)
-sys.exit(ec)
+# 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.
+#
+set -e
+base=$(dirname $0)
+PYTHON_CMD=${base}/sb/cmd-pkg-config.py
+if test -f ${base}/sb/python-wrapper.sh; then
+  . ${base}/sb/python-wrapper.sh
+fi
+echo "error: python wrapper not found"
diff --git a/source-builder/sb-bootstrap b/source-builder/sb-bootstrap
index a1ee9a7..618e2bb 100755
--- a/source-builder/sb-bootstrap
+++ b/source-builder/sb-bootstrap
@@ -1,7 +1,7 @@
-#! /usr/bin/env python
+#! /bin/sh
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2013 Chris Johns (chrisj at rtems.org)
+# Copyright 2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -17,15 +17,11 @@
 # 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.
-
-from __future__ import print_function
-
-import sys, os
-base = os.path.dirname(sys.argv[0])
-sys.path.insert(0, base + '/sb')
-try:
-    import bootstrap
-    bootstrap.run(sys.argv)
-except ImportError:
-    print("Incorrect Source Builder installation", file = sys.stderr)
-    sys.exit(1)
+#
+set -e
+base=$(dirname $0)
+PYTHON_CMD=${base}/sb/cmd-bootstrap.py
+if test -f ${base}/sb/python-wrapper.sh; then
+  . ${base}/sb/python-wrapper.sh
+fi
+echo "error: python wrapper not found"
diff --git a/source-builder/sb-builder b/source-builder/sb-builder
index 8721b56..be3d205 100755
--- a/source-builder/sb-builder
+++ b/source-builder/sb-builder
@@ -1,7 +1,7 @@
-#! /usr/bin/env python
+#! /bin/sh
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2012 Chris Johns (chrisj at rtems.org)
+# Copyright 2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -17,15 +17,11 @@
 # 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.
-
-from __future__ import print_function
-
-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("Incorrect Source Builder installation", file = sys.stderr)
-    sys.exit(1)
+#
+set -e
+base=$(dirname $0)
+PYTHON_CMD=${base}/sb/cmd-builder.py
+if test -f ${base}/sb/python-wrapper.sh; then
+  . ${base}/sb/python-wrapper.sh
+fi
+echo "error: python wrapper not found"
diff --git a/source-builder/sb-check b/source-builder/sb-check
index d23b799..b092697 100755
--- a/source-builder/sb-check
+++ b/source-builder/sb-check
@@ -1,7 +1,7 @@
-#! /usr/bin/env python
+#! /bin/sh
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2012 Chris Johns (chrisj at rtems.org)
+# Copyright 2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -17,15 +17,11 @@
 # 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.
-
-from __future__ import print_function
-
-import sys, os
-base = os.path.dirname(sys.argv[0])
-sys.path.insert(0, base + '/sb')
-try:
-    import check
-    check.run()
-except ImportError:
-    print("Incorrect Source Builder installation", file = sys.stderr)
-    sys.exit(1)
+#
+set -e
+base=$(dirname $0)
+PYTHON_CMD=${base}/sb/cmd-check.py
+if test -f ${base}/sb/python-wrapper.sh; then
+  . ${base}/sb/python-wrapper.sh
+fi
+echo "error: python wrapper not found"
diff --git a/source-builder/sb-defaults b/source-builder/sb-defaults
index 790a5e5..25437ba 100755
--- a/source-builder/sb-defaults
+++ b/source-builder/sb-defaults
@@ -1,7 +1,7 @@
-#! /usr/bin/env python
+#! /bin/sh
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2013 Chris Johns (chrisj at rtems.org)
+# Copyright 2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -17,15 +17,11 @@
 # 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.
-
-from __future__ import print_function
-
-import sys, os
-base = os.path.dirname(sys.argv[0])
-sys.path.insert(0, base + '/sb')
-try:
-    import options
-    options.run(sys.argv)
-except ImportError:
-    print("Incorrect Source Builder installation", file = sys.stderr)
-    sys.exit(1)
+#
+set -e
+base=$(dirname $0)
+PYTHON_CMD=${base}/sb/cmd-defaults.py
+if test -f ${base}/sb/python-wrapper.sh; then
+  . ${base}/sb/python-wrapper.sh
+fi
+echo "error: python wrapper not found"
diff --git a/source-builder/sb-reports b/source-builder/sb-reports
index 3330be3..5fb02d1 100755
--- a/source-builder/sb-reports
+++ b/source-builder/sb-reports
@@ -1,7 +1,7 @@
-#! /usr/bin/env python
+#! /bin/sh
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2013 Chris Johns (chrisj at rtems.org)
+# Copyright 2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -17,15 +17,11 @@
 # 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.
-
-from __future__ import print_function
-
-import sys, os
-base = os.path.dirname(sys.argv[0])
-sys.path.insert(0, base + '/sb')
-try:
-    import reports
-    reports.run(sys.argv)
-except ImportError:
-    print("Incorrect Source Builder installation", file = sys.stderr)
-    sys.exit(1)
+#
+set -e
+base=$(dirname $0)
+PYTHON_CMD=${base}/sb/cmd-reports.py
+if test -f ${base}/sb/python-wrapper.sh; then
+  . ${base}/sb/python-wrapper.sh
+fi
+echo "error: python wrapper not found"
diff --git a/source-builder/sb-rtems-config b/source-builder/sb-rtems-config
index 1633b6b..66a95f7 100755
--- a/source-builder/sb-rtems-config
+++ b/source-builder/sb-rtems-config
@@ -1,7 +1,7 @@
-#! /usr/bin/env python
+#! /bin/sh
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2012 Chris Johns (chrisj at rtems.org)
+# Copyright 2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -17,15 +17,11 @@
 # 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.
-
-from __future__ import print_function
-
-import sys, os
-base = os.path.dirname(sys.argv[0])
-sys.path.insert(0, base + '/sb')
-try:
-    import rtemsconfig
-    rtemsconfig.run(sys.argv)
-except ImportError:
-    print("Incorrect Source Builder installation", file = sys.stderr)
-    sys.exit(1)
+#
+set -e
+base=$(dirname $0)
+PYTHON_CMD=${base}/sb/cmd-rtems-config.py
+if test -f ${base}/sb/python-wrapper.sh; then
+  . ${base}/sb/python-wrapper.sh
+fi
+echo "error: python wrapper not found"
diff --git a/source-builder/sb-set-builder b/source-builder/sb-set-builder
index 561199e..6a196fe 100755
--- a/source-builder/sb-set-builder
+++ b/source-builder/sb-set-builder
@@ -1,7 +1,7 @@
-#! /usr/bin/env python
+#! /bin/sh
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2012 Chris Johns (chrisj at rtems.org)
+# Copyright 2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -17,16 +17,11 @@
 # 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.
-
-from __future__ import print_function
-
-import sys, os
-base = os.path.dirname(sys.argv[0])
-sys.path.insert(0, base + '/sb')
-
-try:
-    import setbuilder
-    setbuilder.run()
-except ImportError:
-    print("Incorrect Source Builder installation", file = sys.stderr)
-    sys.exit(1)
+#
+set -e
+base=$(dirname $0)
+PYTHON_CMD=${base}/sb/cmd-set-builder.py
+if test -f ${base}/sb/python-wrapper.sh; then
+  . ${base}/sb/python-wrapper.sh
+fi
+echo "error: python wrapper not found"
diff --git a/source-builder/sb/build.py b/source-builder/sb/build.py
index 88446bb..a17bfe2 100644
--- a/source-builder/sb/build.py
+++ b/source-builder/sb/build.py
@@ -69,7 +69,15 @@ class script:
         self.lc = 0
 
     def append(self, text):
+        is_str = False
         if type(text) is str:
+            is_str = True
+        try:
+            if type(text) is unicode:
+                is_str = True
+        except:
+            pass
+        if is_str:
             text = text.splitlines()
         if not log.quiet:
             i = 0
diff --git a/source-builder/sb/cmd-bootstrap.py b/source-builder/sb/cmd-bootstrap.py
new file mode 100755
index 0000000..0243237
--- /dev/null
+++ b/source-builder/sb/cmd-bootstrap.py
@@ -0,0 +1,29 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2013 Chris Johns (chrisj at 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.
+
+from __future__ import print_function
+
+import sys, os
+
+try:
+    import bootstrap
+    bootstrap.run(sys.argv)
+except ImportError:
+    print("Incorrect Source Builder installation", file = sys.stderr)
+    sys.exit(1)
diff --git a/source-builder/sb/cmd-builder.py b/source-builder/sb/cmd-builder.py
new file mode 100755
index 0000000..437b81a
--- /dev/null
+++ b/source-builder/sb/cmd-builder.py
@@ -0,0 +1,29 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj at 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.
+
+from __future__ import print_function
+
+import sys, os
+
+try:
+    import build
+    build.run(sys.argv)
+except ImportError:
+    print("Incorrect Source Builder installation", file = sys.stderr)
+    sys.exit(1)
diff --git a/source-builder/sb/cmd-check.py b/source-builder/sb/cmd-check.py
new file mode 100755
index 0000000..4525dbb
--- /dev/null
+++ b/source-builder/sb/cmd-check.py
@@ -0,0 +1,29 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj at 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.
+
+from __future__ import print_function
+
+import sys, os
+
+try:
+    import check
+    check.run()
+except ImportError:
+    print("Incorrect Source Builder installation", file = sys.stderr)
+    sys.exit(1)
diff --git a/source-builder/sb/cmd-defaults.py b/source-builder/sb/cmd-defaults.py
new file mode 100755
index 0000000..0b2b357
--- /dev/null
+++ b/source-builder/sb/cmd-defaults.py
@@ -0,0 +1,29 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2013 Chris Johns (chrisj at 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.
+
+from __future__ import print_function
+
+import sys, os
+
+try:
+    import options
+    options.run(sys.argv)
+except ImportError:
+    print("Incorrect Source Builder installation", file = sys.stderr)
+    sys.exit(1)
diff --git a/source-builder/sb/cmd-pkg-config.py b/source-builder/sb/cmd-pkg-config.py
new file mode 100755
index 0000000..c2f485c
--- /dev/null
+++ b/source-builder/sb/cmd-pkg-config.py
@@ -0,0 +1,220 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2014-2016 Chris Johns (chrisj at rtems.org)
+# All rights reserved.
+#
+# This file is part of the RTEMS Tools package in 'rtems-tools'.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+from __future__ import print_function
+
+import os
+import sys
+
+base = os.path.dirname(sys.argv[0])
+
+try:
+    import argparse
+except:
+    sys.path.insert(0, base + '/sb/imports')
+    try:
+        import argparse
+    except:
+        print("Incorrect Source Builder installation", file = sys.stderr)
+        sys.exit(1)
+
+import pkgconfig
+
+#
+# Make trace true to get a file of what happens and what is being asked.
+#
+trace = True
+trace_stdout = False
+logfile = 'pkg-config.log'
+out = None
+srcfd = None
+
+#
+# Write all the package source parsed to a single file.
+#
+trace_src = True
+if trace_src:
+    srcfd = open('pkg-src.txt', 'w')
+
+def src(text):
+    if srcfd:
+        srcfd.writelines(text)
+
+def log(s, lf = True):
+    global trace, logfile, out
+    if trace:
+        if out is None:
+            if logfile:
+                out = open(logfile, 'a')
+            else:
+                out = sys.stdout
+        if lf:
+            if out != sys.stdout and trace_stdout:
+                print(s)
+            print(s, file = out)
+        else:
+            if out != sys.stdout and trace_stdout:
+                print(s, end = '')
+                sys.stdout.flush()
+            print(s, end = '', file = out)
+
+def run(argv):
+
+    class version_action(argparse.Action):
+        def __call__(self, parser, namespace, values, option_string = None):
+            parts = values[0].strip().split('.')
+            for p in parts:
+                if not p.isdigit():
+                    raise error('invalid version value: %s' % (values))
+            setattr(namespace, self.dest, '.'.join(parts))
+
+    ec = 0
+
+    opts = argparse.ArgumentParser(prog = 'pkg-config', description = 'Package Configuration.')
+    opts.add_argument('libraries', metavar='lib', type = str,  help = 'a library', nargs = '*')
+    opts.add_argument('--modversion', dest = 'modversion', action = 'store', default = None,
+                      help = 'Requests that the version information of the libraries.')
+    opts.add_argument('--print-errors', dest = 'print_errors', action = 'store_true',
+                      default = False,
+                      help = 'Print any errors.')
+    opts.add_argument('--short-errors', dest = 'short_errors', action = 'store_true',
+                      default = False,
+                      help = 'Make error messages short.')
+    opts.add_argument('--silence-errors', dest = 'silence_errors', action = 'store_true',
+                      default = False,
+                      help = 'Do not print any errors.')
+    opts.add_argument('--errors-to-stdout', dest = 'errors_to_stdout', action = 'store_true',
+                      default = False,
+                      help = 'Print errors to stdout rather than stderr.')
+    opts.add_argument('--cflags', dest = 'cflags', action = 'store_true',
+                      default = False,
+                      help = 'This prints pre-processor and compile flags required to' \
+                             ' compile the package(s)')
+    opts.add_argument('--libs', dest = 'libs', action = 'store_true',
+                      default = False,
+                      help = 'This option is identical to "--cflags", only it prints the' \
+                             ' link flags.')
+    opts.add_argument('--libs-only-L', dest = 'libs_only_L', action = 'store_true',
+                      default = False,
+                      help = 'This prints the -L/-R part of "--libs".')
+    opts.add_argument('--libs-only-l', dest = 'libs_only_l', action = 'store_true',
+                      default = False,
+                      help = 'This prints the -l part of "--libs".')
+    opts.add_argument('--variable', dest = 'variable', action = 'store',
+                      nargs = 1, default = None,
+                      help = 'This returns the value of a variable.')
+    opts.add_argument('--define-variable', dest = 'define_variable', action = 'store',
+                      nargs = 1, default = None,
+                      help = 'This sets a global value for a variable')
+    opts.add_argument('--uninstalled', dest = 'uninstalled', action = 'store_true',
+                      default = False,
+                      help = 'Ignored')
+    opts.add_argument('--atleast-pkgconfig-version', dest = 'atleast_pkgconfig_version',
+                      action = 'store', nargs = 1, default = None,
+                      help = 'Check the version of package config. Always ok.')
+    opts.add_argument('--exists', dest = 'exists', action = 'store_true',
+                      default = False,
+                      help = 'Test if a library is present')
+    opts.add_argument('--atleast-version', dest = 'atleast_version',
+                      action = version_action, nargs = 1, default = None,
+                      help = 'The package is at least this version.')
+    opts.add_argument('--exact-version', dest = 'exact_version', action = version_action,
+                       nargs = 1, default = None,
+                        help = 'The package is the exact version.')
+    opts.add_argument('--max-version', dest = 'max_version', action = version_action,
+                      nargs = 1, default = None,
+                      help = 'The package is no later than this version.')
+    opts.add_argument('--msvc-syntax', dest = 'msvc_syntax', action = 'store_true',
+                      default = False,
+                      help = 'Ignored')
+    opts.add_argument('--dont-define-prefix', dest = 'dont_define_prefix', action = 'store_true',
+                      default = False,
+                      help = 'Ignored')
+    opts.add_argument('--prefix-variable', dest = 'prefix', action = 'store',
+                      nargs = 1, default = pkgconfig.default_prefix(),
+                      help = 'Define the prefix.')
+    opts.add_argument('--static', dest = 'static', action = 'store_true',
+                      default = False,
+                      help = 'Output libraries suitable for static linking')
+    opts.add_argument('--dump', dest = 'dump', action = 'store_true',
+                      default = False,
+                      help = 'Dump the package if one is found.')
+
+    args = opts.parse_args(argv[1:])
+
+    if (args.exists and (args.exact_version or args.max_version)) or \
+            (args.exact_version and (args.exists or args.max_version)) or \
+            (args.max_version and (args.exists or args.exact_version)):
+        raise error('only one of --exists, --exact-version, or --max-version')
+
+    if args.dont_define_prefix:
+        args.prefix = pkgconfig.default_prefix(False)
+
+    exists = False
+
+    ec = 1
+
+    if args.atleast_pkgconfig_version:
+        ec = 0
+    else:
+        ec, pkg, flags = pkgconfig.check_package(args.libraries, args, log, src)
+        if ec == 0:
+            if args.cflags:
+                if len(flags['cflags']):
+                    print(flags['cflags'])
+                    log('cflags: %s' % (flags['cflags']))
+                else:
+                    log('cflags: empty')
+            if args.libs:
+                if len(flags['libs']):
+                    print(flags['libs'])
+                    log('libs: %s' % (flags['libs']))
+                else:
+                    log('libs: empty')
+
+    #pkgconfig.package.dump_loaded()
+
+    return ec
+
+try:
+    log('-' * 40)
+    log('pkg-config', lf = False)
+    for a in sys.argv[1:]:
+        log(' "%s"' % (a), lf = False)
+    log('')
+    ec = run(sys.argv)
+    log('ec = %d' % (ec))
+except ImportError:
+    print("incorrect package config installation", file = sys.stderr)
+    sys.exit(1)
+except pkgconfig.error as e:
+    print('error: %s' % (e), file = sys.stderr)
+    sys.exit(1)
+sys.exit(ec)
diff --git a/source-builder/sb/cmd-reports.py b/source-builder/sb/cmd-reports.py
new file mode 100755
index 0000000..4c41e33
--- /dev/null
+++ b/source-builder/sb/cmd-reports.py
@@ -0,0 +1,29 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2013 Chris Johns (chrisj at 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.
+
+from __future__ import print_function
+
+import sys, os
+
+try:
+    import reports
+    reports.run(sys.argv)
+except ImportError:
+    print("Incorrect Source Builder installation", file = sys.stderr)
+    sys.exit(1)
diff --git a/source-builder/sb/cmd-rtems-config.py b/source-builder/sb/cmd-rtems-config.py
new file mode 100755
index 0000000..f29ef04
--- /dev/null
+++ b/source-builder/sb/cmd-rtems-config.py
@@ -0,0 +1,29 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj at 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.
+
+from __future__ import print_function
+
+import sys, os
+
+try:
+    import rtemsconfig
+    rtemsconfig.run(sys.argv)
+except ImportError:
+    print("Incorrect Source Builder installation", file = sys.stderr)
+    sys.exit(1)
diff --git a/source-builder/sb/cmd-set-builder.py b/source-builder/sb/cmd-set-builder.py
new file mode 100755
index 0000000..56114cd
--- /dev/null
+++ b/source-builder/sb/cmd-set-builder.py
@@ -0,0 +1,29 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2010-2012 Chris Johns (chrisj at 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.
+
+from __future__ import print_function
+
+import sys, os
+
+try:
+    import setbuilder
+    setbuilder.run()
+except ImportError:
+    print("Incorrect Source Builder installation", file = sys.stderr)
+    sys.exit(1)
diff --git a/source-builder/sb/config.py b/source-builder/sb/config.py
index a901038..b7bf403 100644
--- a/source-builder/sb/config.py
+++ b/source-builder/sb/config.py
@@ -557,7 +557,7 @@ class file:
                 elif m.startswith('%{expand'):
                     colon = m.find(':')
                     if colon < 8:
-                        log.warning('malformed expand macro, no colon found')
+                        log.warning(self._name_line_msg('malformed expand macro, no colon found'))
                     else:
                         e = self._expand(m[colon + 1:-1].strip())
                         s = s.replace(m, self._label(e))
@@ -576,7 +576,7 @@ class file:
                     mn = None
                 elif m.startswith('%{echo'):
                     if not m.endswith('}'):
-                        log.warning("malformed conditional macro '%s'" % (m))
+                        log.warning(self._name_line_msg("malformed conditional macro '%s'" % (m)))
                         mn = None
                     else:
                         e = self._expand(m[6:-1].strip())
@@ -648,7 +648,7 @@ class file:
                     colon = m[start:].find(':')
                     if colon < 0:
                         if not m.endswith('}'):
-                            log.warning("malformed conditional macro '%s'" % (m))
+                            log.warning(self._name_line_msg("malformed conditional macro '%s'" % (m)))
                             mn = None
                         else:
                             mn = self._label(m[start:-1])
@@ -690,18 +690,18 @@ class file:
 
     def _disable(self, config, ls):
         if len(ls) != 2:
-            log.warning('invalid disable statement')
+            log.warning(self._name_line_msg('invalid disable statement'))
         else:
             if ls[1] == 'select':
                 self.macros.lock_read_map()
                 log.trace('config: %s: %3d: _disable_select: %s' % (self.name, self.lc,
                                                                      ls[1]))
             else:
-                log.warning('invalid disable statement: %s' % (ls[1]))
+                log.warning(self._name_line_msg('invalid disable statement: %s' % (ls[1])))
 
     def _select(self, config, ls):
         if len(ls) != 2:
-            log.warning('invalid select statement')
+            log.warning(self._name_line_msg('invalid select statement'))
         else:
             r = self.macros.set_read_map(ls[1])
             log.trace('config: %s: %3d: _select: %s %s %r' % \
@@ -716,7 +716,7 @@ class file:
 
     def _define(self, config, ls):
         if len(ls) <= 1:
-            log.warning('invalid macro definition')
+            log.warning(self._name_line_msg('invalid macro definition'))
         else:
             d = self._label(ls[1])
             if self.disable_macro_reassign:
@@ -727,7 +727,7 @@ class file:
                     else:
                         self.macros[d] = ' '.join([f.strip() for f in ls[2:]])
                 else:
-                    log.warning("macro '%s' already defined" % (d))
+                    log.warning(self._name_line_msg("macro '%s' already defined" % (d)))
             else:
                 if len(ls) == 2:
                     self.macros[d] = '1'
@@ -736,7 +736,7 @@ class file:
 
     def _undefine(self, config, ls):
         if len(ls) <= 1:
-            log.warning('invalid macro definition')
+            log.warning(self._name_line_msg('invalid macro definition'))
         else:
             mn = self._label(ls[1])
             if mn in self.macros:
@@ -841,7 +841,7 @@ class file:
                     i = andi
                 log.trace('config: %s: %3d: _if[%i]: next OP found at %i' % (self.name, self.lc,
                                                                              self.if_depth,
-                i))
+                                                                             i))
             ls = cls[:i]
             if len(ls) == 0:
                 self._error('invalid if expression: ' + reduce(add, sls, ''))
@@ -965,6 +965,16 @@ class file:
                     break
         return self._ifs(config, ls, '%ifos', isos, isvalid, dir, info)
 
+    def _ifnos(self, config, ls, isvalid, dir, info):
+        isnos = True
+        if isvalid:
+            os = self.define('_os')
+            for l in ls:
+                if l in os:
+                    isnos = False
+                    break
+        return self._ifs(config, ls, '%ifnos', isnos, isvalid, dir, info)
+
     def _ifarch(self, config, positive, ls, isvalid, dir, info):
         isarch = False
         if isvalid:
@@ -1063,6 +1073,10 @@ class file:
                     d = self._ifos(config, ls, isvalid, dir, info)
                     if len(d):
                         return ('data', d)
+                elif ls[0] == '%ifnos':
+                    d = self._ifnos(config, ls, isvalid, dir, info)
+                    if len(d):
+                        return ('data', d)
                 elif ls[0] == '%ifarch':
                     d = self._ifarch(config, True, ls, isvalid, dir, info)
                     if len(d):
@@ -1074,11 +1088,11 @@ class file:
                 elif ls[0] == '%endif':
                     if roc:
                         return ('control', '%endif', '%endif')
-                    log.warning("unexpected '" + ls[0] + "'")
+                    log.warning(self._name_line_msg("unexpected '" + ls[0] + "'"))
                 elif ls[0] == '%else':
                     if roc:
                         return ('control', '%else', '%else')
-                    log.warning("unexpected '" + ls[0] + "'")
+                    log.warning(self._name_line_msg("unexpected '" + ls[0] + "'"))
                 elif ls[0].startswith('%defattr'):
                     return ('data', [l])
                 elif ls[0] == '%bcond_with':
@@ -1103,7 +1117,7 @@ class file:
                                 log.trace('config: %s: %0d: _parse: directive: %s' % \
                                           (self.name, self.lc, ls[0].strip()))
                                 return ('directive', ls[0].strip(), ls[1:])
-                        log.warning("unknown directive: '" + ls[0] + "'")
+                        log.warning(self._name_line_msg("unknown directive: '" + ls[0] + "'"))
                         return ('data', [lo])
             else:
                 return ('data', [lo])
@@ -1124,7 +1138,7 @@ class file:
                 _package = results[2][0]
             else:
                 if results[2][0].strip() != '-n':
-                    log.warning("unknown directive option: '%s'" % (' '.join(results[2])))
+                    log.warning(self._name_line_msg("unknown directive option: '%s'" % (' '.join(results[2]))))
                 _package = results[2][1].strip()
             self._set_package(_package)
         if directive and directive != results[1]:
@@ -1146,7 +1160,7 @@ class file:
                 log.output(l[4:])
             elif l.startswith('%warning'):
                 l = self._expand(l)
-                log.warning(l[9:])
+                log.warning(self._name_line_msg(l[9:]))
             if not directive:
                 l = self._expand(l)
                 ls = self.tags.split(l, 1)
@@ -1161,7 +1175,7 @@ class file:
                 if info is not None:
                     self._info_append(info, info_data)
                 else:
-                    log.warning("invalid format: '%s'" % (info_data[:-1]))
+                    log.warning(self._name_line_msg("invalid format: '%s'" % (info_data[:-1])))
             else:
                 l = self._expand(l)
                 log.trace('config: %s: %3d: _data: %s %s' % (self.name, self.lc, l, new_data))
@@ -1275,7 +1289,7 @@ class file:
                 elif r[0] == 'control':
                     if r[1] == '%end':
                         break
-                    log.warning("unexpected '%s'" % (r[1]))
+                    log.warning(self._name_line_msg("unexpected '%s'" % (r[1])))
                 elif r[0] == 'directive':
                     if r[1] == '%include':
                         self.load(r[2][0])
diff --git a/source-builder/sb/freebsd.py b/source-builder/sb/freebsd.py
index 2c519a1..e207d00 100644
--- a/source-builder/sb/freebsd.py
+++ b/source-builder/sb/freebsd.py
@@ -57,6 +57,8 @@ def load():
         '_host_cpu':        ('none',    'none',     cpu),
         '_host_alias':      ('none',    'none',     '%{nil}'),
         '_host_arch':       ('none',    'none',     cpu),
+        'host_includes':    ('none',    'convert',  '-I%{_usr}/include'),
+        'host_ldflags':     ('none',    'convert',  '-L%{_usr}/lib'),
         '_usr':             ('dir',     'required', '/usr/local'),
         '_var':             ('dir',     'optional', '/usr/local/var'),
         '__bash':           ('exe',     'optional', '/usr/local/bin/bash'),
@@ -67,7 +69,7 @@ def load():
         '__xz':             ('exe',     'optional', '/usr/bin/xz'),
         '__make':           ('exe',     'required', 'gmake'),
         '__patch_opts':     ('none',     'none',    '-E')
-        }
+    }
 
     defines['_build']        = defines['_host']
     defines['_build_vendor'] = defines['_host_vendor']
@@ -110,7 +112,7 @@ def load():
         #
         # Fix the mess iconv is on FreeBSD 10.0.
         #
-        defines['iconv_includes'] = ('none', 'none', '-I/usr/local/include -L/usr/local/lib')
+        defines['iconv_includes'] = ('none', 'none', '%{_host_includes} %{_host_ldflags}')
 
         #
         # On 11.0+ makeinfo and install-info have moved to /usr/local/...
diff --git a/source-builder/sb/macros.py b/source-builder/sb/macros.py
index cf25783..2abe386 100644
--- a/source-builder/sb/macros.py
+++ b/source-builder/sb/macros.py
@@ -53,7 +53,8 @@ class macros:
         def iterkeys(self):
             return self.keys
 
-    def _unicode_to_str(self, us):
+    @staticmethod
+    def _unicode_to_str(us):
         try:
             if type(us) == unicode:
                 return us.encode('ascii', 'replace')
@@ -174,14 +175,14 @@ class macros:
                             'override', 'undefine', 'convert']:
             raise TypeError('bad value tuple (attrib field): %s' % (value[1]))
         if value[1] == 'convert':
-            value = self.expand(value)
+            value = (value[0], value[1], self.expand(value[2]))
         self.macros[self.write_map][self.key_filter(key)] = value
 
     def __delitem__(self, key):
         self.undefine(key)
 
     def __contains__(self, key):
-        return self.has_key(key)
+        return self.has_key(self._unicode_to_str(key))
 
     def __len__(self):
         return len(list(self.keys()))
@@ -201,6 +202,7 @@ class macros:
         return sorted(set(keys))
 
     def has_key(self, key):
+        key = self._unicode_to_str(key)
         if type(key) is not str:
             raise TypeError('bad key type (want str): %s' % (type(key)))
         if self.key_filter(key) not in list(self.keys()):
@@ -452,6 +454,7 @@ class macros:
 
     def expand(self, _str):
         """Simple basic expander of config file macros."""
+        _str = self._unicode_to_str(_str)
         expanded = True
         while expanded:
             expanded = False
diff --git a/source-builder/sb/options.py b/source-builder/sb/options.py
index 7312285..c5fcabe 100644
--- a/source-builder/sb/options.py
+++ b/source-builder/sb/options.py
@@ -601,10 +601,15 @@ def load(args, optargs = None, defaults = '%{_sbdir}/defaults.mc', logfile = Tru
     global host_windows
     global host_posix
 
+    #
+    # Adjust the args to remove the wrapper.
+    #
+    args = args[1:]
+
     #
     # The path to this command.
     #
-    command_path = path.dirname(args[0])
+    command_path = path.dirname(path.abspath(args[0]))
     if len(command_path) == 0:
         command_path = '.'
 
diff --git a/source-builder/sb/path.py b/source-builder/sb/path.py
index 984f3d7..93852c8 100644
--- a/source-builder/sb/path.py
+++ b/source-builder/sb/path.py
@@ -30,10 +30,13 @@ import os
 import shutil
 import stat
 import string
+import sys
 
 import error
 
+windows_posix = sys.platform == 'msys'
 windows = os.name == 'nt'
+
 win_maxpath = 254
 
 def host(path):
@@ -54,13 +57,15 @@ def host(path):
     return path
 
 def shell(path):
+    if isinstance(path, bytes):
+        path = path.decode('ascii')
     if path is not None:
-        if windows:
-            path = path.encode('ascii', 'ignore')
+        if windows or windows_posix:
+            path = path.encode('ascii', 'ignore').decode('ascii')
             if path.startswith('\\\\?\\'):
                 path = path[4:]
             if len(path) > 1 and path[1] == ':':
-                path = '/%s%s' % (path[0], path[2:])
+                path = '/%s%s' % (path[0].lower(), path[2:])
             path = path.replace('\\', '/')
         while '//' in path:
             path = path.replace('//', '/')
diff --git a/source-builder/sb/python-wrapper.sh b/source-builder/sb/python-wrapper.sh
new file mode 100644
index 0000000..c1b62d2
--- /dev/null
+++ b/source-builder/sb/python-wrapper.sh
@@ -0,0 +1,39 @@
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2018 Chris Johns (chrisj at 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.
+set -e
+if test ! -f $PYTHON_CMD; then
+  echo "error: python command not found: $PYTHON_CMD"
+  exit 5
+fi
+for py in python2 python3 python
+do
+  set +e
+  py_cmd=$(command -v $py)
+  set -e
+  if test -n "$RTEMS_PYTHON_OVERRIDE"; then
+    if test "$RTEMS_PYTHON_OVERRIDE" != "$py"; then
+      py_cmd=""
+    fi
+  fi
+  if test -n "$py_cmd"; then
+    exec $py_cmd $PYTHON_CMD $0 $*
+  fi
+done
+echo "error: no valid python found"
+exit 5
diff --git a/source-builder/sb/rtems-build-dep b/source-builder/sb/rtems-build-dep
new file mode 100755
index 0000000..94bb566
--- /dev/null
+++ b/source-builder/sb/rtems-build-dep
@@ -0,0 +1,170 @@
+#! /bin/sh
+#
+# RTEMS Tools Project (http://www.rtems.org/)
+# Copyright 2018 Chris Johns (chrisj at 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.
+
+#
+# Host Build Dependence
+#
+# This script finds a file that is part of the compiler's default
+# build environment. The file can be header or a library.
+#
+# Header files:
+#  - Get the list of include directories from the compiler.
+#  - Search the include paths for the header file.
+#
+# Library:
+#  - Ask the compiler to print the library paths, add on any user
+#    paths and search with a wilecard.
+#
+
+set -e
+
+op=
+name=
+includes=
+libraries=
+compile=
+verbose=no
+debug=no
+
+if [ $# == 0 ]
+then
+    echo 'Usage: rtems-build-dep [-c compiler] [-H header] [-I header-paths]
+                       [-l library] [-L library-paths] [-v] [-d]'
+    exit 2
+fi
+while [ $# > 0 ]
+do
+    case "$1"
+    in
+	-c)
+	    if [ $# == 1 ]; then
+		echo 'error: no compiler (-c) provided'
+		exit 2
+	    fi
+	    compiler="$2"; shift;
+            shift;;
+	-H)
+	    if [ $# == 1 ]; then
+		echo 'error: no header (-H) provided'
+		exit 2
+	    fi
+	    op="header"
+            name="$2"; shift;
+            shift;;
+	-I)
+	    if [ $# == 1 ]; then
+		echo 'error: no header path (-I) provided'
+		exit 2
+	    fi
+            includes="$2"; shift;
+            shift;;
+	-l)
+	    if [ $# == 1 ]; then
+		echo 'error: no library (-l) provided'
+		exit 2
+	    fi
+	    op="library"
+            name="$2"; shift;
+            shift;;
+	-L)
+	    if [ $# == 1 ]; then
+		echo 'error: no library path (-L) provided'
+		exit 2
+	    fi
+            libraries="$2"; shift;
+            shift;;
+	-v)
+	    verbose=yes
+            shift;;
+	-d)
+	    debug=yes
+            shift;;
+	*)
+	    break;
+    esac
+done
+
+if [ ${debug} = yes ]; then
+    set -x
+fi
+
+if [ -z "${op}" ]; then
+    echo "error: no header or library file to find found."
+    exit 2
+fi
+if [ -z "${compiler}" ]; then
+    echo "error: no compiler provided."
+    exit 2
+fi
+if [ -z "${name}" ]; then
+    echo "error: no name found."
+    exit 2
+fi
+
+#
+# Header file.
+#
+if [ ${op} = "header" ]; then
+    inc_paths=$(echo | ${compiler} ${includes} -xc -E -v - 2>&1 | \
+	       awk 'BEGIN {flag=0;} /starts here/{flag=1;next}/End/{flag=0}flag')
+    for p in ${inc_paths}
+    do
+	if [ ${verbose} = yes ]; then
+	    echo "Include: ${p}"
+	fi
+	if [ -f "${p}/${name}" ]; then
+	    echo "found"
+	    exit 0
+	fi
+    done
+    echo "not-found"
+    exit 0
+fi
+
+#
+# Library file
+#
+if [ ${op} = "library" ]; then
+    if [ "${OS}" = "Windows_NT" ]; then
+	sep=';'
+    else
+	sep=':'
+    fi
+    lib_paths_1=$(${compiler} -print-search-dirs 2>&1 | \
+		      grep libraries | \
+		      sed -e 's/libraries:.*=//' | \
+		      awk 'BEGIN {FS="'${sep}'"} {for (i=0;++i<=NF;) print $i;}')
+    lib_paths_2=$(echo ${libraries} | \
+		      awk 'BEGIN {FS="-L"} {for (i=0;++i<=NF;) if (length($i) > 0) print $i;}')
+    for p in ${lib_paths_1} ${lib_paths_2}
+    do
+	if [ ${verbose} = yes ]; then
+	    echo "Library: ${p}/${name}"
+	fi
+	if ls ${p}/${name} 1> /dev/null 2>&1; then
+	    echo "found"
+	    exit 0
+	fi
+    done
+    echo "not-found"
+    exit 0
+fi
+
+exit 1
diff --git a/source-builder/sb/windows.py b/source-builder/sb/windows.py
index f4eb85c..0eabf9c 100644
--- a/source-builder/sb/windows.py
+++ b/source-builder/sb/windows.py
@@ -1,6 +1,6 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2013 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
@@ -21,12 +21,12 @@
 # Windows specific support and overrides.
 #
 
-import error
-import pprint
 import os
 import sys
 
+import error
 import execute
+import path
 
 def load():
     # Default to the native Windows Python.
@@ -146,13 +146,19 @@ def load():
     #  6. W64/Python2 - Ok if machsize is 32
     #  7. W64/Python3 - gdb-7.9 needs python2.
     #
-    if sys.platform == 'win32' and 'MSC' in sys.version:
-        raise error.general('python.org Pythons are built with MSC and cannot be linked with GDB')
-
+    # Find a suitable python2 and python3.
+    #
+    for p in os.environ['PATH'].split(os.pathsep):
+        sh = os.path.join(p, 'sh.exe')
+        if os.path.exists(sh) and os.path.isfile(sh):
+            break
+        sh = None
+    if sh is None:
+        raise error.general('cannot find a shell (sh.exe) in the PATH')
     #
     # Search the MSYS2 install tree for a suitable python.
     #
-    if sys.platform == 'msys':
+    if sys.platform == 'msys' or True:
         e = execute.capture_execution()
         exit_code, proc, output = e.shell("sh -c mount")
         if exit_code != 0:
@@ -166,23 +172,19 @@ def load():
             raise error.general('cannot locate MSYS root mount point')
         if install_point[1] != ':':
             raise error.general('invalid MSYS root mount point: %s' % install_point)
-        install_point = '/%s%s' % (install_point[0], install_point[2:])
-        bin = '/mingw%s/bin' % (machsize)
-        bin_list = os.listdir(bin)
-        exe = None
-        for python in ['python2.exe']:
-            for f in bin_list:
-                if f == python:
-                    exe = install_point + os.path.join(bin, f)
-                    break;
-            if exe is not None:
-                break
-        if exe is None:
-            raise error.general('no valid python found; you need a mingw%s python2 installed' % (machsize))
-        defines['with_python_path'] = exe
-
+        install_point = path.shell(install_point)
+        mingw = path.join(install_point, 'mingw%s' % (machsize))
+        if not path.exists(mingw) or not path.isdir(mingw):
+            raise error.general('cannot find MinGW install: %s' % (path.host(mingw)))
+        for version in ['2', '3']:
+            python = 'python%s' % (version)
+            exe = path.join(mingw, 'bin', '%s.exe' % (python))
+            if not path.exists(exe) or not path.isdir(exe):
+                defines['gdb_python%s' % (version)] = exe
+                header = path.join(mingw, python)
 
     return defines
 
 if __name__ == '__main__':
+    import pprint
     pprint.pprint(load())
-- 
2.15.1




More information about the devel mailing list