blob: 0d6b9be6a52adf6ce2c937ac7aad32afbc9c3815 [file] [log] [blame]
#!/usr/bin/env bash
#
# Copyright 2019-2020 Google LLC. All Rights Reserved.
# Copyright 2014-2017 Nest Labs Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Description:
# This file is a convenience script that will bootstrap the GNU
# autotools system for a project after any build system changes.
#
#
# usage
#
# Display program usage.
#
usage() {
name="$(basename "${0}")"
echo "Usage: ${name} [ options ] [ -w <what> ]"
if [ "${1}" -ne 0 ]; then
echo "Try '${name} -h' for more information."
fi
if [ "${1}" -ne 1 ]; then
echo ""
echo " -h, --help Print this help, then exit."
echo " -I DIR Specify directory DIR as the root of the "
echo " nlbuild-autotools repository."
echo " -v, --verbose Verbosely report bootstrap progress."
echo " -w, --what WHAT Specify what part of the package should be "
echo " bootstrapped: all, config, make, or none "
echo " (default: all)."
echo ""
fi
exit "${1}"
}
#
# check_required_executable <path variable> <executable name>
#
# Check to ensure that the named executable with the path in the
# provided variable exists and is executable by the current user.
#
check_required_executable() {
variable="${1}"
path="${!variable}"
name="${2}"
output="${3}"
stem="The required executable '${name}'"
if [ -z "${path}" ]; then
echo "${stem} could not be found."
eval "${output}=no"
return 1
elif [ ! -e "${path}" ] || [ ! -x "${path}" ]; then
stem="${stem} at '${path}'"
if [ ! -e "${path}" ]; then
echo "${stem} does not exist."
elif [ ! -x "${path}" ]; then
echo "${stem} is not executable."
fi
echo "Please ensure '${name}' is available in PATH."
eval "${output}=no"
return 1
fi
eval "${output}=yes"
return 0
}
check_required_executables()
{
local have_aclocal
local have_autoconf
local have_autoheader
local have_automake
local have_libtoolize
local have_m4
check_required_executable ACLOCAL aclocal have_aclocal
check_required_executable AUTOCONF autoconf have_autoconf
check_required_executable AUTOHEADER autoheader have_autoheader
check_required_executable AUTOMAKE automake have_automake
check_required_executable LIBTOOLIZE libtoolize have_libtoolize
check_required_executable M4 m4 have_m4
if [ "${have_aclocal}" = "no" ] || [ "${have_autoconf}" = "no" ] || [ "${have_autoheader}" = "no" ] || [ "${have_automake}" = "no" ] || [ "${have_libtoolize}" = "no" ] || [ "${have_m4}" = "no" ]; then
cat << EOF
--------------------------------------------------------------------------------
Your build host system is missing one or more of the above executables required
for bootstrapping this nlbuild-autotools-based package. You can either install
these yourself using package management tools available and appropriate for your
build host platform or you can build preselected versions of these executables
from source for this package on this build host by invoking:
make -C ${nlbuild_autotools_dir} tools
and then re-running this script which will use those executables.
--------------------------------------------------------------------------------
EOF
exit 1
fi
}
#
# removetmp
#
# Remove temporary files and directories used during the run of this
# script.
#
removetmp() {
if [ -n "${LIBTOOLIZE}" ] && [ "${LIBTOOLIZE}" = "${BOOTSTRAP_TMPDIR}/libtoolize" ]; then
rm -f "${LIBTOOLIZE}"
fi
if [ -n "${AUTOM4TE_CFG}" ]; then
rm -f "${AUTOM4TE_CFG}"
fi
rm -r -f "${BOOTSTRAP_TMPDIR}"
}
#
# try_tool_action <tool executable>
#
# This attempts to run the specified build bootstrap tool, displaying
# the tool action to standard output if the verbose flag has been
# asserted.
#
# If the tool has failure status or if the verbose flag has been
# asserted, any error output from the tool is displayed to standard
# error. Likewise, if the tool has failure status, temporary files are
# removed and the script exits with that failed status.
#
try_tool_action()
{
local action
local errors
local status
action="${1}"
# If the verbose flag is asserted, display to standard output the
# tool action that will be run.
if [[ -n "${verbose}" ]]; then
echo "${action}"
fi
# Run the tool, capturing any errors and exit status.
errors="$(${action} 2>&1)"
status="${?}"
# If there was failed exit status or if the verbose flag is
# asserted and if there were errors captured, display them to
# standard error.
if [[ ${status} -ne 0 ]] || [[ -n "${verbose}" ]]; then
if [[ -n "${errors}" ]]; then
echo "${errors}" >&2
fi
fi
# If there was failed exit status, clean up any temporary files
# and exit with the failed status.
if [[ ${status} -ne 0 ]]; then
removetmp
exit ${status}
fi
}
what="all"
verbose=
nlbuild_autotools_dir=
# Parse out any command line options
while [ ${#} -gt 0 ]; do
case ${1} in
-h|--help)
usage 0
;;
-I)
nlbuild_autotools_dir="${2}"
shift 2
;;
-v|--verbose)
verbose="--verbose"
shift 1
;;
-w|--what)
case "${2}" in
all|make*|conf*|none)
what="${2}"
shift 2
;;
*)
echo "Unknown what value '${2}'." >&2
usage 1
;;
esac
;;
*)
usage 1
;;
esac
done
# Check to ensure that the location of the nlbuild-autotools directory
# is sane.
if [ -z "${nlbuild_autotools_dir}" ]; then
echo "$0: No -I option specified. Please provide the location of the nlbuild-autotools directory." >&2
exit 1
elif [ ! -d "${nlbuild_autotools_dir}" ]; then
echo "$0: No such directory: ${nlbuild_autotools_dir}. Please provide a valid path to the nlbuild-autotools directory." >&2
exit 1
fi
# Establish some key directories
abs_top_hostdir="${nlbuild_autotools_dir}/tools/host"
# Figure out what sort of build host we are running on, stripping off
# any trailing version number information typically included on Darwin
# / Mac OS X.
host="$("${nlbuild_autotools_dir}/third_party/autoconf/config.guess" | sed -e 's/[[:digit:].]*$//g')"
# If possible, attempt to be self-sufficient, relying on GNU autotools
# executables installed along with the SDK itself.
if [ -d "${abs_top_hostdir}/${host}/bin" ]; then
export PATH="${abs_top_hostdir}/${host}/bin:${PATH}"
fi
if [ -d "${abs_top_hostdir}/bin" ]; then
export PATH="${abs_top_hostdir}/bin:${PATH}"
fi
ACLOCAL="$(command -v aclocal)"
AUTOCONF="$(command -v autoconf)"
AUTOHEADER="$(command -v autoheader)"
AUTOM4TE="$(command -v autom4te)"
AUTOMAKE="$(command -v automake)"
LIBTOOLIZE="$(command -v libtoolize || command -v glibtoolize)"
M4="$(command -v m4)"
TRUE="$(command -v true)"
export ACLOCAL
export AUTOCONF
export AUTOHEADER
export AUTOM4TE
export AUTOMAKE
export LIBTOOLIZE
export M4
# Establish, if necessary, some SDK-specific directories needed to
# override various paths in GNU autotools that otherwise expect to be
# absolute (e.g. /usr/share, etc.).
if [ -d "${abs_top_hostdir}/share" ]; then
if [ -d "${abs_top_hostdir}/share/autoconf" ]; then
export AC_MACRODIR="${abs_top_hostdir}/share/autoconf"
export autom4te_perllibdir="${abs_top_hostdir}/share/autoconf"
fi
if [ -d "${abs_top_hostdir}/share/automake-1.14" ]; then
export PERL5LIB="${abs_top_hostdir}/share/automake-1.14:${PERL5LIB}"
make_action_options="--libdir ${abs_top_hostdir}/share/automake-1.14"
fi
if [ -d "${abs_top_hostdir}/share/aclocal-1.14" ]; then
local_action_options="--automake-acdir=${abs_top_hostdir}/share/aclocal-1.14 ${local_action_options}"
fi
if [ -d "${abs_top_hostdir}/share/aclocal" ]; then
local_action_options="--system-acdir=${abs_top_hostdir}/share/aclocal ${local_action_options}"
fi
fi
# Both autom4te.cfg and libtoolize, as installed from source, want to
# use absolute file system paths that cannot be
# overridden. Consequently, we create temporary, local versions of
# these, patched up with SDK-specific paths.
BOOTSTRAP_TMPDIR="$(mktemp -d /tmp/tmp.bootstrapXXXXXX)"
trap "removetmp" 1 2 3 15
#
# Generate any temporary files that need to be patched at run time
# with the location of the SDK tree, including:
#
# - The autom4te configuration file
# - The libtoolize executable script
#
if [ -r "${abs_top_hostdir}/share/autoconf/autom4te.cfg" ]; then
export AUTOM4TE_CFG="${BOOTSTRAP_TMPDIR}/autom4te.cfg"
sed -e "s,//share/autoconf,${abs_top_hostdir}/share/autoconf,g" < "${abs_top_hostdir}/share/autoconf/autom4te.cfg" > "${AUTOM4TE_CFG}"
fi
if [ -r "${abs_top_hostdir}/${host}/bin/libtoolize" ]; then
export LIBTOOLIZE="${BOOTSTRAP_TMPDIR}/libtoolize"
sed -e "s,//share/libtool,${abs_top_hostdir}/share/libtool,g" -e "s,//share/aclocal,${abs_top_hostdir}/share/aclocal,g" < "${abs_top_hostdir}/${host}/bin/libtoolize" > "${LIBTOOLIZE}"
chmod 775 "${LIBTOOLIZE}"
fi
# Before we get much further, check to ensure that the required
# executables are available and, if not, provide some actionable
# guidance.
check_required_executables
if [ -n "${verbose}" ]; then
echo PATH="${PATH}"
echo ACLOCAL="${ACLOCAL}"
echo AUTOCONF="${AUTOCONF}"
echo AUTOHEADER="${AUTOHEADER}"
echo AUTOM4TE="${AUTOM4TE}"
echo AUTOMAKE="${AUTOMAKE}"
echo LIBTOOLIZE="${LIBTOOLIZE}"
echo M4="${M4}"
echo TRUE="${TRUE}"
echo AC_MACRODIR="${AC_MACRODIR}"
echo AUTOM4TE_CFG="${AUTOM4TE_CFG}"
echo PERL5LIB="${PERL5LIB}"
echo autom4te_perllibdir="${autom4te_perllibdir}"
echo local_action_options="${local_action_options}"
echo make_action_options="${make_action_options}"
fi
# Set up the default actions for each bootstrap stage.
local_action="${ACLOCAL} ${verbose} ${local_action_options}"
header_action="${AUTOHEADER} ${verbose}"
tool_action="${LIBTOOLIZE} ${verbose} --automake --copy --force"
make_action="${AUTOMAKE} ${verbose} ${make_action_options} --add-missing --copy"
config_action="${AUTOCONF} ${verbose}"
# Determine what needs to be short-circuited based on the
# user-specified "what".
case "${what}" in
all)
;;
conf*)
local_action="${TRUE}"
header_action="${TRUE}"
tool_action="${TRUE}"
make_action="${TRUE}"
;;
make*)
local_action="${TRUE}"
header_action="${TRUE}"
config_action="${TRUE}"
;;
none)
local_action="${TRUE}"
header_action="${TRUE}"
tool_action="${TRUE}"
make_action="${TRUE}"
config_action="${TRUE}"
;;
esac
# Bootstrap the package.
try_tool_action "${local_action}"
try_tool_action "${tool_action}"
try_tool_action "${header_action}"
try_tool_action "${make_action}"
try_tool_action "${config_action}"
# Clean up any temporary files created.
removetmp