#!/bin/bash ########################################################################################### # spb-build - Source Package Builder :: Package Assembler # 0.1.x - James Linden - Initial version based on pkgbuilder # 0.2.x - James Linden - switches for building i386 compatible # 0.3.x - James Linden - configuration options for compile flags # 0.4.x - James Linden - Renamed to spb-build # 0.5.x - James Linden - Customizations for koreos build # 0.6.x - James Linden - Optional build type / build scope variables # 0.7.x - James Linden - Cleanup and enhancements # 0.8.x - James Linden - Modifications for Prime GNU/Linux ########################################################################################## # This script's current version SCRIPT_NAME="spb-build" SCRIPT_VERSION="0.8.4" # Current date/time function edate() { echo $(date "+%Y-%m-%d %H:%M") } # Color prompts function (yellow) function cecho() { printf "\033[1;34m%s\033[0m> \033[1;33m%s\033[0m\n" "`edate`" "$@" } # Color prompts function (red) function eecho() { printf "\033[1;34m%s\033[0m> \033[1;31m%s\033[0m\n" "`edate`" "$@" } # Output script info function cp_info() { cat << EOF ${SCRIPT_NAME} ${SCRIPT_VERSION} Copyright 2007-2008 James Linden Released under the GNU GPL ver 2.0 EOF } # Output usage info function cp_usage() { cat << EOF Usage: ${SCRIPT_NAME} [options] General Options: -h --help Show this help message --version Show version number --pkgname Package name --pkgversion Package version --pkgtype Package type --release Package release --auto Skip failsafe check !! WARNING WILL ROBINSON !! --test Compile only (do not create package) EOF } function cp_license() { cat << EOF This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. EOF } ################################################################################ # Section: Configuration ################################################################################ LOCAL_NAME="" LOCAL_VERS="" LOCAL_ROOT="$(pwd)" LOCAL_BUILDROOT="${LOCAL_ROOT}/tmp/build" LOCAL_HOST="build.prime-linux.org" LOCAL_AUTO="0" LOCAL_TEST="0" CFG_NAME="" CFG_VERSION="" CFG_RELEASE="" CFG_DESC="" CFG_LICENSE="" CFG_GROUP="" CFG_URL="" CFG_HOME="" CFG_PACKAGER="" CFG_SOURCE="" CFG_BUILD="" CFG_BUILDTMP="0" CFG_BUILDVERS="$(date +%Y%m%d.%H%M)" CFG_ARCH="i686" CFG_TYPE="default" CFG_FLAGC="" CFG_FLAGCPP="" CFG_FLAGCXX="" BC_CMD="bc -q" # Type level options DIRTOOLS="/build/tools" DIRBIN="/bin" DIRETC="/etc" DIRLIB="/lib" DIRVAR="/var" DIRUSR="/usr" DIRSBIN="/sbin" DIRTMP="/tmp" DIRJUNK="/junk" DIRMAN="/usr/man" DIRSHARE="/usr/share" DIRINFO="/usr/share/info" DIRLOG="/var/log" DIRBOOT="/boot" DIRHOME="/home" PKG_PREFIX="" PKG_SUFFIX="tar.bz2" PKG_COMPRESS="bz" PKG_BUILDFILE_PATH="etc/prime/" PKG_INCLUDE_SPB="1" # Repo level options REPO_URL="" REPO_PACKAGER="" REPO_ARCH="" ################################################################################ # Section: Command line options ################################################################################ SCRIPT_SELF=$(basename "$0") SCRIPT_ARGS=$(getopt -a -n ${SCRIPT_SELF} -o +h -l help,version,pkgname:,pkgversion:,pkgtype:,release:,auto:,test: -- "$@") eval set -- $SCRIPT_ARGS while [ "$1" != "--" ]; do case "$1" in -h|--help) cp_usage exit 0 ;; --version) shift cp_info exit 0 ;; --pkgname) shift LOCAL_NAME="$(echo $1)" ;; --pkgversion) shift LOCAL_VERS="$(echo $1)" ;; --pkgtype) shift CFG_TYPE="$(echo $1)" ;; --release) shift CFG_RELEASE="$(echo $1)" ;; --auto) shift LOCAL_AUTO="1" ;; --test) shift LOCAL_TEST="1" ;; esac shift done if [ -z "${LOCAL_NAME}" ]; then eecho "--pkgname missing" exit 1 fi if [ -z "${LOCAL_VERS}" ]; then eecho "--pkgversion missing" exit 1 fi ################################################################################ # Section: Load type build option configuration ################################################################################ RC_TYPE="${LOCAL_ROOT}/build/${CFG_TYPE}.conf" if ! [ -f "${RC_TYPE}" ]; then eecho "Unable to locate ${RC_TYPE}!" exit 1 fi source ${RC_TYPE} ################################################################################ # Section: Load package specific configuration ################################################################################ LOCAL_PATH_RC="${LOCAL_ROOT}/build/${LOCAL_NAME}" RC_PKG="${LOCAL_PATH_RC}/package.conf" if ! [ -f "${RC_PKG}" ]; then eecho "Unable to locate ${RC_PKG}!" exit 1 fi source ${RC_PKG} RC_BLD="${LOCAL_PATH_RC}/${LOCAL_VERS}/${CFG_TYPE}.conf" if ! [ -f "${RC_BLD}" ]; then eecho "Unable to locate ${RC_BLD}!" exit 1 fi source ${RC_BLD} CFG_SOURCE="${LOCAL_ROOT}/source/${CFG_SOURCE}" ################################################################################ # Section: Check files and directories ################################################################################ if ! [ -d ${LOCAL_BUILDROOT} ]; then mkdir -p ${LOCAL_BUILDROOT} fi if ! [ -f ${CFG_SOURCE} ]; then eecho "Unable to find specified source package:" echo " ${CFG_SOURCE}" exit 1 fi PKG_BASENAME="${CFG_NAME}-${CFG_VERSION}" TMP_DIR="${LOCAL_BUILDROOT}/${CFG_RELEASE}/${PKG_BASENAME}" DESTDIR_PATH="${TMP_DIR}/target" ################################################################################ # Section: String replacement for commands ################################################################################ TMP_BUILD="${CFG_BUILD}" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@BUILD|${LOCAL_PATH_RC}/${LOCAL_VERS}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@CUSTOM|${LOCAL_PATH_RC}/custom|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@TARGET|${DESTDIR_PATH}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@NAME|${CFG_NAME}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@ARCH|${REPO_ARCH}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@VERSION|${CFG_VERSION}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@RELEASE|${CFG_RELEASE}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@TOOLS|${DIRTOOLS}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@SOURCE|${LOCAL_ROOT}/source|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@TEMP|${TMP_DIR}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRJUNK|${DIRJUNK}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRLIB|${DIRLIB}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRBIN|${DIRBIN}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRETC|${DIRETC}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRUSR|${DIRUSR}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRVAR|${DIRVAR}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRTMP|${DIRTMP}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRMAN|${DIRMAN}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRSBIN|${DIRSBIN}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRLOG|${DIRLOG}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRINFO|${DIRINFO}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRSHARE|${DIRSHARE}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRBOOT|${DIRBOOT}|g")" TMP_BUILD="$(echo ${TMP_BUILD} | sed "s|@DIRHOME|${DIRHOME}|g")" CFG_BUILD="${TMP_BUILD}" TMP_BUILD="$(echo ${CFG_BUILD} | sed 's/ && / \&\& \\\n /g')" ################################################################################ # Section: Output a snapshot of current configuration ################################################################################ clear cat << EOF Current configuration: Package metadata: Name: [${CFG_NAME}] Version: [${CFG_VERSION}] Summary: [${CFG_DESC}] License: [${CFG_LICENSE}] Group: [${CFG_GROUP}] URL: [${CFG_URL}] Home: [${CFG_HOME}] Packager: [${CFG_PACKAGER}] Host: [${LOCAL_HOST}] Build: [${CFG_BUILDVERS}] Arch: [${CFG_ARCH}] Release: [${CFG_RELEASE}] Type: [${CFG_TYPE}] Package build options: Build temp: [${CFG_BUILDTMP}] Source: [${CFG_SOURCE}] Temp dir: [${LOCAL_BUILDROOT}] Flags: C [${CFG_FLAGC}] CPP [${CFG_FLAGCPP}] CXX [${CFG_FLAGCXX}] Commands: [${TMP_BUILD}] EOF ################################################################################ # Section: Chance to exit before anything happens ################################################################################ if [ "${LOCAL_AUTO}" = 0 ]; then echo eecho "This is your last chance to exit before you really FUBAR everything!" echo cecho "Press [ENTER] to destroy the planet or [CTRL-C] to save yourself." USERPAUSE=foo while [ "$USERPAUSE" ]; do read USERPAUSE done else echo fi ################################################################################ # Section: Setup temporary build location ################################################################################ if [ -d ${TMP_DIR} ]; then rm -fr ${TMP_DIR} fi mkdir -p ${TMP_DIR} PACKAGE_LOG="${TMP_DIR}/${SCRIPT_NAME}.log" ################################################################################ # Section: Unpack the source file ################################################################################ cecho "Unpacking source file:" echo " ${CFG_SOURCE}" tar -C "${TMP_DIR}" -xf "${CFG_SOURCE}" WORK_PATH="" # figure out the directory name that was unpacked for f in $(ls ${TMP_DIR}/); do if [ -d "${TMP_DIR}/${f}" ]; then WORK_PATH="${f}" fi done ################################################################################ # Section: Create package build directory ################################################################################ if [ "${CFG_BUILDTMP}" = 1 ]; then EXECDIR_PATH="${TMP_DIR}/build" mkdir -p ${EXECDIR_PATH} fi ################################################################################ # Section: Create package target directory ################################################################################ mkdir -p ${DESTDIR_PATH} ################################################################################ # Section: Generate build execution script ################################################################################ cecho "Generating build script:" FIX_MAKEINSTALL="$(echo "${CFG_BUILD}" | sed "s|make install|make DESTDIR=${DESTDIR_PATH} install|g")" if [ "$(echo "${CFG_BUILD}" | grep 'configure')" ]; then if [ "${CFG_BUILDTMP}" = 0 ]; then COMPILE_PATH="${TMP_DIR}/${WORK_PATH}" FULL_BUILD="./${FIX_MAKEINSTALL}" else COMPILE_PATH="${EXECDIR_PATH}" FULL_BUILD="../${WORK_PATH}/${FIX_MAKEINSTALL}" fi else COMPILE_PATH="${TMP_DIR}/${WORK_PATH}" FULL_BUILD="${FIX_MAKEINSTALL}" fi EXEC_SCRIPT=${TMP_DIR}/${SCRIPT_NAME}-exec echo " ${EXEC_SCRIPT}" cat > $EXEC_SCRIPT << EOF #!/bin/bash export LANG="C" export CFLAGS+="${CFG_FLAGC}" export CPPFLAGS+="${CFG_FLAGCPP}" export CXXFLAGS+="${CFG_FLAGCXX}" cd "${COMPILE_PATH}" ${CFG_PREBUILD} ${FULL_BUILD} # Report outcome if [ \$? -eq 0 ]; then exit 0 else exit 1 fi EOF chmod 700 ${EXEC_SCRIPT} ################################################################################ # Section: Run specified commands ################################################################################ cecho "Building source with:" echo " ${FULL_BUILD}" EXEC_START=$(date +%s) $EXEC_SCRIPT &> ${PACKAGE_LOG} INSTALL_FAILED=$? EXEC_STOP=$(date +%s) unset LD_PRELOAD if [ $INSTALL_FAILED -gt 0 ]; then echo eecho "Build appears to have failed. Aborting." eecho "Check ${PACKAGE_LOG} for more information" exit 1 fi ################################################################################ # Section: Calculate execution run time ################################################################################ TIME_SECS="$(echo "${EXEC_STOP}-${EXEC_START}" | ${BC_CMD})" TIME_MINS="0" TIME_HRS="0" if [ "$(echo "${TIME_SECS} > 59" | ${BC_CMD})" = "1" ]; then TIME_MINS="$(echo "${TIME_SECS}/60" | ${BC_CMD})" TIME_SECS="$(echo "${TIME_SECS}-(${TIME_MINS}*60)" | ${BC_CMD})" fi if [ "$(echo "${TIME_MINS} > 59" | ${BC_CMD})" = "1" ]; then TIME_HRS="$(echo "${TIME_MINS}/60" | ${BC_CMD})" TIME_MINS="$(echo "${TIME_MINS}-(${TIME_HRS}*60)" | ${BC_CMD})" fi TIME_TXT="Build completed in" if [ ${TIME_HRS} -gt 0 ]; then TIME_TXT="${TIME_TXT} ${TIME_HRS} hour(s)"; fi if [ ${TIME_MINS} -gt 0 ]; then TIME_TXT="${TIME_TXT} ${TIME_MINS} minute(s)"; fi if [ ${TIME_SECS} -gt 0 ]; then TIME_TXT="${TIME_TXT} ${TIME_SECS} second(s)"; fi cecho "${TIME_TXT}" ################################################################################ # Section: Cleanup junk location ################################################################################ cecho "Cleaning up junk..." rm -fr ${DESTDIR_PATH}${DIRJUNK} ################################################################################ # Section: Generate file list ################################################################################ cecho "Generating file list..." find ${DESTDIR_PATH}/* | uniq | grep -v '\.svn' > ${TMP_DIR}/newfiles ################################################################################ # Section: Generate .spb file ################################################################################ cecho "Creating description file..." SPB_BUILD="${PKG_BASENAME}+${CFG_BUILDVERS}+${PKG_PREFIX}.${CFG_ARCH}.spb" SPB_DESC="${TMP_DIR}/${SPB_BUILD}" cat > ${SPB_DESC} << EOF # Source Package Builder # generated by ${SCRIPT_NAME} ${SCRIPT_VERSION} name: ${CFG_NAME} version: ${CFG_VERSION} group: ${CFG_GROUP} license: ${CFG_LICENSE} url: ${CFG_URL} website: ${CFG_HOME} packager: ${CFG_PACKAGER} summary: ${CFG_DESC} date: $(date --utc) host: ${LOCAL_HOST} build: ${CFG_BUILDVERS} arch: ${CFG_ARCH} release: ${CFG_RELEASE} type: ${CFG_TYPE} EOF echo "bcmd: $(echo ${CFG_BUILD} | sed 's/ && /\nbcmd: /g')" >> ${SPB_DESC} echo >> ${SPB_DESC} ################################################################################ # Section: Collate package contents ################################################################################ cecho "Collating package..." for item in $(cat ${TMP_DIR}/newfiles); do targ=$(dirname ${item}) bfile="${item}" if [ "${DESTDIR_PATH}" ]; then targ=$(echo $targ | sed "s|^$DESTDIR_PATH||") bfile=$(echo $bfile | sed "s|^$DESTDIR_PATH||") fi if [ -f ${item} ]; then echo "file: ${bfile}" >> ${SPB_DESC} elif [ -d ${item} ]; then echo "mkdir: ${bfile}" >> ${SPB_DESC} fi done ################################################################################ # Section: Include SPB file ################################################################################ if [ "${PKG_INCLUDE_SPB}" = "1" ]; then if ! [ -d "${DESTDIR_PATH}/${PKG_BUILDFILE_PATH}" ]; then mkdir -p ${DESTDIR_PATH}/${PKG_BUILDFILE_PATH} fi echo "file: /${PKG_BUILDFILE_PATH}${SPB_BUILD}" >> ${SPB_DESC} cp ${SPB_DESC} ${DESTDIR_PATH}/${PKG_BUILDFILE_PATH}/ fi ################################################################################ # Section: Strip ################################################################################ cecho "Stripping package contents..." for f in $(find ${DESTDIR_PATH}/* -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 \)); do INFO="$(file ${f})" if [ "$(echo "${INFO}" | grep 'LSB executable')" ]; then strip --strip-unneeded $f elif [ "$(echo "${INFO}" | grep 'LSB shared object')" ]; then strip --strip-debug $f fi done ################################################################################ # Section: Adjust permissions ################################################################################ cecho "Adjusting permissions" for f in $(find ${DESTDIR_PATH}/* -name *.[1-8] | grep '/usr/man'); do chmod 644 $f done ################################################################################ # Section: Quit here if --test ################################################################################ if [ "${LOCAL_TEST}" = "1" ]; then exit 0 fi ################################################################################ # Section: Build final package ################################################################################ cecho "Building package..." PKG_FILENAME="${TMP_DIR}/${PKG_BASENAME}+${CFG_BUILDVERS}+${PKG_PREFIX}.${CFG_ARCH}.${PKG_SUFFIX}" chmod 0644 ${SPB_DESC} if [ "${PKG_COMPRESS}" = "bz" ]; then tar -C ${DESTDIR_PATH} -cpjf ${PKG_FILENAME} ./ elif [ "${PKG_COMPRESS}" = "gz" ]; then tar -C ${DESTDIR_PATH} -cpzf ${PKG_FILENAME} ./ fi ################################################################################ # Section: Relocate files ################################################################################ cecho "Relocating files..." REL_PATH="${LOCAL_ROOT}/package/${PKG_PREFIX}-${CFG_RELEASE}/${LOCAL_NAME}" if ! [ -d "${REL_PATH}" ]; then mkdir -p ${REL_PATH} fi cp -f ${SPB_DESC} ${REL_PATH}/ cp -f ${PKG_FILENAME} ${REL_PATH}/ cecho "Package build complete." echo exit 0