1#!/bin/sh 2 3# 4# Copyright 2014-2018 Nest Labs Inc. All Rights Reserved. 5# Copyright 2018 Google LLC. All Rights Reserved. 6# 7# Licensed under the Apache License, Version 2.0 (the "License"); 8# you may not use this file except in compliance with the License. 9# You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, software 14# distributed under the License is distributed on an "AS IS" BASIS, 15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16# See the License for the specific language governing permissions and 17# limitations under the License. 18# 19 20# 21# Description: 22# This file is a convenience script for building, for the current 23# build host system, the minimal, core set of GNU autotools on 24# which other projects' build systems depend. 25# 26 27EXTENSIONS="tar.gz tar.xz" 28 29VERBOSE=0 30 31stem=tools/packages 32abs_srcdir=`pwd` 33abs_top_srcdir=`echo ${abs_srcdir} | sed -e s,/${stem},,g` 34 35abs_top_hostdir="${abs_top_srcdir}/tools/host" 36 37# 38# usage 39# 40# Display program usage. 41# 42usage() { 43 name=`basename ${0}` 44 45 echo "Usage: ${name} [ options ] [ -- <package> ... ]" 46 47 if [ $1 -ne 0 ]; then 48 echo "Try '${name} -h' for more information." 49 fi 50 51 if [ $1 -ne 1 ]; then 52 echo "" 53 echo " --arch ARCH Build the package for ARCH host architecture." 54 echo " -h, --help Print this help, then exit." 55 echo " --builddir DIR Build the packages in DIR." 56 echo " --destdir DIR Install the built tools to directory DIR." 57 echo " --srcdir DIR Find package, version, and URL metadata in DIR." 58 echo " -v, --verbose Enable verbose output." 59 echo "" 60 fi 61 62 exit $1 63} 64 65# 66# error <...> 67# 68# Display to standard error the specified arguments 69# 70error() { 71 echo "${*}" >&2 72} 73 74# 75# verbose <...> 76# 77# Display to standard error the specified arguments 78# 79verbose() { 80 echo "${*}" >&2 81} 82 83# 84# separator 85# 86# Display to standard error a log separator. 87# 88separator() { 89 verbose "--------------------------------------------------------------------------------" 90} 91 92# 93# trailer 94# 95# Display to standard error a log trailer. 96# 97trailer() { 98 verbose "================================================================================" 99} 100 101# 102# banner <message ...> 103# 104# Display to standard error a log banner with a message. 105# 106banner() { 107 trailer 108 109 verbose "${*}" 110} 111 112# 113# subbanner <message ...> 114# 115# Display to standard error a log subbanner with a message. 116# 117subbanner() { 118 separator 119 120 verbose "${*}" 121} 122 123# 124# find_archive <subdir> <package> <extensions...> 125# 126# Attempt to find the specified package archive in the provided 127# subdirectory matching one of the specified extensions. 128# 129find_archive() { 130 local subdir="${1}" 131 local package="${2}" 132 local archive 133 134 shift 2 135 136 for extension in ${*}; do 137 local maybe_archive="${subdir}/${package}.${extension}" 138 139 verbose " FIND ${maybe_archive}" 140 141 if [ -r "${maybe_archive}" ]; then 142 archive="${maybe_archive}" 143 break 144 fi 145 done 146 147 echo "${archive}" 148} 149 150# 151# find_versioned_or_nonversioned_archive <subdir> <package> <version> <extensions...> 152# 153# Attempt to find the specified version-qualified or non-qualified 154# package archive in the provided subdirectory matching one of the 155# specified extensions. 156# 157find_versioned_or_nonverioned_archive() { 158 local subdir="${1}" 159 local package="${2}" 160 local version="${3}" 161 local fqpackage="${package}-${version}" 162 local archive 163 164 shift 3 165 166 archive="`find_archive ${subdir} ${fqpackage} ${*}`" 167 168 if [ -z "${archive}" ]; then 169 archive="`find_archive ${subdir} ${package} ${*}`" 170 fi 171 172 echo "${archive}" 173} 174 175# 176# fetch_url_with_command <fetchdir> <url> <command ...> 177# 178# Attempt to fetch the specified URL to the provided directory with 179# the provided command. 180# 181fetch_url_with_command() { 182 local fetchdir="${1}" 183 local url="${2}" 184 local executable="`which ${3}`" 185 local curdir="`pwd`" 186 local status=1 187 188 shift 2 189 190 if [ -x "${executable}" ]; then 191 cd "${fetchdir}" 192 193 verbose " `echo ${1} | tr '[[:lower:]]' '[[:upper:]]'` ${url}" 194 195 ${*} "${url}" 196 197 status=${?} 198 199 if [ ${?} -ne 0 ]; then 200 error "Failed to fetch ${url} with ${1}." 201 fi 202 203 cd "${curdir}" 204 fi 205 206 return ${status} 207} 208 209# 210# fetch_url <fetchdir> <url> 211# 212# Attempt to fetch the specified URL to the provided directory with 213# either wget or curl. 214# 215fetch_url() { 216 local fetchdir="${1}" 217 local url="${2}" 218 219 # Try to fetch the package using wget or curl 220 221 fetch_url_with_command "${fetchdir}" "${url}" wget --tries 4 --no-check-certificate --quiet || 222 fetch_url_with_command "${fetchdir}" "${url}" curl --retry 4 --insecure --silent --remote-name 223} 224 225# 226# fetch_package <finddir> <fetchdir> <package> <version> <url> 227# 228# Attempt to fetch the specified package version to <fetchdir>, if a 229# local archive does not already exist in <finddir> or <fetchdir>, 230# from the provided URL. 231# 232fetch_package() { 233 local finddir="${1}" 234 local fetchdir="${2}" 235 local package="${3}" 236 local version="${4}" 237 local url="${5}" 238 local fqpackage="${package}-${version}" 239 240 # Check whether a local archive already exists in <finddir> or <fetchdir>. 241 242 archive="`find_versioned_or_nonverioned_archive ${finddir} ${package} ${version} ${EXTENSIONS}`" 243 244 if [ -z "${archive}" ]; then 245 archive="`find_versioned_or_nonverioned_archive ${fetchdir} ${package} ${version} ${EXTENSIONS}`" 246 fi 247 248 # If no archive was found, attempt to fetch it. 249 250 if [ -z "${archive}" ]; then 251 verbose " FETCH ${url}" 252 253 fetch_url "${fetchdir}" "${url}" 254 255 else 256 error "No, found ${archive} locally." 257 258 fi 259} 260 261# 262# removetmp 263# 264# Remove temporary files and directories used during the run of this 265# script. 266# 267removetmp() { 268 if [ -O "${LIBTOOLIZE}" ]; then 269 rm -f "${LIBTOOLIZE}" 270 fi 271 if [ -n "${AUTOM4TE_CFG}" ]; then 272 rm -f "${AUTOM4TE_CFG}" 273 fi 274} 275 276# 277# patch_directory <directory> <patch arguments> <patch file> [ ... ] 278# 279# Patch the specified directory by applying the provided patched files 280# using the specified patch arguments. The specified patch files may 281# be uncompressed or compressed with any of bz2, gz, xz, compress, or 282# zip. 283# 284patch_directory() { 285 local directory="${1}" 286 local patchargs="${2}" 287 288 shift 2 289 290 verbose " PATCH ${directory}" 291 292 for patch in "${*}"; do 293 verbose " PATCH ${patch}" 294 295 extension=`echo "${patch}" | awk -F . '{if (NF > 1) {print $$NF}}'`; 296 297 case "${extension}" in 298 299 bz2) 300 uncompressor="bunzip2 -c" 301 ;; 302 303 gz) 304 uncompressor="gunzip -c" 305 ;; 306 307 xz) 308 uncompressor="xz -d -c" 309 ;; 310 311 Z) 312 uncompressor="uncompress -c" 313 ;; 314 315 zip) 316 uncompressor="unzip -p" 317 ;; 318 319 *) 320 uncompressor="cat" 321 ;; 322 323 esac 324 325 ${uncompressor} "${patch}" | patch ${patchargs} -d "${directory}" || exit 1; 326 327 done 328} 329 330# 331# build_package <package> <version> <host> <patchdir> <archivedir> <builddir> <destdir> 332# 333# Build the specified package version for <host> in <builddir> from 334# the archive found in <archivedir>, after applying the patches in 335# <patchdir> (if any), and install it into the specified destination 336# directory, <destdir>. 337# 338build_package() { 339 local package="${1}" 340 local version="${2}" 341 local host="${3}" 342 local patchdir="${4}" 343 local archivedir="${5}" 344 local builddir="${6}" 345 local destdir="${7}" 346 local fqpackage="${package}-${version}" 347 local curdir=`pwd` 348 local archive 349 350 verbose " CHECK ${package}" 351 352 archive="`find_versioned_or_nonverioned_archive ${archivedir} ${package} ${version} ${EXTENSIONS}`" 353 354 if [ -z "${archive}" ]; then 355 error "Could not find an archive for ${package}." 356 exit 1 357 fi 358 359 if [ ! -d "${archivedir}/${fqpackage}" ]; then 360 verbose " TAR ${archive}" 361 tar --directory "${archivedir}" -xf "${archive}" || exit ${?} 362 fi 363 364 # If necessary, patch the expanded package. 365 366 if [ -d "${patchdir}" ]; then 367 patch_directory "${archivedir}/${fqpackage}" "-s -p1" ${patchdir}/*.patch* 368 fi 369 370 # If possible, attempt to be self-sufficient, relying on GNU autotools 371 # executables installed along with the SDK itself. 372 373 if [ -d "${destdir}/${host}/bin" ]; then 374 export PATH="${destdir}/${host}/bin:${PATH}" 375 fi 376 377 if [ -d "${destdir}/bin" ]; then 378 export PATH="${destdir}/bin:${PATH}" 379 fi 380 381 export ACLOCAL=`which aclocal` 382 export AUTOCONF="`which autoconf`" 383 export AUTOHEADER="`which autoheader`" 384 export AUTOM4TE="`which autom4te`" 385 export AUTOMAKE="`which automake`" 386 export LIBTOOLIZE="`which libtoolize || which glibtoolize`" 387 export M4=`which m4` 388 389 # Establish, if necessary, some SDK-specific directories needed to 390 # override various paths in GNU autotools that otherwise expect to be 391 # absolute (e.g. /usr/share, etc.). 392 393 if [ -d "${destdir}/share" ]; then 394 if [ -d "${destdir}/share/autoconf" ]; then 395 export AC_MACRODIR="${destdir}/share/autoconf" 396 397 export autom4te_perllibdir="${destdir}/share/autoconf" 398 fi 399 400 if [ -d "${destdir}/share/automake-1.14" ]; then 401 export PERL5LIB="${destdir}/share/automake-1.14:${PERL5LIB}" 402 fi 403 fi 404 405 trap "removetmp" 1 2 3 9 15 406 407 # 408 # Generate any temporary files that need to be patched at run time 409 # with the location of the SDK tree, including: 410 # 411 # - The autom4te configuration file 412 # - The libtoolize executable script 413 # 414 415 if [ -r "${destdir}/share/autoconf/autom4te.cfg" ]; then 416 export AUTOM4TE_CFG="${destdir}/autom4te.cfg" 417 418 sed -e "s,//share/autoconf,${destdir}/share/autoconf,g" < "${destdir}/share/autoconf/autom4te.cfg" > "${AUTOM4TE_CFG}" 419 fi 420 421 if [ -r "${destdir}/${host}/bin/libtoolize" ]; then 422 export LIBTOOLIZE="${destdir}/libtoolize" 423 424 sed -e "s,//share/libtool,${destdir}/share/libtool,g" -e "s,//share/aclocal,${destdir}/share/aclocal,g" < "${destdir}/${host}/bin/libtoolize" > "${LIBTOOLIZE}" 425 426 chmod 775 "${LIBTOOLIZE}" 427 fi 428 429 # Configure the package 430 431 if [ ${VERBOSE} -gt 0 ]; then 432 CONFIGURE_FLAGS="" 433 else 434 CONFIGURE_FLAGS="--quiet" 435 fi 436 437 verbose " CONFIG ${package}" 438 439 cd "${builddir}" 440 441 ${archivedir}/${fqpackage}/configure ${CONFIGURE_FLAGS} --prefix=/ --exec-prefix=/${host} || exit ${?} 442 443 cd "${curdir}" 444 445 # Build the package 446 447 verbose " MAKE ${package}" 448 449 make V=${VERBOSE} -C "${builddir}" all || exit ${?} 450 451 # Install / stage the package 452 453 verbose " INSTALL ${package}" 454 455 make V=${VERBOSE} -C "${builddir}" DESTDIR="${destdir}" install || exit ${?} 456 457 # Remove any temporary files created. 458 459 removetmp 460} 461 462# Parse out any command line options 463 464while [ ${#} -gt 0 ]; do 465 case ${1} in 466 --arch) 467 ARCH=${2} 468 shift 2 469 ;; 470 471 -h|--help) 472 usage 0 473 ;; 474 475 --builddir) 476 BUILDDIR=${2} 477 shift 2 478 ;; 479 480 --destdir) 481 DESTDIR=${2} 482 shift 2 483 ;; 484 485 --srcdir) 486 SRCDIR=${2} 487 shift 2 488 ;; 489 490 -v|--verbose) 491 $((VERBOSE++)) 492 shift 1 493 ;; 494 495 --) 496 shift 1 497 break 498 ;; 499 500 *) 501 usage 1 502 ;; 503 esac 504done 505 506# If the architecture is not specified, fail. 507 508if [ -z "${ARCH}" ]; then 509 error "The host architecture was not specified via --arch." 510 511 usage 1 512fi 513 514# If the --builddir option wasn't specified, then provide a default. 515 516if [ -z "${BUILDDIR}" ]; then 517 BUILDDIR="`pwd`" 518fi 519 520# If the --destdir option wasn't specified, then provide a default. 521 522if [ -z "${DESTDIR}" ]; then 523 DESTDIR=${abs_top_hostdir} 524fi 525 526# If the --srcdir option wasn't specified, then provide a default. 527 528if [ -z "${SRCDIR}" ]; then 529 SRCDIR="`pwd`" 530fi 531 532# Determine what packages to build 533 534if [ ${#} -gt 0 ]; then 535 PACKAGES="${*}" 536 537else 538 PACKAGES="`cat ${SRCDIR}/packages`" 539 540fi 541 542# Build each package 543 544banner "Building GNU autotools for ${ARCH}..." 545 546for package in ${PACKAGES}; do 547 url="`cat ${SRCDIR}/${package}/${package}.url`" 548 version="`cat ${SRCDIR}/${package}/${package}.version`" 549 patchdir="${SRCDIR}/${package}/${package}.patches" 550 551 # Fetch, if necessary, the package from the canonical source location. 552 553 subbanner " CHECK ${package}" 554 555 fetch_package "${SRCDIR}/${package}" "${BUILDDIR}" "${package}" "${version}" "${url}" 556 557 # Build and install the package. 558 559 verbose " MKDIR ${BUILDDIR}/build/${ARCH}/${package}-${version}" 560 561 mkdir -p "${BUILDDIR}/build/${ARCH}/${package}-${version}" || exit ${?} 562 563 build_package "${package}" "${version}" "${ARCH}" "${patchdir}" "${BUILDDIR}" "${BUILDDIR}/build/${ARCH}/${package}-${version}" "${DESTDIR}" 564done 565 566trailer 567