diff options
Diffstat (limited to 'src/opkbuild.sh')
-rw-r--r-- | src/opkbuild.sh | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/src/opkbuild.sh b/src/opkbuild.sh new file mode 100644 index 0000000..faa72ef --- /dev/null +++ b/src/opkbuild.sh @@ -0,0 +1,258 @@ +#! /bin/sh +# +# opkhelper +# src/opkbuild +# Build opkg packages. +# +# Copyright (C) 2012 Patrick "P. J." McDermott +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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, see <http://www.gnu.org/licenses/>. + +. @@LIBDIR@@/opkhelper/controlfields +. @@LIBDIR@@/opkhelper/architecture +. @@LIBDIR@@/opkhelper/archive + +print_usage() +{ + printf 'Usage: %s [-r assume-uid0-cmd] [-p target-platform] [-d]\n' "${1}" +} + +error() +{ + [ ${#} -eq 1 ] && printf 'opkbuild: [%s] Error\n' "${1}" >&2 + if ${dbg}; then + printf 'opkbuild: Starting debugging shell...\n' >&2 + /bin/sh + fi + cd .. + rm -Rf tmp 2> /dev/null + exit 1 +} + +opts=$(getopt -n "${0}" -o 'r:p:d' -- "${@}") +if [ ${?} -ne 0 ]; then + print_usage "${0}" >&2 + exit 1; +fi +eval set -- "${opts}" +while true; do + case "${1}" in + -r) + uid0_cmd=${2} + shift 2 + ;; + -p) + platform=${2} + shift 2 + ;; + -d) + dbg=true + shift + ;; + --) + shift + break + ;; + *) + print_usage "${0}" >&2 + exit 1 + ;; + esac +done + +if [ -z "${uid0_cmd}" ]; then + uid0_cmd=fakeroot +fi +${uid0_cmd} true +if [ ${?} -ne 0 ]; then + printf 'opkbuild: Error running command to gain UID 0\n' >&2 + exit 1 +fi +if [ -z "${dbg}" ]; then + dbg=false +fi + +# Sanity checks. +printf 'opkbuild: Checking for sanity...\n' +if [ ! -f format -o ! -f build -o ! -f control ]; then + printf 'Error: Current working directory is not a source package.\n' >&2 + exit 1 +fi +if [ "$(cat format)" != '1.0' ]; then + printf 'Error: Source package is of an incompatible version.\n' >&2 + exit 1 +fi + +# Attempt to detect the target platform. +# If there no config files to copy, build platform-independent packages. +if [ ! -f config ]; then + platform='' +# If a target platform was not specified ... +elif [ -z "${platform}" ]; then + platform=$(opkg print-architecture | \ + sed -n 's/^arch \([^ -][^ -]*\) [0-9][0-9]*$/\1/p' | \ + grep -v 'all') + # ... and there are config files and zero installable platforms, fail. + if [ -z "${platform}" ]; then + printf 'opkbuild: Error: %s\n' \ + 'Building platform-dependent package and no platforms detected' >&2 + exit 1 + # ... and there are config files and multiple installable platforms, request + # explicit selection. + elif [ $(echo "${platform}" | wc -l) -gt 1 ]; then + printf 'opkbuild: Error: %s\n' \ + 'Multiple platforms found while detecting target' >&2 + exit 1 + fi + # ... and there are config files and one installable platform, build for it. +fi + +# Attempt to detect the target architecture tuple. +# NB: Currently cross-compiling is not supported. +arch=$(opkg print-architecture | sed -n \ + 's/^arch \([^ -][^ -]*-[^ -][^ -]*-[^ -][^ -]*\) [0-9][0-9]*$/\1/p') +if [ -z "${arch}" ]; then + printf 'opkbuild: Error: No installable architecture found\n' >&2 +elif [ $(echo "${arch}" | wc -l) -gt 1 ]; then + printf 'opkbuild: Error: Multiple installable architectures found\n' >&2 +fi + +# Make work area. +printf 'opkbuild: Making work area...\n' +mkdir tmp +cd tmp + +# Get source package name and version. +printf 'opkbuild: Reading source package control fields...\n' +srcpkg=$(oh_get_field Source) +version=$(oh_get_field Version) + +# Set environment variables for the build configuration. +export OH_PLATFORM="${platform}" +export OH_ARCH="${arch}" +IFS=- read OH_ARCH_CPU OH_ARCH_KERNEL OH_ARCH_LIBS <<EOF +${OH_ARCH} +EOF +export OH_ARCH_CPU OH_ARCH_KERNEL OH_ARCH_LIBS +export OH_SRCPKG="${srcpkg}" +export OH_PKGVER=${version} + +# Set build flags. +. @@DATADIR@@/opkhelper/buildflags/${OH_ARCH_CPU} + +# Check build dependencies. +oh-checkbuilddeps || error "${srcpkg}-src" + +printf '\n' + +# Build *-src package. +printf 'opkbuild: Attempting to build package "%s"...\n' "${srcpkg}-src" +printf 'opkbuild: Installing files for package "%s"...\n' "${srcpkg}-src" +${uid0_cmd} mkdir -p ${srcpkg}-src.data/usr/src/${srcpkg}_${version} || + error "${srcpkg}-src" +for file in ../*; do + case ${file} in + ../tmp) + ;; + ../*) + ${uid0_cmd} cp -R ${file} \ + ${srcpkg}-src.data/usr/src/${srcpkg}_${version} || + error "${srcpkg}-src" + ;; + esac +done +( ${uid0_cmd} oh-gencontrol -s;) || error "${srcpkg}-src" +( ${uid0_cmd} oh-buildopk -s;) || error "${srcpkg}-src" +( ${uid0_cmd} rm -Rf ${srcpkg}-src.data;) || error "${srcpkg}-src" +printf 'opkbuild: Package "%s" complete!\n\n' "${srcpkg}-src" + +# Build other binary packages. +for binpkgdir in ../*.pkg/; do + binpkg=${binpkgdir#'../'} + binpkg=${binpkg%'.pkg/'} + export OH_BINPKG="${binpkg}" + # Check architecture. + oh_is_buildable "${binpkg}" + if [ ${?} -eq 0 ]; then + printf 'opkbuild: Attempting to build package "%s"...\n' "${binpkg}" + # Copy or extract software sources to src. + if [ -d ../src ]; then + printf 'opkbuild: Copying sources into work area...\n' + cp -Rp ../src src || error "${binpkg}" + else + printf 'opkbuild: Extracting sources into work area...\n' + oh_archive_extract_source + case ${?} in + 1) + printf 'opkbuild: Error: No source archive found\n' >&2 + error + ;; + 2) + printf 'opkbuild: Error: Multiple source archives found\n' \ + >&2 + error + ;; + 3) + printf 'opkbuild: Error: %s\n' \ + 'Unsupported archive compression format detected' >&2 + error + ;; + 4) + printf 'opkbuild: Error: %s\n' \ + 'No directories found in source archive' >&2 + error + ;; + 5) + printf 'opkbuild: Error: %s\n' \ + 'Multiple top-level directories found in source archive' >&2 + error + ;; + 6) + printf 'opkbuild: Error: %s\n' \ + 'Failed to extract source archive' >&2 + error + ;; + 7) + printf 'opkbuild: Error: %s\n' \ + 'Failed to move extracted sources' >&2 + error + ;; + esac + fi + # Make installation directory. + # TODO: Maybe this should be an FHS-compliant filesystem hierarchy. + mkdir dest || error "${binpkg}" + # Apply patches. + oh-applypatches + # Copy platform config files. + oh-copyconfig || error "${binpkg}" + # Build the package. + ${uid0_cmd} ../build ${binpkg} || error "${binpkg}" + printf 'opkbuild: Package "%s" complete!\n\n' "${binpkg}" + # Clean up everything except the build stamps. + for file in *; do + case ${file} in + *.buildstamp) + ;; + *) + ${uid0_cmd} rm -Rf ${file} || error "${binpkg}" + ;; + esac + done + fi +done + +# Clean up tmp. +cd .. +rm -Rf tmp |