Module Name: src
Committed By: apb
Date: Fri Sep 9 18:48:34 UTC 2011
Modified Files:
src: BUILDING build.sh
src/doc: BUILDING.mdoc
Log Message:
Add tests for the shell under which build.sh is run. If the
shell fails the tests, then build.sh tries to re-exec itself
under a more suitable shell.
To generate a diff of this commit:
cvs rdiff -u -r1.95 -r1.96 src/BUILDING
cvs rdiff -u -r1.248 -r1.249 src/build.sh
cvs rdiff -u -r1.84 -r1.85 src/doc/BUILDING.mdoc
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/BUILDING
diff -u src/BUILDING:1.95 src/BUILDING:1.96
--- src/BUILDING:1.95 Fri Sep 9 14:01:28 2011
+++ src/BUILDING Fri Sep 9 18:48:34 2011
@@ -82,17 +82,23 @@
Environment variables
Several environment variables control the behaviour of NetBSD builds.
- HOST_SH Path name to a POSIX-compliant shell. If this is not
- set explicitly, then the default is set using heuris-
- tics dependent on the host platform, or from the shell
- under which build.sh is executed (if that can be deter-
- mined), or using the first copy of sh found in PATH.
- If the host system's /bin/sh is not POSIX-compliant, we
- suggest that you build using commands like
-
- HOST_SH=/path/to/working/shell
- export HOST_SH
- ${HOST_SH} build.sh [options]
+ HOST_SH Path name to a shell available on the host system and
+ suitable for use during the build. The NetBSD build
+ system requires a modern Bourne-like shell with POSIX-
+ compliant features, and also requires support for the
+ ``local'' keyword to declare local variables in shell
+ functions (which is a widely-implemented but non-stan-
+ dardised feature).
+
+ Depending on the host system, a suitable shell may be
+ /bin/sh, /usr/xpg4/bin/sh, /bin/ksh (provided it is a
+ variant of ksh that supports the ``local'' keyword,
+ such as ksh88, but not ksh93), or /usr/local/bin/bash.
+
+ Most parts of the build require HOST_SH to be an abso-
+ lute path; however, build.sh allows it to be a simple
+ command name, which will be converted to an absolute
+ path by searching the PATH.
HOST_CC Path name to C compiler used to create the toolchain.
@@ -629,11 +635,31 @@
those as well but currently does not.
The "build.sh" script
- This script file is a Bourne shell script designed to build the entire
- NetBSD system on any host with a Bourne shell in /bin/sh, including many
- that are not POSIX compliant. Note that if a host system's /bin/sh is
- unusually old and broken, the Korn Shell (/bin/ksh), if available, may be
- a usable alternative.
+ This script file is a shell script designed to build the entire NetBSD
+ system on any host with a suitable modern shell and some common utili-
+ ties. The required shell features are described under the HOST_SH vari-
+ able.
+
+ If a host system's default shell does support the required features, then
+ we suggest that you explicitly specify a suitable shell using a command
+ like
+
+ /path/to/suitable/shell build.sh [options]
+
+ The above command will usually enable build.sh to automatically set
+ HOST_SH=/path/to/suitable/shell, but if that fails, then the following
+ set of commands may be used instead:
+
+ HOST_SH=/path/to/suitable/shell
+ export HOST_SH
+ ${HOST_SH} build.sh [options]
+
+ If build.sh detects that it is being executed under an unsuitable shell,
+ it attempts to exec a suitable shell instead, or prints an error message.
+ If HOST_SH is not set explicitly, then build.sh sets a default using
+ heuristics dependent on the host platform, or from the shell under which
+ build.sh is executed (if that can be determined), or using the first copy
+ of sh found in PATH.
All cross-compile builds, and most native builds, of the entire system
should make use of build.sh rather than just running ``make''. This way,
Index: src/build.sh
diff -u src/build.sh:1.248 src/build.sh:1.249
--- src/build.sh:1.248 Fri Sep 9 13:29:23 2011
+++ src/build.sh Fri Sep 9 18:48:34 2011
@@ -1,5 +1,5 @@
#! /usr/bin/env sh
-# $NetBSD: build.sh,v 1.248 2011/09/09 13:29:23 apb Exp $
+# $NetBSD: build.sh,v 1.249 2011/09/09 18:48:34 apb Exp $
#
# Copyright (c) 2001-2011 The NetBSD Foundation, Inc.
# All rights reserved.
@@ -29,15 +29,234 @@
# POSSIBILITY OF SUCH DAMAGE.
#
#
-# Top level build wrapper, for a system containing no tools.
+# Top level build wrapper, to build or cross-build NetBSD.
#
-# This script should run on any POSIX-compliant shell. If the
-# first "sh" found in the PATH is a POSIX-compliant shell, then
-# you should not need to take any special action. Otherwise, you
-# should set the environment variable HOST_SH to a POSIX-compliant
-# shell, and invoke build.sh with that shell. (Depending on your
-# system, one of /bin/ksh, /usr/local/bin/bash, or /usr/xpg4/bin/sh
-# might be a suitable shell.)
+
+#
+# {{{ Begin shell feature tests.
+#
+# We try to determine whether or not this script is being run under
+# a shell that supports the features that we use. If not, we try to
+# re-exec the script under another shell. If we can't find another
+# suitable shell, then we print a message and exit.
+#
+
+errmsg='' # error message, if not empty
+shelltest=false # if true, exit after testing the shell
+re_exec_allowed=true # if true, we may exec under another shell
+
+# Parse special command line options in $1. These special options are
+# for internal use only, are not documented, and are not valid anywhere
+# other than $1.
+case "$1" in
+"--shelltest")
+ shelltest=true
+ re_exec_allowed=false
+ shift
+ ;;
+"--no-re-exec")
+ re_exec_allowed=false
+ shift
+ ;;
+esac
+
+# Solaris /bin/sh, and other SVR4 shells, do not support "!".
+# This is the first feature that we test, because subsequent
+# tests use "!".
+#
+if test -z "$errmsg"; then
+ if ( eval '! false' ) >/dev/null 2>&1 ; then
+ :
+ else
+ errmsg='Shell does not support "!".'
+ fi
+fi
+
+# Does the shell support functions?
+#
+if test -z "$errmsg"; then
+ if ! (
+ eval 'somefunction() { : ; }'
+ ) >/dev/null 2>&1
+ then
+ errmsg='Shell does not support functions.'
+ fi
+fi
+
+# Does the shell support the "local" keyword for variables in functions?
+#
+# Local variables are not required by SUSv3, but some scripts run during
+# the NetBSD build use them.
+#
+# ksh93 fails this test; it uses an incompatible syntax involving the
+# keywords 'function' and 'typeset'.
+#
+if test -z "$errmsg"; then
+ if ! (
+ eval 'f() { local v=2; }; v=1; f && test x"$v" = x"1"'
+ ) >/dev/null 2>&1
+ then
+ errmsg='Shell does not support the "local" keyword in functions.'
+ fi
+fi
+
+# Does the shell support ${var%suffix}, ${var#prefix}, and their variants?
+#
+# We don't bother testing for ${var+value}, ${var-value}, or their variants,
+# since shells without those are sure to fail other tests too.
+#
+if test -z "$errmsg"; then
+ if ! (
+ eval 'var=a/b/c ;
+ test x"${var#*/};${var##*/};${var%/*};${var%%/*}" = \
+ x"b/c;c;a/b;a" ;'
+ ) >/dev/null 2>&1
+ then
+ errmsg='Shell does not support "${var%suffix}" or "${var#prefix}".'
+ fi
+fi
+
+# Does the shell support IFS?
+#
+# zsh in normal mode (as opposed to "emulate sh" mode) fails this test.
+#
+if test -z "$errmsg"; then
+ if ! (
+ eval 'IFS=: ; v=":a b::c" ; set -- $v ; IFS=+ ;
+ test x"$#;$1,$2,$3,$4;$*" = x"4;,a b,,c;+a b++c"'
+ ) >/dev/null 2>&1
+ then
+ errmsg='Shell does not support IFS word splitting.'
+ fi
+fi
+
+# Does the shell support ${1+"$@"}?
+#
+# Some versions of zsh fail this test, even in "emulate sh" mode.
+#
+if test -z "$errmsg"; then
+ if ! (
+ eval 'set -- "a a a" "b b b"; set -- ${1+"$@"};
+ test x"$#;$1;$2" = x"2;a a a;b b b";'
+ ) >/dev/null 2>&1
+ then
+ errmsg='Shell does not support ${1+"$@"}.'
+ fi
+fi
+
+# Does the shell support $(...) command substitution?
+#
+if test -z "$errmsg"; then
+ if ! (
+ eval 'var=$(echo abc); test x"$var" = x"abc"'
+ ) >/dev/null 2>&1
+ then
+ errmsg='Shell does not support "$(...)" command substitution.'
+ fi
+fi
+
+# Does the shell support $(...) command substitution with
+# unbalanced parentheses?
+#
+# Some shells known to fail this test are: NetBSD /bin/ksh (as of 2009-12),
+# bash-3.1, pdksh-5.2.14, zsh-4.2.7 in "emulate sh" mode.
+#
+if test -z "$errmsg"; then
+ if ! (
+ eval 'var=$(case x in x) echo abc;; esac); test x"$var" = x"abc"'
+ ) >/dev/null 2>&1
+ then
+ # XXX: This test is ignored because so many shells fail it; instead,
+ # the NetBSD build avoids using the problematic construct.
+ : ignore 'Shell does not support "$(...)" with unbalanced ")".'
+ fi
+fi
+
+# Does the shell support getopts or getopt?
+#
+if test -z "$errmsg"; then
+ if ! (
+ eval 'type getopts || type getopt'
+ ) >/dev/null 2>&1
+ then
+ errmsg='Shell does not support getopts or getopt.'
+ fi
+fi
+
+#
+# If shelltest is true, exit now, reporting wheher or not the shell is good.
+#
+if $shelltest; then
+ if test -n "$errmsg"; then
+ echo >&2 "$0: $errmsg"
+ exit 1
+ else
+ exit 0
+ fi
+fi
+
+#
+# If the shell was bad, try to exec a better shell, or report an error.
+#
+# Loops are broken by passing an extra "--no-re-exec" flag to the new
+# instance of this script.
+#
+if test -n "$errmsg"; then
+ if $re_exec_allowed; then
+ for othershell in \
+ "${HOST_SH}" /usr/xpg4/bin/sh ksh ksh88 mksh pdksh bash dash
+ # NOTE: some shells known not to work are:
+ # any shell using csh syntax;
+ # Solaris /bin/sh (missing many modern features);
+ # ksh93 (incompatible syntax for local variables);
+ # zsh (many differences, unless run in compatibility mode).
+ do
+ test -n "$othershell" || continue
+ if eval 'type "$othershell"' >/dev/null 2>&1 \
+ && "$othershell" "$0" --shelltest >/dev/null 2>&1
+ then
+ cat <<EOF
+$0: $errmsg
+$0: Retrying under $othershell
+EOF
+ HOST_SH="$othershell"
+ export HOST_SH
+ exec $othershell "$0" --no-re-exec "$@" # avoid ${1+"$@"}
+ fi
+ # If HOST_SH was set, but failed the test above,
+ # then give up without trying any other shells.
+ test x"${othershell}" = x"${HOST_SH}" && break
+ done
+ fi
+
+ #
+ # If we get here, then the shell is bad, and we either could not
+ # find a replacement, or were not allowed to try a replacement.
+ #
+ cat <<EOF
+$0: $errmsg
+
+The NetBSD build system requires a shell that supports modern POSIX
+features, as well as the "local" keyword in functions (which is a
+widely-implemented but non-standardised feature).
+
+Please re-run this script under a suitable shell. For example:
+
+ /path/to/suitable/shell $0 ...
+
+The above command will usually enable build.sh to automatically set
+HOST_SH=/path/to/suitable/shell, but if that fails, then you may also
+need to explicitly set the HOST_SH environment variable, as follows:
+
+ HOST_SH=/path/to/suitable/shell
+ export HOST_SH
+ \${HOST_SH} $0 ...
+EOF
+ exit 1
+fi
+
+#
+# }}} End shell feature tests.
#
progname=${0##*/}
@@ -169,6 +388,13 @@
#
[ -x "${HOST_SH}" ] ||
bomb "HOST_SH=\"${HOST_SH}\" is not executable."
+
+ # If HOST_SH fails tests, bomb.
+ # ("$0" may be a path that is no longer valid, because we have
+ # performed "cd $(dirname $0)", so don't use $0 here.)
+ #
+ "${HOST_SH}" build.sh --shelltest ||
+ bomb "HOST_SH=\"${HOST_SH}\" failed functionality tests."
}
# initdefaults --
@@ -699,7 +925,7 @@
optremcmd='shift $((${OPTIND} -1))'
else
type getopt >/dev/null 2>&1 ||
- bomb "/bin/sh shell is too old; try ksh or bash"
+ bomb "Shell does not support getopts or getopt"
# Use old-style getopt(1) (doesn't handle whitespace in args).
#
@@ -1404,7 +1630,7 @@
eval cat <<EOF ${makewrapout}
#! ${HOST_SH}
# Set proper variables to allow easy "make" building of a NetBSD subtree.
-# Generated from: \$NetBSD: build.sh,v 1.248 2011/09/09 13:29:23 apb Exp $
+# Generated from: \$NetBSD: build.sh,v 1.249 2011/09/09 18:48:34 apb Exp $
# with these arguments: ${_args}
#
Index: src/doc/BUILDING.mdoc
diff -u src/doc/BUILDING.mdoc:1.84 src/doc/BUILDING.mdoc:1.85
--- src/doc/BUILDING.mdoc:1.84 Fri Sep 9 14:23:38 2011
+++ src/doc/BUILDING.mdoc Fri Sep 9 18:48:34 2011
@@ -1,4 +1,4 @@
-.\" $NetBSD: BUILDING.mdoc,v 1.84 2011/09/09 14:23:38 apb Exp $
+.\" $NetBSD: BUILDING.mdoc,v 1.85 2011/09/09 18:48:34 apb Exp $
.\"
.\" Copyright (c) 2001-2011 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -170,25 +170,35 @@
.
.
.It Sy HOST_SH
-Path name to a POSIX-compliant shell.
-If this is not set explicitly, then the default is set
-using heuristics dependent on the host platform,
-or from the shell under which
+Path name to a shell available on the host system
+and suitable for use during the build.
+The
+.Nx
+build system requires a modern Bourne-like shell
+with POSIX-compliant features,
+and also requires support for the
+.Dq local
+keyword to declare local variables in shell functions
+(which is a widely-implemented but non-standardised feature).
+.Pp
+Depending on the host system, a suitable shell may be
+.Pa /bin/sh ,
+.Pa /usr/xpg4/bin/sh ,
+.Pa /bin/ksh
+(provided it is a variant of ksh that supports the
+.Dq local
+keyword,
+such as ksh88, but not ksh93),
+or
+.Pa /usr/local/bin/bash .
+.Pp
+Most parts of the build require
+.Sy HOST_SH
+to be an absolute path; however,
.Nm build.sh
-is executed (if that can be determined),
-or using the first copy of
-.Pa sh
-found in
+allows it to be a simple command name, which will be converted
+to an absolute path by searching the
.Sy PATH .
-If the host system's
-.Pa /bin/sh
-is not POSIX-compliant, we suggest that you build using
-commands like
-.Bd -unfilled -offset indent
-.Li HOST_SH= Ns Va /path/to/working/shell
-.Li export HOST_SH
-.Li ${HOST_SH} build.sh Op Ar options
-.Ed
.
.It Sy HOST_CC
Path name to C compiler used to create the toolchain.
@@ -1155,17 +1165,49 @@
.
.Ss The \*qbuild.sh\*q script
.
-This script file is a Bourne shell script designed to build the
+This script file is a shell script designed to build the
entire
.Nx
-system on any host with a Bourne shell in
-.Sy /bin/sh ,
-including many that are not POSIX compliant.
-Note that if a host system's
-.Sy /bin/sh
-is unusually old and broken, the Korn Shell
-.Sy ( /bin/ksh ) ,
-if available, may be a usable alternative.
+system on any host with a suitable modern shell and some common
+utilities.
+The required shell features are described under the
+.Sy HOST_SH
+variable.
+.Pp
+If a host system's default shell does support the required
+features, then we suggest that you explicitly specify
+a suitable shell using a command like
+.Bd -unfilled -offset indent
+.Li /path/to/suitable/shell build.sh Op Ar options
+.Ed
+.Pp
+The above command will usually enable
+.Nm build.sh
+to automatically set
+.Sy HOST_SH Ns Cm = Ns Pa /path/to/suitable/shell ,
+but if that fails, then the following set of commands may be used instead:
+.Bd -unfilled -offset indent
+.Li HOST_SH= Ns Va /path/to/suitable/shell
+.Li export HOST_SH
+.Li ${HOST_SH} build.sh Op Ar options
+.Ed
+.Pp
+If
+.Sy build.sh
+detects that it is being executed under an unsuitable shell, it attempts
+to exec a suitable shell instead, or prints an error message.
+If
+.Sy HOST_SH
+is not set explicitly, then
+.Nm build.sh
+sets a default using heuristics dependent on the host platform,
+or from the shell under which
+.Nm build.sh
+is executed (if that can be determined),
+or using the first copy of
+.Pa sh
+found in
+.Sy PATH .
.Pp
All cross-compile builds, and most native builds, of the entire system
should make use of