blob: aab550a2275e02d8ebe918bedcc8853f91970aaa [file] [log] [blame]
#!/bin/sh
#
# 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 for building, for the current
# build host system, the minimal, core set of GNU autotools on
# which other projects' build systems depend.
#
EXTENSIONS="tar.gz tar.xz"
VERBOSE=0
stem=tools/packages
abs_srcdir=`pwd`
abs_top_srcdir=`echo ${abs_srcdir} | sed -e s,/${stem},,g`
abs_top_hostdir="${abs_top_srcdir}/tools/host"
#
# usage
#
# Display program usage.
#
usage() {
name=`basename ${0}`
echo "Usage: ${name} [ options ] [ -- <package> ... ]"
if [ $1 -ne 0 ]; then
echo "Try '${name} -h' for more information."
fi
if [ $1 -ne 1 ]; then
echo ""
echo " --arch ARCH Build the package for ARCH host architecture."
echo " -h, --help Print this help, then exit."
echo " --builddir DIR Build the packages in DIR."
echo " --destdir DIR Install the built tools to directory DIR."
echo " --srcdir DIR Find package, version, and URL metadata in DIR."
echo " -v, --verbose Enable verbose output."
echo ""
fi
exit $1
}
#
# error <...>
#
# Display to standard error the specified arguments
#
error() {
echo "${*}" >&2
}
#
# verbose <...>
#
# Display to standard error the specified arguments
#
verbose() {
echo "${*}" >&2
}
#
# separator
#
# Display to standard error a log separator.
#
separator() {
verbose "--------------------------------------------------------------------------------"
}
#
# trailer
#
# Display to standard error a log trailer.
#
trailer() {
verbose "================================================================================"
}
#
# banner <message ...>
#
# Display to standard error a log banner with a message.
#
banner() {
trailer
verbose "${*}"
}
#
# subbanner <message ...>
#
# Display to standard error a log subbanner with a message.
#
subbanner() {
separator
verbose "${*}"
}
#
# find_archive <subdir> <package> <extensions...>
#
# Attempt to find the specified package archive in the provided
# subdirectory matching one of the specified extensions.
#
find_archive() {
local subdir="${1}"
local package="${2}"
local archive
shift 2
for extension in ${*}; do
local maybe_archive="${subdir}/${package}.${extension}"
verbose " FIND ${maybe_archive}"
if [ -r "${maybe_archive}" ]; then
archive="${maybe_archive}"
break
fi
done
echo "${archive}"
}
#
# find_versioned_or_nonversioned_archive <subdir> <package> <version> <extensions...>
#
# Attempt to find the specified version-qualified or non-qualified
# package archive in the provided subdirectory matching one of the
# specified extensions.
#
find_versioned_or_nonverioned_archive() {
local subdir="${1}"
local package="${2}"
local version="${3}"
local fqpackage="${package}-${version}"
local archive
shift 3
archive="`find_archive ${subdir} ${fqpackage} ${*}`"
if [ -z "${archive}" ]; then
archive="`find_archive ${subdir} ${package} ${*}`"
fi
echo "${archive}"
}
#
# fetch_url_with_command <fetchdir> <url> <command ...>
#
# Attempt to fetch the specified URL to the provided directory with
# the provided command.
#
fetch_url_with_command() {
local fetchdir="${1}"
local url="${2}"
local curdir="`pwd`"
shift 2
cd "${fetchdir}"
${*} "${url}"
if [ ${?} -ne 0 ]; then
error "Failed to fetch ${url} with ${1}."
fi
cd "${curdir}"
}
#
# fetch_url <fetchdir> <url>
#
# Attempt to fetch the specified URL to the provided directory with
# either wget or curl.
#
fetch_url() {
local fetchdir="${1}"
local url="${2}"
# Try to fetch the package using wget or curl
fetch_url_with_command "${fetchdir}" "${url}" wget --quiet ||
fetch_url_with_command "${fetchdir}" "${url}" curl --silent --remote-name
}
#
# fetch_package <finddir> <fetchdir> <package> <version> <url>
#
# Attempt to fetch the specified package version to <fetchdir>, if a
# local archive does not already exist in <finddir> or <fetchdir>,
# from the provided URL.
#
fetch_package() {
local finddir="${1}"
local fetchdir="${2}"
local package="${3}"
local version="${4}"
local url="${5}"
local fqpackage="${package}-${version}"
# Check whether a local archive already exists in <finddir> or <fetchdir>.
archive="`find_versioned_or_nonverioned_archive ${finddir} ${package} ${version} ${EXTENSIONS}`"
if [ -z "${archive}" ]; then
archive="`find_versioned_or_nonverioned_archive ${fetchdir} ${package} ${version} ${EXTENSIONS}`"
fi
# If no archive was found, attempt to fetch it.
if [ -z "${archive}" ]; then
verbose " FETCH ${url}"
fetch_url "${fetchdir}" "${url}"
else
error "No, found ${archive} locally."
fi
}
#
# removetmp
#
# Remove temporary files and directories used during the run of this
# script.
#
removetmp() {
rm -f "${LIBTOOLIZE}"
if [ -n "${AUTOM4TE_CFG}" ]; then
rm -f "${AUTOM4TE_CFG}"
fi
}
#
# build_package <package> <version> <host> <archivedir> <builddir> <destdir>
#
# Build the specified package version for <host> in <builddir> from
# the archive found in <archivedir> and install it into the specified
# destination directory, <destdir>.
#
build_package() {
local package="${1}"
local version="${2}"
local host="${3}"
local archivedir="${4}"
local builddir="${5}"
local destdir="${6}"
local fqpackage="${package}-${version}"
local curdir=`pwd`
local archive
verbose " CHECK ${package}"
archive="`find_versioned_or_nonverioned_archive ${archivedir} ${package} ${version} ${EXTENSIONS}`"
if [ -z "${archive}" ]; then
error "Could not find an archive for ${package}."
exit 1
fi
if [ ! -d "${archivedir}/${fqpackage}" ]; then
verbose " TAR ${archive}"
tar --directory "${archivedir}" -xf "${archive}" || exit ${?}
fi
# If possible, attempt to be self-sufficient, relying on GNU autotools
# executables installed along with the SDK itself.
if [ -d "${destdir}/${host}/bin" ]; then
export PATH="${destdir}/${host}/bin:${PATH}"
fi
if [ -d "${destdir}/bin" ]; then
export PATH="${destdir}/bin:${PATH}"
fi
export ACLOCAL=`which aclocal`
export AUTOCONF="`which autoconf`"
export AUTOHEADER="`which autoheader`"
export AUTOM4TE="`which autom4te`"
export AUTOMAKE="`which automake`"
export LIBTOOLIZE="`which libtoolize || which glibtoolize`"
export M4=`which 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 "${destdir}/share" ]; then
if [ -d "${destdir}/share/autoconf" ]; then
export AC_MACRODIR="${destdir}/share/autoconf"
export autom4te_perllibdir="${destdir}/share/autoconf"
fi
if [ -d "${destdir}/share/automake-1.14" ]; then
export PERL5LIB="${destdir}/share/automake-1.14:${PERL5LIB}"
fi
fi
trap "removetmp" 1 2 3 9 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 "${destdir}/share/autoconf/autom4te.cfg" ]; then
export AUTOM4TE_CFG="${destdir}/autom4te.cfg"
sed -e "s,//share/autoconf,${destdir}/share/autoconf,g" < "${destdir}/share/autoconf/autom4te.cfg" > "${AUTOM4TE_CFG}"
fi
if [ -r "${destdir}/${host}/bin/libtoolize" ]; then
export LIBTOOLIZE="${destdir}/libtoolize"
sed -e "s,//share/libtool,${destdir}/share/libtool,g" -e "s,//share/aclocal,${destdir}/share/aclocal,g" < "${destdir}/${host}/bin/libtoolize" > "${LIBTOOLIZE}"
chmod 775 "${LIBTOOLIZE}"
fi
# Configure the package
if [ ${VERBOSE} -gt 0 ]; then
CONFIGURE_FLAGS=""
else
CONFIGURE_FLAGS="--quiet"
fi
verbose " CONFIG ${package}"
cd "${builddir}"
${archivedir}/${fqpackage}/configure ${CONFIGURE_FLAGS} --prefix=/ --exec-prefix=/${host} || exit ${?}
cd "${curdir}"
# Build the package
verbose " MAKE ${package}"
make V=${VERBOSE} -C "${builddir}" all || exit ${?}
# Install / stage the package
verbose " INSTALL ${package}"
make V=${VERBOSE} -C "${builddir}" DESTDIR="${destdir}" install-strip || exit ${?}
# Remove any temporary files created.
removetmp
}
# Parse out any command line options
while [ ${#} -gt 0 ]; do
case ${1} in
--arch)
ARCH=${2}
shift 2
;;
-h|--help)
usage 0
;;
--builddir)
BUILDDIR=${2}
shift 2
;;
--destdir)
DESTDIR=${2}
shift 2
;;
--srcdir)
SRCDIR=${2}
shift 2
;;
-v|--verbose)
$((VERBOSE++))
shift 1
;;
--)
shift 1
break
;;
*)
usage 1
;;
esac
done
# If the architecture is not specified, fail.
if [ -z "${ARCH}" ]; then
error "The host architecture was not specified via --arch."
usage 1
fi
# If the --builddir option wasn't specified, then provide a default.
if [ -z "${BUILDDIR}" ]; then
BUILDDIR="`pwd`"
fi
# If the --destdir option wasn't specified, then provide a default.
if [ -z "${DESTDIR}" ]; then
DESTDIR=${abs_top_hostdir}
fi
# If the --srcdir option wasn't specified, then provide a default.
if [ -z "${SRCDIR}" ]; then
SRCDIR="`pwd`"
fi
# Determine what packages to build
if [ ${#} -gt 0 ]; then
PACKAGES="${*}"
else
PACKAGES="`cat ${SRCDIR}/packages`"
fi
# Build each package
banner "Building GNU autotools for ${ARCH}..."
for package in ${PACKAGES}; do
url="`cat ${SRCDIR}/${package}/${package}.url`"
version="`cat ${SRCDIR}/${package}/${package}.version`"
# Fetch, if necessary, the package from the canonical source location.
subbanner " CHECK ${package}"
fetch_package "${SRCDIR}/${package}" "${BUILDDIR}" "${package}" "${version}" "${url}"
# Build and install the package.
verbose " MKDIR ${BUILDDIR}/build/${ARCH}/${package}-${version}"
mkdir -p "${BUILDDIR}/build/${ARCH}/${package}-${version}" || exit ${?}
build_package "${package}" "${version}" "${ARCH}" "${BUILDDIR}" "${BUILDDIR}/build/${ARCH}/${package}-${version}" "${DESTDIR}"
done
trailer