#!/bin/sh set -e ## true # avoid the shell overhead of fork/exec'ing just to call /bin/true # returns true true() { : ; } ## false # avoid the shell overhead of fork/exec'ing just to call /bin/false # returns false false() { ! : ; } ## error # displays the supplied on stderr error() { echo "error: $*" >&2; } ## die # display the supplied and exit with an error die() { error "$*"; exit 1; } ## mkenv # prepare the environment structure for the current package mkenv() { for dir in "${W}" "${L}" "${E}" "${D}" "${T}"; do if [ ! -d "${dir}" ]; then mkdir -p "${dir}" fi done unset dir if [ "$#" -gt "0" ]; then cat /dev/null > "${L}/${1}.log" set > "${E}/${1}.env" fi } ## cleanup # deal with temporary junk when we exit # FIXME we need a way to universally deal w/ cleanup of junk created by # imported commands. cleanup() { test -f "${BUILDER_MAKEFILE}" && rm -f "${BUILDER_MAKEFILE}" test -p "${BUILDER_PIPE}" && rm -f "${BUILDER_PIPE}" } ## import # import a builder library. # During import a library can check 'BUILDER_CALL_STACK' to see if it equals # '__main__'. If it does, then the library is being executed directly. # Further more, builder-libraries can do load-time tests in order to perform # various one-time optimizations. # # Note: this is borrowed from 'shlib' almost verbatim w/ the only change being # the variable names. import() { set -- "${1}" "`echo "${1}" | tr '-' '_'`" test -f "${BUILDER_LIBDIR}/${1}" || die "library does not exist '${1}'" eval "test -z '\${BUILDER_IMPORT_${2}}'" || return BUILDER_CALL_STASH="${BUILDER_CALL_STACK}" BUILDER_CALL_STACK="${BUILDER_CALL_STACK} ${1}" . "${BUILDER_CALL_LIBDIR}/${1}" eval "BUILDER_IMPORT_${2}='${BUILDER_LIBDIR}/${1}" if [ -z "${BUILDER_IMPORTED}" ]; then BUILDER_IMPORTED="${1}" else BUILDER_IMPORTED="${BUILDER_IMPORTED} ${1}" fi BUILDER_CALL_STACK="${BUILDER_CALL_STASH}" } ## load_rules # load the Buildrules of a package into the current program space load_rules() { # Evaluate our environment data # There is a bit of a performance penalty here in that the query # routine will source the build-rules to finish collecting data, so we # end up sourcing the Buildrules twice. eval $(build-query --environ "${1}") RELEASE= S= # Source in the category Buildrules if [ -f "${BUILDER_PKGDIR}/${CATEGORY}/.buildrules" ]; then . "${BUILDER_PKGDIR}/${CATEGORY}/.buildrules" fi # Source in the package Buildrules . "${RULESFILE}" if [ "${CATEGORY}/${NAME}" != "${1}" ]; then die "Buildrules can not set the package name" fi if [ -z "${VERSION}" ]; then die "missing version in '${NAME}'" fi if [ -z "${DESCRIPTION}" ]; then die "missing description in '${NAME}'" fi if test -z "${RELEASE}"; then RELEASE="${VERSION#*-}" if ! test -z "${RELEASE}" && test "${RELEASE}" != "${VERSION}"; then VERSION="${VERSION%-${RELEASE}}" if test -z "${S}"; then S="${W}/${NAME}-${VERSION}-${RELEASE}" fi else RELEASE='0' fi fi if test -z "${S}"; then S="${W}/${NAME}-${VERSION}" fi } if [ ! -z "${BUILDER_DEBUG}" ]; then set -x fi ## # Check to see if we are wrapping a sub-command BUILDER_COMMAND= if [ -f "${1}" ]; then case "${1##*/}" in (build-*) BUILDER_COMMAND="${1}" shift . "${BUILDER_COMMAND}" # exit with the exit status of the last command from within the # sub-script. This is normal shell behavior, we are just # making it explicit. exit $? ;; esac fi ## # We are being called as 'build [options] '. Setup the environment # for execution of a sub-command. BUILDER_DEBUG=0 while [ "$#" -gt "0" ]; do case "$1" in (-v|-version|--version) version; exit 0;; (-d|-debug|--debug) BUILDER_DEBUG=1 set -x ;; (-h|-help|--help) shift 1 set -- help "$@" break ;; (-*) echo "error: unknown option '${1}'" >&2 echo "try '${0} help'" >&2 exit 1 ;; (*) break ;; esac shift 1 done export BUILDER_DEBUG ## # Done with arguments, time for setting up the enviroment for the build TOPDIR="${PWD}" while [ ! -z "${TOPDIR}" ]; do [ -d "${TOPDIR}/.builder" ] && break TOPDIR="${TOPDIR%/*}" done if [ -z "${TOPDIR}" ]; then echo "error: current path not in a build-tree" >&2 exit 1 fi # We are being executed as 'build ' BUILDER_CALL_STACK='__main__' export BUILDER_CALL_STACK # set the builtin defaults based on TOPDIR. We export TOPDIR as BUILDER_TOPDIR # to avoid stepping on the potential usage of TOPDIR within package Makefiles BUILDER_TOPDIR="${TOPDIR}" BUILDER_CFGDIR="${TOPDIR}/.builder" BUILDER_PKGDIR="${TOPDIR}/packages" BUILDER_SRCDIR="${TOPDIR}/sources" BUILDER_ATFDIR="${TOPDIR}/artifacts" BUILDER_LIBDIR="${TOPDIR}/scripts/libexec" BUILDER_TMPDIR="${TOPDIR}/tmp" export BUILDER_CFGDIR BUILDER_PKGDIR BUILDER_SRCDIR export BUILDER_ATFDIR BUILDER_LIBDIR BUILDER_TOPDIR export BUILDER_TMPDIR # We save the pre-config PATH as BUILDER_PATH to be used by downstream tools. # FIXME detect prefixing BUILDER_LIBDIR onto PATH multiple times? BUILDER_PATH="${BUILDER_LIBDIR}:${PATH}" PATH="${BUILDER_PATH}" export BUILDER_PATH PATH # FIXME The original idea here is to allow a "default" environment, that has a "default" # override... Basically we set some default variables, and then load the # default config, and THEN let the target config override anything set. This # is really confusing, and totally obsolted by an 'include' option in the configs. test -f "${BUILDER_CFGDIR}/config" && . "${BUILDER_CFGDIR}/config" BUILDER_CONFIG="${BUILDER_CONFIG:-config}" if [ "${BUILDER_CONFIG}" != 'config' ]; then if [ ! -f "${BUILDER_CFGDIR}/${BUILDER_CONFIG}" ]; then die "invalid config '${BUILDER_CONFIG}'" fi . "${BUILDER_CFGDIR}/${BUILDER_CONFIG}" fi export BUILDER_CONFIG # FIXME MAKE_OPTS should default to #CPUS + 1, until we can detect #CPUS, we # just set it to 2 for uni-processor systems. MAKE_OPTS="${MAKE_OPTS:--j2}" export MAKE_OPTS # Default build target # FIXME this should default to all/all TARGET="${TARGET:-all/all}" export TARGET # If unspecified go ahead and ask gcc CBUILD="${CBUILD:-$(build-dumpmachine)}" export CBUILD ARCHIVE_FORMAT="${ARCHIVE_FORMAT:-tar.bz2}" export ARCHIVE_FORMAT # FIXME this stuff needs to be detected in a more reliable fashion ARCH="${ARCH:-$(uname -m)}" export ARCH CHOST="${CHOST:-${CBUILD}}" export CHOST # if we aren't given an action then we do everything ACTION="install" if [ "$#" -gt "0" ]; then ACTION="${1}" shift 1 fi if command -v "build-make-${ACTION}" 2>&1 > /dev/null; then BUILDER_COMMAND="$(command -v 'build-make')" set -- "${ACTION}" "${@}" elif command -v "build-${ACTION}" 2>&1 > /dev/null; then BUILDER_COMMAND="$(command -v "build-${ACTION}")" else error "unknown action '${ACTION}'" echo "try '${0} help'" >&2 exit 1 fi export BUILDER_COMMAND exec "${BUILDER_COMMAND}" "${@}"