mirror of
https://github.com/archlinuxarm/PKGBUILDs.git
synced 2024-11-08 22:45:43 +00:00
429 lines
12 KiB
Bash
Executable file
429 lines
12 KiB
Bash
Executable file
#! /bin/bash
|
|
|
|
# Default values.
|
|
DEFAULT_MIRROR='http://hiciu.rootnode.net/arch-arm'
|
|
|
|
# Command line options and default values.
|
|
DEBUG='n'
|
|
SUDO='y'
|
|
HELP='n'
|
|
BUILD='n'
|
|
CHROOT='n'
|
|
# ARCH can be specified on the command line. Otherwise we'll guess.
|
|
ARCH='i686'
|
|
# Which groups and additional packages are to install.
|
|
TARGETS=()
|
|
# PACMAN_EXTRA takes extra flags passed to pacman. No checking is done.
|
|
PACMAN_EXTRA=''
|
|
|
|
# Default values of command line arguments.
|
|
DESTDIR=''
|
|
MIRROR=''
|
|
|
|
# Prints the help message, optionally using its first argument as script name.
|
|
printHelp() {
|
|
test -z "$1" && 1='archOnFr'
|
|
|
|
echo "$1 [-a arch] [-s] [-n] [-d] [-t TARGETS] DESTDIR [MIRROR]"
|
|
echo "$1 -b [-a arch] [-s] [-n] [-d] [-t TARGETS] DESTDIR [MIRROR]"
|
|
echo "$1 -e [-s] [-d] DIR"
|
|
echo "$1 -h"
|
|
echo
|
|
echo "In the first form $1 installs the base system suited to run on the smart phone"
|
|
echo "to DESTDIR optionally using a different mirror for the packages instead of the"
|
|
echo "default."
|
|
echo
|
|
echo "In the second form a build system is installed to DESTDIR optionally using a"
|
|
echo "different mirror. The build system is suited to run on the host pc to develop"
|
|
echo "Arch Mobile."
|
|
echo
|
|
echo "In the third form $1 enters the development environment given at DESTDIR."
|
|
echo
|
|
echo "In the fourth form this help message is printed."
|
|
echo
|
|
echo "OPTIONS"
|
|
echo " -a --arch=[i686|x86_64]"
|
|
echo " host system's architecture"
|
|
echo " -d --debug"
|
|
echo " print debug messages"
|
|
echo " -h --help"
|
|
echo " prints this help message"
|
|
echo " -p --extra=flags"
|
|
echo " add flags to pacman's flags when calling (use with care!)"
|
|
echo " -s --nosudo"
|
|
echo " don't use sudo for pacman calls (needs root previleges)"
|
|
echo " -t --targets=TARGETS"
|
|
echo " install TARGETS which might be groups or packages explicitly."
|
|
echo " (Default: base)"
|
|
echo
|
|
echo "EXAMPLES"
|
|
echo " $1 /media/card http://hiciu.rootnode.net/arch-arm"
|
|
echo " $1 /media/card file:///home/harlekin/archpkgs"
|
|
}
|
|
|
|
# Check if we are already able to interpret ARM binaries and configure the
|
|
# the kernel if we are not. Expects mount call and echo call as arguments.
|
|
binfmt_mount() {
|
|
MOUNT_CALL="$1"
|
|
ECHO_CALL="$2"
|
|
|
|
debug "Checking for binfmt_misc."
|
|
if [ ! -e /proc/sys/fs/binfmt_misc/register ]; then
|
|
debug "binfmt_misc not mounted."
|
|
|
|
debug "$MOUNT_CALL -t binfmt_misc none /proc/sys/fs/binfmt_misc"
|
|
$MOUNT_CALL -t binfmt_misc none /proc/sys/fs/binfmt_misc &>/dev/null
|
|
test $? -ne 0 && \
|
|
error "Failed to mount binfmt_misc."
|
|
fi
|
|
if [ ! -f /proc/sys/fs/binfmt_misc/arm ]; then
|
|
debug "$ECHO_CALL ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-static-arm:' > /proc/sys/fs/binfmt_misc/register"
|
|
$ECHO_CALL ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-static-arm:' > /proc/sys/fs/binfmt_misc/register
|
|
test $? -ne 0 && \
|
|
error "Failed to write ARM binary information to binfmt_misc/register."
|
|
|
|
debug "binfmt_misc successfully created and configured."
|
|
fi
|
|
}
|
|
|
|
debug() {
|
|
test "$DEBUG" = "y" && echo "debug: $1"
|
|
}
|
|
|
|
error() {
|
|
echo "error: $1"
|
|
doCleanup
|
|
exit 1
|
|
}
|
|
|
|
# Script for cleaning up all temporary files and reverting temporary changes
|
|
# (such as mounting) even if an error occurs. Takes an array as first argument
|
|
# which consists of the affected file, prefixed with the action.
|
|
# F:foo will remove the file foo
|
|
# D:bar will remove the directory bar recursively
|
|
# M:baz will un-mount bar
|
|
doCleanup() {
|
|
test ${#CLEANUP} -eq 0 && debug "Nothing to clean up."
|
|
|
|
debug "Cleaning up..."
|
|
for target in ${CLEANUP[*]}; do
|
|
action="${target:0:2}"
|
|
target="${target#?:}"
|
|
case "$action" in
|
|
F:)
|
|
debug "Removing file $target."
|
|
rm -f "$target"
|
|
;;
|
|
D:)
|
|
debug "Removing directory $target."
|
|
rm -rf "$target"
|
|
;;
|
|
M:)
|
|
debug "Unmounting $target."
|
|
if [ "$SUDO" = 'y' ]; then
|
|
sudo umount "$target"
|
|
else
|
|
umount "$target"
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Print help if called without arguments and exit with error condition.
|
|
test $# -eq 0 && HELP='y!'
|
|
|
|
while [ $# -ne 0 ]; do
|
|
case "$1" in
|
|
--arch=*)
|
|
ARCH="${1#--arch=}"
|
|
;;
|
|
-a|--arch)
|
|
shift
|
|
ARCH="$1"
|
|
;;
|
|
-b|--build)
|
|
test $CHROOT = y && \
|
|
error "Command line option --build conflicts with --enter."
|
|
BUILD='y'
|
|
;;
|
|
-e|--enter)
|
|
test $BUILD = y && \
|
|
error "Command line option --enter conflicts with --build."
|
|
CHROOT='y'
|
|
;;
|
|
-h|--help)
|
|
HELP='y'
|
|
;;
|
|
--extra=)
|
|
PACMAN_EXTRA="${1#--extra=}"
|
|
;;
|
|
-p|--extra)
|
|
shift
|
|
PACMAN_EXTRA="$1"
|
|
;;
|
|
-d|--debug)
|
|
DEBUG='y'
|
|
;;
|
|
-s|--nosudo)
|
|
SUDO='n'
|
|
;;
|
|
--targets=)
|
|
TARGETS=(${TARGETS[*]} "${1#--targets=}")
|
|
;;
|
|
-t|--targets)
|
|
shift
|
|
TARGETS=(${TARGETS[*]} "$1")
|
|
;;
|
|
-*)
|
|
error "Unrecognized command line option $1."
|
|
exit 1
|
|
;;
|
|
*)
|
|
if [ -z "$DESTDIR" ]; then
|
|
DESTDIR="$1"
|
|
else
|
|
if [ -z "$MIRROR" ]; then
|
|
MIRROR="$1"
|
|
else
|
|
error "Unrecognized command line argument $1."
|
|
fi
|
|
fi
|
|
;;
|
|
esac; shift
|
|
done
|
|
|
|
# Print help message if requested or set because of invalied command line
|
|
# arguments.
|
|
if [ "$HELP" = 'y!' ]; then
|
|
printHelp "$(basename $0)"
|
|
exit 1
|
|
elif [ "$HELP" = 'y' ]; then
|
|
printHelp "$(basename $0)"
|
|
exit 0
|
|
fi
|
|
|
|
if [ -z "$ARCH" ]; then
|
|
debug "ARCH = ?"
|
|
else
|
|
debug "ARCH = $ARCH"
|
|
fi
|
|
debug "BUILD = $BUILD"
|
|
debug "FORCE = $FORCE"
|
|
debug "NODEPS = $NODEPS"
|
|
debug "SUDO = $SUDO"
|
|
debug "DESTDIR = $DESTDIR"
|
|
debug "CHROOT = $CHROOT"
|
|
if [ -z "${TARGETS[*]}" ]; then
|
|
debug "TARGETS = base"
|
|
else
|
|
debug "TARGETS = ${TARGETS[*]}"
|
|
fi
|
|
if [ -z "$MIRROR" ]; then
|
|
debug "MIRROR = $DEFAULT_MIRROR"
|
|
else
|
|
debug "MIRROR = $MIRROR"
|
|
fi
|
|
debug "PATH = $PATH"
|
|
debug "PACMAN_EXTRA = $PACMAN_EXTRA"
|
|
|
|
# Check for root privileges
|
|
test $SUDO = 'n' -a "$UID" -ne 0 && \
|
|
error "Need root privileges for pacman call or don't specify --nosudo."
|
|
|
|
# If we are using sudo we should check if it is installed.
|
|
debug "Checking for sudo."
|
|
if [ $SUDO = y ]; then
|
|
SUDO_CALL="$(which sudo 2>/dev/null)"
|
|
test $? -ne 0 && \
|
|
error "sudo couldn't be found on your system. Please install and configure it or use --nosudo and run as root."
|
|
fi
|
|
debug "sudo found as $SUDO_CALL."
|
|
|
|
# Set current working directory since we might change the directory
|
|
STARTDIR="$(pwd)"
|
|
test $? -ne 0 && error "Failed to obtain the current working directory."
|
|
|
|
# Check if DESTDIR is set
|
|
test -z "$DESTDIR" && error "DESTDIR not set."
|
|
|
|
# Prepare mount, echo and chroot calls.
|
|
MOUNT_CALL='mount'
|
|
ECHO_CALL='echo'
|
|
CHROOT_CALL='chroot'
|
|
|
|
test $SUDO = y && MOUNT_CALL="$SUDO_CALL $MOUNT_CALL"
|
|
test $SUDO = y && ECHO_CALL="$SUDO_CALL $ECHO_CALL"
|
|
test $SUDO = y && CHROOT_CALL="$SUDO_CALL $CHROOT_CALL"
|
|
|
|
# Entering buildsystem
|
|
if [ $CHROOT = y ]; then
|
|
debug "Entering build system."
|
|
|
|
binfmt_mount "$MOUNT_CALL" "$ECHO_CALL"
|
|
|
|
debug "$CHROOT_CALL $DESTDIR /bin/bash"
|
|
$CHROOT_CALL $DESTDIR /bin/bash
|
|
|
|
test $? -ne 0 && \
|
|
error "Failed to chroot into build systen in $DESTDIR."
|
|
|
|
exit 0
|
|
fi
|
|
|
|
# Set default mirror if MIRROR isn't set
|
|
test -z "$MIRROR" && MIRROR="$DEFAULT_MIRROR"
|
|
|
|
# If no targets are specified we default to the base group and the stock kernel.
|
|
test -z "${TARGETS[*]}" && TARGETS=(base kernel26)
|
|
|
|
# If we are installing the build environment we need to know the host system's
|
|
# architecture.
|
|
test -z "$ARCH" && ARCH="$(arch 2>/dev/null)"
|
|
test -z "$ARCH" && \
|
|
error "Could not obtain architecture type. Please use --arch manually."
|
|
if [ "$ARCH" != 'i686' -a "$ARCH" != 'x86_64' ]; then
|
|
error "Host system's architecture $ARCH is not supported"
|
|
fi
|
|
|
|
# Prepending the current working directory if DESTDIR isn't abolute. Safety
|
|
# measure as we're going to change to a temporary working directory.
|
|
if [ "${DESTDIR:0:1}" != "/" ]; then
|
|
debug 'DESTDIR not an absolute path. Prepending STARTDIR.'
|
|
DESTDIR="$STARTDIR/$DESTDIR"
|
|
fi
|
|
|
|
# Remove trailing / of MIRROR if necessary
|
|
MIRROR="${MIRROR%/}"
|
|
|
|
# Create DESTDIR if it doesn't exist yet.
|
|
if [ ! -d "$DESTDIR" ]; then
|
|
debug "Destination installation directory does not exist."
|
|
debug "Creating destination directory."
|
|
debug "mkdir -p \"$DESTDIR\" 2>/dev/null"
|
|
mkdir -p "$DESTDIR" 2>/dev/null
|
|
if [ $? -ne 0 ]; then
|
|
error "Failed to create $DESTDIR. Please create it manually and run again."
|
|
fi
|
|
fi
|
|
|
|
# Trying to find a pacman executable.
|
|
debug "Trying to find a pacman binary."
|
|
|
|
PACMAN="$(which pacman.static 2>/dev/null)"
|
|
if [ $? -ne 0 ]; then
|
|
debug "No pacman.static available in PATH."
|
|
PACMAN=''
|
|
fi
|
|
|
|
if [ -z "$PACMAN" ]; then
|
|
PACMAN="$(which pacman-static 2>/dev/null)"
|
|
if [ $? -ne 0 ]; then
|
|
debug "No pacman-static available in PATH."
|
|
PACMAN=''
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$PACMAN" ]; then
|
|
PACMAN="$(which pacman 2>/dev/null)"
|
|
if [ $? -ne 0 ]; then
|
|
debug "No pacman available in PATH."
|
|
PACMAN=''
|
|
fi
|
|
fi
|
|
|
|
# Check if pacman is now available
|
|
test -z "$PACMAN" && \
|
|
error "Could not obtain pacman binary. Install pacman to your PATH and run again."
|
|
debug "Found pacman binary as $PACMAN."
|
|
|
|
# Creating temporary pacman.conf
|
|
debug "Creating temporary pacman.conf."
|
|
CONFIG="$(mktemp -t pacman.conf.XXXX 2>/dev/null)"
|
|
test $? -ne 0 && CONFIG=''
|
|
|
|
test -z "$CONFIG" && error "Failed to create temporary pacman.conf."
|
|
|
|
# Build up pacman's temporary configuration file. We need the build repository
|
|
# even when we're not perfoming a build environment installation because of the
|
|
# system dependent qemu.
|
|
CLEANUP=("F:$CONFIG" ${CLEANUP[*]})
|
|
echo "[build]" > "$CONFIG"
|
|
echo "Server = $MIRROR/$ARCH/build" >> "$CONFIG"
|
|
echo >> "$CONFIG"
|
|
echo "[core]" >> "$CONFIG"
|
|
echo "Server = $MIRROR/arm/core" >> "$CONFIG"
|
|
|
|
MKDIR_CALL='mkdir'
|
|
test "$SUDO" = 'y' && MKDIR_CALL="$SUDO_CALL $MKDIR_CALL"
|
|
|
|
# Mounting binfmt if necessary.
|
|
binfmt_mount "$MOUNT_CALL" "$ECHO_CALL"
|
|
|
|
# Mounting proc and dev. This is needed for executing scriptlets using qemu.
|
|
for dir in proc dev; do
|
|
debug "Creating $dir directory under $DESTDIR."
|
|
debug "$MKDIR_CALL -p \"$DESTDIR/$dir\" &>/dev/null"
|
|
$MKDIR_CALL -p "$DESTDIR/$dir" &>/dev/null
|
|
test $? -ne 0 && error "Failed to create $dir directory under $DESTDIR."
|
|
done
|
|
|
|
for dir in proc dev; do
|
|
debug "Mounting $dir under new root."
|
|
debug "$MOUNT_CALL -o bind /$dir \"$DESTDIR/$dir\" &>/dev/null"
|
|
$MOUNT_CALL -o bind /$dir "$DESTDIR/$dir" &>/dev/null
|
|
test $? -ne 0 && error "Failed to bind $dir to $DESTDIR/$dir."
|
|
CLEANUP=("M:$DESTDIR/$dir" ${CLEANUP[*]})
|
|
done
|
|
|
|
# Set correct umask
|
|
debug "Setting umask to 022."
|
|
umask 022 &>/dev/null
|
|
test $? -ne 0 && error "Failed to set umask to 022."
|
|
|
|
# Creating pacman's working directory
|
|
debug "Creating pacman's working directory."
|
|
debug "$MKDIR_CALL -p \"$DESTDIR/var/lib/pacman\" &>/dev/null"
|
|
$MKDIR_CALL -p "$DESTDIR/var/lib/pacman" &>/dev/null
|
|
test $? -ne 0 && error "Failed to create pacman's working directory."
|
|
|
|
# Preparing pacman call
|
|
PACMAN_FLAGS="-r $DESTDIR --config $CONFIG --noconfirm --noprogressbar"
|
|
PACMAN_TARGETS="${TARGETS[*]}"
|
|
PACMAN_CALL="$PACMAN"
|
|
test "$SUDO" = 'y' && PACMAN_CALL="$SUDO_CALL $PACMAN_CALL"
|
|
test "$BUILD" = 'y' && PACMAN_TARGETS="base-devel $PACMAN_TARGETS"
|
|
PACMAN_FLAGS="$PACMAN_FLAGS $PACMAN_EXTRA"
|
|
|
|
debug "PACMAN_FLAGS = $PACMAN_FLAGS"
|
|
debug "PACMAN_TARGETS = $PACMAN_TARGETS"
|
|
debug "${CONFIG}:"
|
|
cat "$CONFIG" | while read ln; do
|
|
debug "$ln"
|
|
done
|
|
|
|
# Installing qemu (for chrooting) and gcc-libs (for shared libs)
|
|
debug "Installing qemu and gcc-libs."
|
|
debug "$PACMAN_CALL $PACMAN_FLAGS -Sy --noscriptlet --nodeps qemu gcc-libs"
|
|
$PACMAN_CALL $PACMAN_FLAGS -Sy --noscriptlet --nodeps qemu gcc-libs
|
|
test $? -ne 0 && error "Failed to install qemu or gcc-libs."
|
|
|
|
# Installing base and possibly base-devel.
|
|
debug "Installing base system."
|
|
debug "$PACMAN_CALL $PACMAN_FLAGS -Sy $PACMAN_TARGETS"
|
|
$PACMAN_CALL $PACMAN_FLAGS -Sy $PACMAN_TARGETS
|
|
test $? -ne 0 && error "Failed to install base or possibly base-devel."
|
|
|
|
# Removing qemu again if necessary.
|
|
if [ "$BUILD" != 'y' ]; then
|
|
debug "Removing qemu from new root."
|
|
debug "$CHROOT_CALL $DESTDIR pacman -Rns --noconfirm --noprogressbar qemu"
|
|
$CHROOT_CALL $DESTDIR pacman -Rns --noconfirm --noprogressbar qemu
|
|
test $? -ne 0 && error "Failed to remove qemu."
|
|
fi
|
|
|
|
doCleanup
|
|
|
|
exit 0
|
|
|
|
# vim: set ft=sh ts=2 sw=2 et:
|