#!/bin/bash # # makepkg - make packages compatible for use with pacman # @configure_input@ # # Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> # Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> # Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> # Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> # Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> # Copyright (c) 2006 by Alex Smith <alex@alex-smith.me.uk> # Copyright (c) 2006 by Andras Voroskoi <voroskoi@frugalware.org> # # 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 2 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/>. # # makepkg uses quite a few external programs during its execution. You # need to have at least the following installed for makepkg to function: # awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils), # gettext, gpg, grep, gzip, openssl, sed, tput (ncurses), xz # gettext initialization export TEXTDOMAIN='pacman-scripts' export TEXTDOMAINDIR='@localedir@' # file -i does not work on Mac OSX unless legacy mode is set export COMMAND_MODE='legacy' # Ensure CDPATH doesn't screw with our cd calls unset CDPATH declare -r myver='@PACKAGE_VERSION@' declare -r confdir='@sysconfdir@' declare -r BUILDSCRIPT='@BUILDSCRIPT@' declare -r startdir="$PWD" packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge' 'upx') other_options=('ccache' 'distcc' 'buildflags' 'makeflags') splitpkg_overrides=('pkgver' 'pkgrel' 'epoch' 'pkgdesc' 'arch' 'license' \ 'groups' 'depends' 'optdepends' 'provides' 'conflicts' \ 'replaces' 'backup' 'options' 'install' 'changelog') readonly -a packaging_options other_options splitpkg_overrides # Options ASROOT=0 CLEANUP=0 DEP_BIN=0 FORCE=0 INFAKEROOT=0 GENINTEG=0 SKIPCHECKSUMS=0 SKIPPGPCHECK=0 INSTALL=0 NOBUILD=0 NODEPS=0 NOEXTRACT=0 RMDEPS=0 REPKG=0 LOGGING=0 SOURCEONLY=0 IGNOREARCH=0 HOLDVER=0 BUILDFUNC=0 CHECKFUNC=0 PKGFUNC=0 SPLITPKG=0 PKGLIST=() SIGNPKG='' # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call # when dealing with svn/cvs/etc PKGBUILDs. FORCE_VER="" PACMAN_OPTS= shopt -s extglob ### SUBROUTINES ### plain() { local mesg=$1; shift printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } msg() { local mesg=$1; shift printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } msg2() { local mesg=$1; shift printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } warning() { local mesg=$1; shift printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } error() { local mesg=$1; shift printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } ## # Special exit call for traps, Don't print any error messages when inside, # the fakeroot call, the error message will be printed by the main call. ## trap_exit() { local signal=$1; shift if (( ! INFAKEROOT )); then echo error "$@" fi [[ -n $srclinks ]] && rm -rf "$srclinks" # unset the trap for this signal, and then call the default handler trap -- "$signal" kill "-$signal" "$$" } ## # Clean up function. Called automatically when the script exits. ## clean_up() { local EXIT_CODE=$? if (( INFAKEROOT )); then # Don't clean up when leaving fakeroot, we're not done yet. return fi if (( ! EXIT_CODE && CLEANUP )); then local pkg file # If it's a clean exit and -c/--clean has been passed... msg "$(gettext "Cleaning up...")" rm -rf "$pkgdir" "$srcdir" if [[ -n $pkgbase ]]; then local fullver=$(get_full_version) # Can't do this unless the BUILDSCRIPT has been sourced. if (( BUILDFUNC )); then rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"* fi if (( CHECKFUNC )); then rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"* fi if (( PKGFUNC )); then rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"* elif (( SPLITPKG )); then for pkg in ${pkgname[@]}; do rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"* done fi # clean up dangling symlinks to packages for pkg in ${pkgname[@]}; do for file in ${pkg}-*-*-${CARCH}{${PKGEXT},${SRCEXT}}; do if [[ -h $file && ! -e $file ]]; then rm -f "$file" fi done done fi fi remove_deps } enter_fakeroot() { msg "$(gettext "Entering %s environment...")" "fakeroot" if [[ -n $newpkgver ]]; then fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $? else fakeroot -- $0 -F "${ARGLIST[@]}" || exit $? fi } # a source entry can have two forms : # 1) "filename::http://path/to/file" # 2) "http://path/to/file" # Return the absolute filename of a source entry # # This function accepts a source entry or the already extracted filename of a # source entry as input get_filepath() { local file="$(get_filename "$1")" if [[ -f "$startdir/$file" ]]; then file="$startdir/$file" elif [[ -f "$SRCDEST/$file" ]]; then file="$SRCDEST/$file" else return 1 fi printf "%s\n" "$file" } # Print 'source not found' error message and exit makepkg missing_source_file() { error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")" plain "$(gettext "Aborting...")" exit 1 # $E_MISSING_FILE } # extract the filename from a source entry get_filename() { # if a filename is specified, use it local filename="${1%%::*}" # if it is just an URL, we only keep the last component printf "%s\n" "${filename##*/}" } # extract the URL from a source entry get_url() { # strip an eventual filename printf "%s\n" "${1#*::}" } ## # usage : get_full_version( [$pkgname] ) # return : full version spec, including epoch (if necessary), pkgver, pkgrel ## get_full_version() { if [[ -z $1 ]]; then if [[ $epoch ]] && (( ! $epoch )); then printf "%s\n" "$pkgver-$pkgrel" else printf "%s\n" "$epoch:$pkgver-$pkgrel" fi else for i in pkgver pkgrel epoch; do local indirect="${i}_override" eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p") [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\" done if (( ! $epoch_override )); then printf "%s\n" "$pkgver_override-$pkgrel_override" else printf "%s\n" "$epoch_override:$pkgver_override-$pkgrel_override" fi fi } ## # Checks to see if options are present in makepkg.conf or PKGBUILD; # PKGBUILD options always take precedence. # # usage : check_option( $option ) # return : y - enabled # n - disabled # ? - not found ## check_option() { local ret=$(in_opt_array "$1" ${options[@]}) if [[ $ret != '?' ]]; then printf "%s\n" "$ret" return fi # fall back to makepkg.conf options ret=$(in_opt_array "$1" ${OPTIONS[@]}) if [[ $ret != '?' ]]; then printf "%s\n" "$ret" return fi echo '?' # Not Found } ## # Check if option is present in BUILDENV # # usage : check_buildenv( $option ) # return : y - enabled # n - disabled # ? - not found ## check_buildenv() { in_opt_array "$1" ${BUILDENV[@]} } ## # usage : in_opt_array( $needle, $haystack ) # return : y - enabled # n - disabled # ? - not found ## in_opt_array() { local needle=$1; shift local opt for opt in "$@"; do if [[ $opt = "$needle" ]]; then echo 'y' # Enabled return elif [[ $opt = "!$needle" ]]; then echo 'n' # Disabled return fi done echo '?' # Not Found } ## # usage : in_array( $needle, $haystack ) # return : 0 - found # 1 - not found ## in_array() { local needle=$1; shift local item for item in "$@"; do [[ $item = "$needle" ]] && return 0 # Found done return 1 # Not Found } source_has_signatures() { local file for file in "${source[@]}"; do if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then return 0 fi done return 1 } get_downloadclient() { # $1 = URL with valid protocol prefix local url=$1 local proto="${url%%://*}" # loop through DOWNLOAD_AGENTS variable looking for protocol local i for i in "${DLAGENTS[@]}"; do local handler="${i%%::*}" if [[ $proto = "$handler" ]]; then local agent="${i##*::}" break fi done # if we didn't find an agent, return an error if [[ -z $agent ]]; then error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF" plain "$(gettext "Aborting...")" exit 1 # $E_CONFIG_ERROR fi # ensure specified program is installed local program="${agent%% *}" if [[ ! -x $program ]]; then local baseprog="${program##*/}" error "$(gettext "The download program %s is not installed.")" "$baseprog" plain "$(gettext "Aborting...")" exit 1 # $E_MISSING_PROGRAM fi printf "%s\n" "$agent" } download_file() { # download command local dlcmd=$1 # URL of the file local url=$2 # destination file local file=$3 # temporary download file, default to last component of the URL local dlfile="${url##*/}" # replace %o by the temporary dlfile if it exists if [[ $dlcmd = *%o* ]]; then dlcmd=${dlcmd//\%o/\"$file.part\"} dlfile="$file.part" fi # add the URL, either in place of %u or at the end if [[ $dlcmd = *%u* ]]; then dlcmd=${dlcmd//\%u/\"$url\"} else dlcmd="$dlcmd \"$url\"" fi local ret=0 eval "$dlcmd || ret=\$?" if (( ret )); then [[ ! -s $dlfile ]] && rm -f -- "$dlfile" return $ret fi # rename the temporary download file to the final destination if [[ $dlfile != "$file" ]]; then mv -f "$SRCDEST/$dlfile" "$SRCDEST/$file" fi } run_pacman() { local cmd if [[ ! $1 = -@(T|Qq) ]]; then cmd=("$PACMAN" $PACMAN_OPTS "$@") else cmd=("$PACMAN" "$@") fi if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then if type -p sudo >/dev/null; then cmd=(sudo "${cmd[@]}") else cmd=(su root -c "$(printf '%q ' "${cmd[@]}")") fi fi "${cmd[@]}" } check_deps() { (( $# > 0 )) || return 0 local ret=0 local pmout pmout=$(run_pacman -T "$@") ret=$? if (( ret == 127 )); then #unresolved deps printf "%s\n" "$pmout" elif (( ret )); then error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout" return "$ret" fi } handle_deps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 (( $# == 0 )) && return $R_DEPS_SATISFIED local deplist="$*" if (( ! DEP_BIN )); then return $R_DEPS_MISSING fi if (( DEP_BIN )); then # install missing deps from binary packages (using pacman -S) msg "$(gettext "Installing missing dependencies...")" if ! run_pacman -S --asdeps $deplist; then error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN" exit 1 # TODO: error code fi fi # we might need the new system environment # save our shell options and turn off extglob local shellopts=$(shopt -p) shopt -u extglob source /etc/profile &>/dev/null eval "$shellopts" return $R_DEPS_SATISFIED } resolve_deps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 # deplist cannot be declared like this: local deplist=$(foo) # Otherwise, the return value will depend on the assignment. local deplist deplist="$(set +E; check_deps $*)" || exit 1 [[ -z $deplist ]] && return $R_DEPS_SATISFIED if handle_deps $deplist; then # check deps again to make sure they were resolved deplist="$(set +E; check_deps $*)" || exit 1 [[ -z $deplist ]] && return $R_DEPS_SATISFIED fi msg "$(gettext "Missing Dependencies:")" local dep for dep in $deplist; do msg2 "$dep" done return $R_DEPS_MISSING } remove_deps() { (( ! RMDEPS )) && return # check for packages removed during dependency install (e.g. due to conflicts) # removing all installed packages is risky in this case if [[ -n $(grep -xvFf <(printf '%s\n' "${current_packagelist[@]}") \ <(printf '%s\n' "${original_packagelist[@]}") || true) ]]; then warning "$(gettext "Failed to remove installed dependencies.")" return 0 fi local deplist deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \ <(printf "%s\n" "${current_pkglist[@]}") || true)) if [[ -z $deplist ]]; then return fi msg "Removing installed dependencies..." # exit cleanly on failure to remove deps as package has been built successfully if ! run_pacman -Rn ${deplist[@]}; then warning "$(gettext "Failed to remove installed dependencies.")" return 0 fi } download_sources() { msg "$(gettext "Retrieving Sources...")" pushd "$SRCDEST" &>/dev/null local netfile for netfile in "${source[@]}"; do local file=$(get_filepath "$netfile" || true) if [[ -n "$file" ]]; then msg2 "$(gettext "Found %s")" "${file##*/}" rm -f "$srcdir/${file##*/}" ln -s "$file" "$srcdir/" continue fi file=$(get_filename "$netfile") local url=$(get_url "$netfile") # if we get here, check to make sure it was a URL, else fail if [[ $file = "$url" ]]; then error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file" exit 1 # $E_MISSING_FILE fi # find the client we should use for this URL local dlclient dlclient=$(get_downloadclient "$url") || exit $? msg2 "$(gettext "Downloading %s...")" "$file" # fix flyspray bug #3289 local ret=0 download_file "$dlclient" "$url" "$file" || ret=$? if (( ret )); then error "$(gettext "Failure while downloading %s")" "$file" plain "$(gettext "Aborting...")" exit 1 fi rm -f "$srcdir/$file" ln -s "$SRCDEST/$file" "$srcdir/" done popd &>/dev/null } get_integlist() { local integ local integlist=() for integ in md5 sha1 sha256 sha384 sha512; do local integrity_sums=($(eval echo "\${${integ}sums[@]}")) if [[ -n "$integrity_sums" ]]; then integlist=(${integlist[@]} $integ) fi done if (( ${#integlist[@]} > 0 )); then printf "%s\n" "${integlist[@]}" else printf "%s\n" "${INTEGRITY_CHECK[@]}" fi } generate_checksums() { msg "$(gettext "Generating checksums for source files...")" plain "" if ! type -p openssl >/dev/null; then error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl" exit 1 # $E_MISSING_PROGRAM fi local integlist if (( $# == 0 )); then integlist=$(get_integlist) else integlist=$@ fi local integ for integ in ${integlist[@]}; do case "$integ" in md5|sha1|sha256|sha384|sha512) : ;; *) error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ" exit 1;; # $E_CONFIG_ERROR esac local ct=0 local numsrc=${#source[@]} printf "%s" "${integ}sums=(" local i local indent='' for (( i = 0; i < ${#integ} + 6; i++ )); do indent="$indent " done local netfile for netfile in "${source[@]}"; do local file file="$(get_filepath "$netfile")" || missing_source_file "$netfile" local sum="$(openssl dgst -${integ} "$file")" sum=${sum##* } (( ct )) && printf "%s" "$indent" printf "%s" "'$sum'" ct=$(($ct+1)) (( $ct < $numsrc )) && echo done echo ")" done } check_checksums() { (( SKIPCHECKSUMS )) && return 0 (( ! ${#source[@]} )) && return 0 local correlation=0 local integ required for integ in md5 sha1 sha256 sha384 sha512; do local integrity_sums=($(eval echo "\${${integ}sums[@]}")) if (( ${#integrity_sums[@]} == ${#source[@]} )); then msg "$(gettext "Validating source files with %s...")" "${integ}sums" correlation=1 local errors=0 local idx=0 local file for file in "${source[@]}"; do local found=1 file="$(get_filename "$file")" printf "%s" " $file ... " >&2 if ! file="$(get_filepath "$file")"; then printf -- "$(gettext "NOT FOUND")\n" >&2 errors=1 found=0 fi if (( $found )) ; then if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then echo "$(gettext "Skipped")" >&2 else local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}") local realsum="$(openssl dgst -${integ} "$file")" realsum="${realsum##* }" if [[ $expectedsum = "$realsum" ]]; then printf -- "$(gettext "Passed")\n" >&2 else printf -- "$(gettext "FAILED")\n" >&2 errors=1 fi fi fi idx=$((idx + 1)) done if (( errors )); then error "$(gettext "One or more files did not pass the validity check!")" exit 1 # TODO: error code fi elif (( ${#integrity_sums[@]} )); then error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ" exit 1 # TODO: error code fi done if (( ! correlation )); then error "$(gettext "Integrity checks are missing.")" exit 1 # TODO: error code fi } check_pgpsigs() { (( SKIPPGPCHECK )) && return 0 ! source_has_signatures && return 0 msg "$(gettext "Verifying source file signatures with %s...")" "gpg" local file pubkey local warning=0 local errors=0 local statusfile=$(mktemp) for file in "${source[@]}"; do file="$(get_filename "$file")" if [[ ! $file = *.@(sig?(n)|asc) ]]; then continue fi printf " %s ... " "${file%.*}" >&2 if ! file="$(get_filepath "$file")"; then printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2 errors=1 continue fi if ! sourcefile="$(get_filepath "${file%.*}")"; then printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2 errors=1 continue fi if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then printf '%s' "$(gettext "FAILED")" >&2 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2 warnings=1 else errors=1 fi printf '\n' >&2 else if grep -q "REVKEYSIG" "$statusfile"; then printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2 errors=1 else printf '%s' "$(gettext "Passed")" >&2 if grep -q "EXPSIG" "$statusfile"; then printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2 warnings=1 elif grep -q "EXPKEYSIG" "$statusfile"; then printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2 warnings=1 fi fi printf '\n' >&2 fi done rm -f "$statusfile" if (( errors )); then error "$(gettext "One or more PGP signatures could not be verified!")" exit 1 fi if (( warnings )); then warning "$(gettext "Warnings have occurred while verifying the signatures.")" plain "$(gettext "Please make sure you really trust them.")" fi } check_source_integrity() { if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then warning "$(gettext "Skipping all source file integrity checks.")" elif (( SKIPCHECKSUMS )); then warning "$(gettext "Skipping verification of source file checksums.")" check_pgpsigs elif (( SKIPPGPCHECK )); then warning "$(gettext "Skipping verification of source file PGP signatures.")" check_checksums else check_checksums check_pgpsigs fi } extract_sources() { msg "$(gettext "Extracting Sources...")" local netfile for netfile in "${source[@]}"; do local file=$(get_filename "$netfile") if in_array "$file" "${noextract[@]}"; then #skip source files in the noextract=() array # these are marked explicitly to NOT be extracted continue fi # fix flyspray #6246 local file_type=$(file -bizL "$file") local ext=${file##*.} local cmd='' case "$file_type" in *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*) cmd="bsdtar" ;; *application/x-gzip*) case "$ext" in gz|z|Z) cmd="gzip" ;; *) continue;; esac ;; *application/x-bzip*) case "$ext" in bz2|bz) cmd="bzip2" ;; *) continue;; esac ;; *application/x-xz*) case "$ext" in xz) cmd="xz" ;; *) continue;; esac ;; *) # See if bsdtar can recognize the file if bsdtar -tf "$file" -q '*' &>/dev/null; then cmd="bsdtar" else continue fi ;; esac local ret=0 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd" if [[ $cmd = "bsdtar" ]]; then $cmd -xf "$file" || ret=$? else rm -f -- "${file%.*}" $cmd -dcf "$file" > "${file%.*}" || ret=$? fi if (( ret )); then error "$(gettext "Failed to extract %s")" "$file" plain "$(gettext "Aborting...")" exit 1 fi done if (( EUID == 0 )); then # change perms of all source files to root user & root group chown -R 0:0 "$srcdir" fi } error_function() { if [[ -p $logpipe ]]; then rm "$logpipe" fi # first exit all subshells, then print the error if (( ! BASH_SUBSHELL )); then error "$(gettext "A failure occurred in %s().")" "$1" plain "$(gettext "Aborting...")" remove_deps fi exit 2 # $E_BUILD_FAILED } cd_safe() { if ! cd "$1"; then error "$(gettext "Failed to change to directory %s")" "$1" plain "$(gettext "Aborting...")" exit 1 fi } source_safe() { shopt -u extglob if ! source "$@"; then error "$(gettext "Failed to source %s")" "$1" exit 1 fi shopt -s extglob } run_function_safe() { local restoretrap set -e set -E restoretrap=$(trap -p ERR) trap 'error_function $pkgfunc' ERR run_function "$1" eval $restoretrap set +E set +e } run_function() { if [[ -z $1 ]]; then return 1 fi local pkgfunc="$1" # clear user-specified buildflags if requested if [[ $(check_option buildflags) = "n" ]]; then unset CFLAGS CXXFLAGS LDFLAGS fi # clear user-specified makeflags if requested if [[ $(check_option makeflags) = "n" ]]; then unset MAKEFLAGS fi msg "$(gettext "Starting %s()...")" "$pkgfunc" cd_safe "$srcdir" # ensure all necessary build variables are exported export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST # save our shell options so pkgfunc() can't override what we need local shellopts=$(shopt -p) local ret=0 if (( LOGGING )); then local fullver=$(get_full_version) local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log" if [[ -f $BUILDLOG ]]; then local i=1 while true; do if [[ -f $BUILDLOG.$i ]]; then i=$(($i +1)) else break fi done mv "$BUILDLOG" "$BUILDLOG.$i" fi # ensure overridden package variables survive tee with split packages logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX") mkfifo "$logpipe" tee "$BUILDLOG" < "$logpipe" & local teepid=$! $pkgfunc &>"$logpipe" wait $teepid rm "$logpipe" else $pkgfunc 2>&1 fi # reset our shell options eval "$shellopts" } run_build() { # use distcc if it is requested (check buildenv and PKGBUILD opts) if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH" export DISTCC_HOSTS fi # use ccache if it is requested (check buildenv and PKGBUILD opts) if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH" fi run_function_safe "build" } run_check() { run_function_safe "check" } run_package() { local pkgfunc if [[ -z $1 ]]; then pkgfunc="package" else pkgfunc="package_$1" fi run_function_safe "$pkgfunc" } tidy_install() { cd_safe "$pkgdir" msg "$(gettext "Tidying install...")" if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then msg2 "$(gettext "Removing doc files...")" rm -rf -- ${DOC_DIRS[@]} fi if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then msg2 "$(gettext "Purging unwanted files...")" local pt for pt in "${PURGE_TARGETS[@]}"; do if [[ ${pt} = "${pt//\/}" ]]; then find . -type f -name "${pt}" -exec rm -f -- '{}' \; else rm -f ${pt} fi done fi if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then msg2 "$(gettext "Compressing man and info pages...")" local manpage ext file link hardlinks hl find ${MAN_DIRS[@]} -type f 2>/dev/null | while read manpage ; do ext="${manpage##*.}" file="${manpage##*/}" if [[ $ext != gz && $ext != bz2 ]]; then # update symlinks to this manpage find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null | while read link ; do rm -f "$link" "${link}.gz" ln -s -- "${file}.gz" "${link}.gz" done # check file still exists (potentially already compressed due to hardlink) if [[ -f ${manpage} ]]; then # find hard links and remove them # the '|| true' part keeps the script from bailing on the EOF returned # by read at the end of the find output IFS=$'\n' read -rd '' -a hardlinks < \ <(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" \ 2>/dev/null || true) || true rm -f "${hardlinks[@]}" # compress the original gzip -9 "$manpage" # recreate hard links removed earlier for hl in "${hardlinks[@]}"; do ln "${manpage}.gz" "${hl}.gz" chmod 644 ${hl}.gz done fi fi done fi if [[ $(check_option strip) = "y" ]]; then msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")" # make sure library stripping variables are defined to prevent excess stripping [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S" [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S" local binary find . -type f -perm -u+w 2>/dev/null | while read binary ; do case "$(file -bi "$binary")" in *application/x-sharedlib*) # Libraries (.so) strip $STRIP_SHARED "$binary";; *application/x-archive*) # Libraries (.a) strip $STRIP_STATIC "$binary";; *application/x-executable*) # Binaries strip $STRIP_BINARIES "$binary";; esac done fi if [[ $(check_option libtool) = "n" ]]; then msg2 "$(gettext "Removing "%s" files...")" "libtool" find . ! -type d -name "*.la" -exec rm -f -- '{}' \; fi if [[ $(check_option emptydirs) = "n" ]]; then msg2 "$(gettext "Removing empty directories...")" find . -depth -type d -empty -delete fi if [[ $(check_option upx) = "y" ]]; then msg2 "$(gettext "Compressing binaries with %s...")" "UPX" local binary find . -type f -perm -u+w 2>/dev/null | while read binary ; do if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then upx $UPXFLAGS "$binary" &>/dev/null || warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}" fi done fi } find_libdepends() { local libdepends find "$pkgdir" -type f -perm -u+x | while read filename do # get architecture of the file; if soarch is empty it's not an ELF binary soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') [ -n "$soarch" ] || continue # process all libraries needed by the binary for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p') do # extract the library name: libfoo.so soname="${sofile%.so?(+(.+([0-9])))}".so # extract the major version: 1 soversion="${sofile##*\.so\.}" if in_array "${soname}" ${depends[@]}; then if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then # libfoo.so=1-64 printf "%s" "${soname}=${soversion}-${soarch}" libdepends+=("${soname}=${soversion}-${soarch}") fi fi done done } find_libprovides() { local libprovides missing for p in "${provides[@]}"; do missing=0 case "$p" in *.so) IFS=$'\n' read -rd '' -a filename < <(find "$pkgdir" -type f -name $p\*) if [[ $filename ]]; then # packages may provide multiple versions of the same library for fn in "${filename[@]}"; do # check if we really have a shared object if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1) local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p') if [[ -z "$sofile" ]]; then warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p" libprovides+=("$p") continue fi # get the library architecture (32 or 64 bit) local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') # extract the library major version local soversion="${sofile##*\.so\.}" libprovides+=("${p}=${soversion}-${soarch}") else warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p" libprovides+=("$p") fi done else libprovides+=("$p") missing=1 fi ;; *) libprovides+=("$p") ;; esac if (( missing )); then warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p" fi done printf '%s\n' "${libprovides[@]}" } check_license() { # TODO maybe remove this at some point # warn if license array is not present or empty if [[ -z $license ]]; then warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT" plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')" fi } write_pkginfo() { local builddate=$(date -u "+%s") if [[ -n $PACKAGER ]]; then local packager="$PACKAGER" else local packager="Unknown Packager" fi # btrfs's delayed allocation causes the stat buffers from the kernel to "lie" # to us momentarily and report 0 blocks allocated (which is how du calculates # size). Sleeping for a second here is about the dirtiest thing possible, # but avoids reporting entirely bogus install sizes. sleep 1 local size="$(@DUPATH@ -sk)" size="$(( ${size%%[^0-9]*} * 1024 ))" msg2 "$(gettext "Generating %s file...")" ".PKGINFO" echo "# Generated by makepkg $myver" if (( INFAKEROOT )); then echo "# using $(fakeroot -v)" fi echo "# $(LC_ALL=C date -u)" printf "pkgname = %s\n" "$1" (( SPLITPKG )) && echo pkgbase = $pkgbase echo "pkgver = $(get_full_version)" printf "pkgdesc = %s\n" "$pkgdesc" printf "url = %s\n" "$url" printf "builddate = %s\n" "$builddate" printf "packager = %s\n" "$packager" printf "size = %s\n" "$size" printf "arch = %s\n" "$PKGARCH" [[ $license ]] && printf "license = %s\n" "${license[@]}" [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}" [[ $groups ]] && printf "group = %s\n" "${groups[@]}" [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }" [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}" IFS=$'\n' read -rd '' -a provides < <(find_libprovides) [[ $provides ]] && printf "provides = %s\n" "${provides[@]}" [[ $backup ]] && printf "backup = %s\n" "${backup[@]}" local it IFS=$'\n' read -rd '' -a libdepends < <(find_libdepends) depends+=("${libdepends[@]}") for it in "${depends[@]}"; do if [[ $it = *.so ]]; then # check if the entry has been found by find_libdepends # if not, it's unneeded; tell the user so he can remove it printf -v re '(^|\s)%s=.*' "$it" if [[ ! $libdepends =~ $re ]]; then error "$(gettext "Cannot find library listed in %s: %s")" "'depends'" "$it" return 1 fi else printf "depend = %s\n" "$it" fi done for it in "${packaging_options[@]}"; do local ret="$(check_option $it)" if [[ $ret != "?" ]]; then if [[ $ret = "y" ]]; then printf "makepkgopt = %s\n" "$it" else printf "makepkgopt = %s\n" "!$it" fi fi done check_license } check_package() { cd_safe "$pkgdir" # check existence of backup files local file for file in "${backup[@]}"; do if [[ ! -f $file ]]; then warning "$(gettext "%s entry file not in package : %s")" "backup" "$file" fi done # check for references to the build and package directory if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then warning "$(gettext "Package contains reference to %s")" "\$srcdir" fi if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then warning "$(gettext "Package contains reference to %s")" "\$pkgdir" fi } create_package() { if [[ ! -d $pkgdir ]]; then error "$(gettext "Missing %s directory.")" "pkg/" plain "$(gettext "Aborting...")" exit 1 # $E_MISSING_PKGDIR fi check_package cd_safe "$pkgdir" msg "$(gettext "Creating package...")" local nameofpkg if [[ -z $1 ]]; then nameofpkg="$pkgname" else nameofpkg="$1" fi if [[ $arch = "any" ]]; then PKGARCH="any" else PKGARCH=$CARCH fi write_pkginfo $nameofpkg > .PKGINFO local comp_files=('.PKGINFO') # check for changelog/install files for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do IFS='/' read -r orig dest < <(printf '%s\n' "$i") if [[ -n ${!orig} ]]; then msg2 "$(gettext "Adding %s file...")" "$orig" cp "$startdir/${!orig}" "$dest" chmod 644 "$dest" comp_files+=("$dest") fi done # tar it up msg2 "$(gettext "Compressing package...")" local fullver=$(get_full_version) local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}" local ret=0 [[ -f $pkg_file ]] && rm -f "$pkg_file" [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig" # when fileglobbing, we want * in an empty directory to expand to # the null string rather than itself shopt -s nullglob # TODO: Maybe this can be set globally for robustness shopt -s -o pipefail # bsdtar's gzip compression always saves the time stamp, making one # archive created using the same command line distinct from another. # Disable bsdtar compression and use gzip -n for now. bsdtar -cf - "${comp_files[@]}" * | case "$PKGEXT" in *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;; *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;; *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;; *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;; *tar) cat ;; *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$PKGEXT"; cat ;; esac > "${pkg_file}" || ret=$? shopt -u nullglob shopt -u -o pipefail if (( ret )); then error "$(gettext "Failed to create package file.")" exit 1 # TODO: error code fi create_signature "$pkg_file" if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then rm -f "${pkg_file/$PKGDEST/$startdir}" ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}" ret=$? if [[ -f $pkg_file.sig ]]; then rm -f "${pkg_file/$PKGDEST/$startdir}.sig" ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig" fi fi if (( ret )); then warning "$(gettext "Failed to create symlink to package file.")" fi } create_signature() { if [[ $SIGNPKG != 'y' ]]; then return fi local ret=0 local filename="$1" msg "$(gettext "Signing package...")" local SIGNWITHKEY="" if [[ -n $GPGKEY ]]; then SIGNWITHKEY="-u ${GPGKEY}" fi # The signature will be generated directly in ascii-friendly format gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$? if (( ! ret )); then msg2 "$(gettext "Created signature file %s.")" "$filename.sig" else warning "$(gettext "Failed to sign package file.")" fi } create_srcpackage() { local ret=0 msg "$(gettext "Creating source package...")" local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)" mkdir "${srclinks}"/${pkgbase} check_license msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT" ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}" local file for file in "${source[@]}"; do if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then local absfile absfile=$(get_filepath "$file") || missing_source_file "$file" msg2 "$(gettext "Adding %s...")" "${absfile##*/}" ln -s "$absfile" "$srclinks/$pkgbase" fi done local i for i in 'changelog' 'install'; do local file while read -r file; do # evaluate any bash variables used eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\" if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}" ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/" fi done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE") done local TAR_OPT case "$SRCEXT" in *tar.gz) TAR_OPT="z" ;; *tar.bz2) TAR_OPT="j" ;; *tar.xz) TAR_OPT="J" ;; *tar.Z) TAR_OPT="Z" ;; *tar) TAR_OPT="" ;; *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$SRCEXT" ;; esac local fullver=$(get_full_version) local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}" # tar it up msg2 "$(gettext "Compressing source package...")" cd_safe "${srclinks}" if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then error "$(gettext "Failed to create source package file.")" exit 1 # TODO: error code fi if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then rm -f "${pkg_file/$SRCPKGDEST/$startdir}" ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}" ret=$? fi if (( ret )); then warning "$(gettext "Failed to create symlink to source package file.")" fi cd_safe "${startdir}" rm -rf "${srclinks}" } install_package() { (( ! INSTALL )) && return if (( ! SPLITPKG )); then msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U" else msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U" fi local fullver pkg pkglist for pkg in ${pkgname[@]}; do fullver=$(get_full_version $pkg) if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} ]]; then pkglist+=" $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT}" else pkglist+=" $PKGDEST/${pkg}-${fullver}-any${PKGEXT}" fi done if ! run_pacman -U $pkglist; then warning "$(gettext "Failed to install built package(s).")" return 0 fi } check_sanity() { # check for no-no's in the build script local i local ret=0 for i in 'pkgname' 'pkgrel' 'pkgver'; do if [[ -z ${!i} ]]; then error "$(gettext "%s is not allowed to be empty.")" "$i" ret=1 fi done for i in "${pkgname[@]}"; do if [[ ${i:0:1} = "-" ]]; then error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname" ret=1 fi done if [[ ${pkgbase:0:1} = "-" ]]; then error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase" ret=1 fi awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" | while IFS='=' read -r _ i; do eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\" if [[ $i = *[[:space:]:-]* ]]; then error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver" return 1 fi done || ret=1 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" | while IFS='=' read -r _ i; do eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\" if [[ $i != +([0-9])?(.+([0-9])) ]]; then error "$(gettext "%s must be a decimal.")" "pkgrel" return 1 fi done || ret=1 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" | while IFS='=' read -r _ i; do eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\" if [[ $i != *([[:digit:]]) ]]; then error "$(gettext "%s must be an integer.")" "epoch" return 1 fi done || ret=1 if [[ $arch != 'any' ]]; then if ! in_array $CARCH ${arch[@]}; then if (( ! IGNOREARCH )); then error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" plain "$(gettext "such as %s.")" "arch=('$CARCH')" ret=1 fi fi fi if (( ${#pkgname[@]} > 1 )); then for i in ${pkgname[@]}; do local arch_list="" eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p') if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then if ! in_array $CARCH ${arch_list[@]}; then if (( ! IGNOREARCH )); then error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH" ret=1 fi fi fi done fi local provides_list=() eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \ sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//') for i in ${provides_list[@]}; do if [[ $i == *['<>']* ]]; then error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides" ret=1 fi done local backup_list=() eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \ sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//') for i in "${backup_list[@]}"; do if [[ ${i:0:1} = "/" ]]; then error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i" ret=1 fi done local optdepends_list=() eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \ sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//') for i in "${optdepends_list[@]}"; do local pkg=${i%%:[[:space:]]*} # the '-' character _must_ be first or last in the character range if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i" ret=1 fi done for i in 'changelog' 'install'; do local file while read -r file; do # evaluate any bash variables used eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\" if [[ $file && ! -f $file ]]; then error "$(gettext "%s file (%s) does not exist.")" "$i" "$file" ret=1 fi done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE") done local valid_options=1 local known kopt options_list eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \ sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//') for i in ${options_list[@]}; do known=0 # check if option matches a known option or its inverse for kopt in ${packaging_options[@]} ${other_options[@]}; do if [[ ${i} = "${kopt}" || ${i} = "!${kopt}" ]]; then known=1 fi done if (( ! known )); then error "$(gettext "%s array contains unknown option '%s'")" "options" "$i" valid_options=0 fi done if (( ! valid_options )); then ret=1 fi if (( ${#pkgname[@]} > 1 )); then for i in ${pkgname[@]}; do if ! declare -f package_${i} >/dev/null; then error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i" ret=1 fi done fi for i in ${PKGLIST[@]}; do if ! in_array $i ${pkgname[@]}; then error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE" ret=1 fi done return $ret } check_software() { # check for needed software local ret=0 # check for sudo if we will need it during makepkg execution if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then if ! type -p sudo >/dev/null; then warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")" fi fi # fakeroot - building as non-root user if [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then if ! type -p fakeroot >/dev/null; then error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot" ret=1 fi fi # gpg - package signing if [[ $SIGNPKG == 'y' || (-z "$SIGNPKG" && $(check_buildenv sign) == 'y') ]]; then if ! type -p gpg >/dev/null; then error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg" ret=1 fi fi # gpg - source verification if (( ! SKIPPGPCHECK )) && source_has_signatures; then if ! type -p gpg >/dev/null; then error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg" ret=1 fi fi # openssl - checksum operations if (( ! SKIPCHECKSUMS )); then if ! type -p openssl >/dev/null; then error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl" ret=1 fi fi # upx - binary compression if [[ $(check_option upx) == 'y' ]]; then if ! type -p upx >/dev/null; then error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx" ret=1 fi fi # distcc - compilation with distcc if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then if ! type -p distcc >/dev/null; then error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc" ret=1 fi fi # ccache - compilation with ccache if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then if ! type -p ccache >/dev/null; then error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache" ret=1 fi fi # strip - strip symbols from binaries/libraries if [[ $(check_option strip) = "y" ]]; then if ! type -p strip >/dev/null; then error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip" ret=1 fi fi # gzip - compressig man and info pages if [[ $(check_option zipman) = "y" ]]; then if ! type -p gzip >/dev/null; then error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip" ret=1 fi fi return $ret } devel_check() { newpkgver="" # Do not update pkgver if --holdver is set, when building a source package, repackaging, # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w) if (( HOLDVER || SOURCEONLY || REPKG )) || [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = "/dev/stdin" ]]; then return fi if [[ -z $FORCE_VER ]]; then # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so. # This will only be used on the first call to makepkg; subsequent # calls to makepkg via fakeroot will explicitly pass the version # number to avoid having to determine the version number twice. # Also do a check to make sure we have the VCS tool available. local vcs=() [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] && vcs+=("darcs") [[ -n ${_cvsroot} && -n ${_cvsmod} ]] && vcs+=("cvs") [[ -n ${_gitroot} && -n ${_gitname} ]] && vcs+=("git") [[ -n ${_svntrunk} && -n ${_svnmod} ]] && vcs+=("svn") [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] && vcs+=("bzr") [[ -n ${_hgroot} && -n ${_hgrepo} ]] && vcs+=("hg") if (( ${#vcs[@]} == 0 )); then return elif (( ${#vcs[@]} > 1 )); then warning "$(gettext "Ambiguous VCS package. Cannot pick from: %s.")" "${vcs[*]}" return 0 fi if ! type -p "$vcs" >/dev/null; then warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "$vcs" "$vcs" return 0 fi msg "$(gettext "Determining latest %s revision...")" "$vcs" case "$vcs" in darcs) newpkgver=$(date +%Y%m%d) ;; cvs) newpkgver=$(date +%Y%m%d) ;; git) newpkgver=$(date +%Y%m%d) ;; svn) newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p') ;; bzr) newpkgver=$(bzr revno ${_bzrtrunk}) ;; hg) if pushd "./src/$_hgrepo" > /dev/null; then local ret=0 hg pull || ret=$? if (( ! ret )); then hg update elif (( ret != 1 )); then return 1 fi else [[ ! -d ./src/ ]] && mkdir ./src/ hg clone "$_hgroot/$_hgrepo" "./src/$_hgrepo" if ! pushd "./src/$_hgrepo" > /dev/null; then warning "$(gettext "An error occured while determining the hg version number.")" return 0 fi fi newpkgver=$(hg tip --template "{rev}") popd > /dev/null ;; esac if [[ -n $newpkgver ]]; then msg2 "$(gettext "Version found: %s")" "$newpkgver" fi else # Version number retrieved from fakeroot->makepkg argument newpkgver=$FORCE_VER fi } devel_update() { # This is lame, but if we're wanting to use an updated pkgver for # retrieving svn/cvs/etc sources, we'll update the PKGBUILD with # the new pkgver and then re-source it. This is the most robust # method for dealing with PKGBUILDs that use, e.g.: # # pkgver=23 # ... # _foo=pkgver # if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE" @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE" source "$BUILDFILE" else warning "$(gettext "%s is not writeable -- pkgver will not be updated")" "$BUILDFILE" fi fi } backup_package_variables() { local var for var in ${splitpkg_overrides[@]}; do local indirect="${var}_backup" eval "${indirect}=(\"\${$var[@]}\")" done } restore_package_variables() { local var for var in ${splitpkg_overrides[@]}; do local indirect="${var}_backup" if [[ -n ${!indirect} ]]; then eval "${var}=(\"\${$indirect[@]}\")" else unset ${var} fi done } run_split_packaging() { local pkgname_backup=${pkgname[@]} for pkgname in ${pkgname_backup[@]}; do pkgdir="$pkgdir/$pkgname" mkdir -p "$pkgdir" chmod a-s "$pkgdir" backup_package_variables run_package $pkgname tidy_install create_package $pkgname restore_package_variables pkgdir="${pkgdir%/*}" done pkgname=${pkgname_backup[@]} } # Canonicalize a directory path if it exists canonicalize_path() { local path="$1"; if [[ -d $path ]]; then ( cd_safe "$path" pwd -P ) else printf "%s\n" "$path" fi } m4_include(library/parse_options.sh) usage() { printf "makepkg (pacman) %s\n" "$myver" echo printf -- "$(gettext "Usage: %s [options]")\n" "$0" echo printf -- "$(gettext "Options:")\n" printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT" printf -- "$(gettext " -c, --clean Clean up work files after build")\n" printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n" printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/" printf -- "$(gettext " -f, --force Overwrite existing package")\n" printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n" printf -- "$(gettext " -h, --help Show this help message and exit")\n" printf -- "$(gettext " -i, --install Install package after successful build")\n" printf -- "$(gettext " -L, --log Log package build process")\n" printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n" printf -- "$(gettext " -o, --nobuild Download and extract files only")\n" printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n" printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n" printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman" printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n" printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n" printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg" printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT" printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" printf -- "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT" printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg" printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT" printf -- "$(gettext " --nosign Do not create a signature for the package")\n" printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n" printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg" printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n" printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n" printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n" echo printf -- "$(gettext "These options can be passed to %s:")\n" "pacman" echo printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n" printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n" echo printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT" echo } version() { printf "makepkg (pacman) %s\n" "$myver" printf -- "$(gettext "\ Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\ Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\ This is free software; see the source for copying conditions.\n\ There is NO WARRANTY, to the extent permitted by law.\n")" } # PROGRAM START # determine whether we have gettext; make it a no-op if we do not if ! type -p gettext >/dev/null; then gettext() { printf "%s\n" "$@" } fi ARGLIST=("$@") # Parse Command Line Options. OPT_SHORT="AcdefFghiLmop:rRsSV" OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps" OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver,skippgpcheck" OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps" OPT_LONG+=",repackage,skipchecksums,skipinteg,skippgpcheck,sign,source,syncdeps" OPT_LONG+=",version,config:" # Pacman Options OPT_LONG+=",noconfirm,noprogressbar" if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then echo; usage; exit 1 # E_INVALID_OPTION; fi eval set -- "$OPT_TEMP" unset OPT_SHORT OPT_LONG OPT_TEMP while true; do case "$1" in # Pacman Options --noconfirm) PACMAN_OPTS+=" --noconfirm" ;; --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;; # Makepkg Options --allsource) SOURCEONLY=2 ;; --asroot) ASROOT=1 ;; -A|--ignorearch) IGNOREARCH=1 ;; -c|--clean) CLEANUP=1 ;; --check) RUN_CHECK='y' ;; --config) shift; MAKEPKG_CONF=$1 ;; -d|--nodeps) NODEPS=1 ;; -e|--noextract) NOEXTRACT=1 ;; -f|--force) FORCE=1 ;; #hidden opt used by fakeroot call for svn/cvs/etc PKGBUILDs to set pkgver --forcever) shift; FORCE_VER=$1;; -F) INFAKEROOT=1 ;; -g|--geninteg) GENINTEG=1 ;; --holdver) HOLDVER=1 ;; -i|--install) INSTALL=1 ;; --key) shift; GPGKEY=$1 ;; -L|--log) LOGGING=1 ;; -m|--nocolor) USE_COLOR='n' ;; --nocheck) RUN_CHECK='n' ;; --nosign) SIGNPKG='n' ;; -o|--nobuild) NOBUILD=1 ;; -p) shift; BUILDFILE=$1 ;; --pkg) shift; PKGLIST=($1) ;; -r|--rmdeps) RMDEPS=1 ;; -R|--repackage) REPKG=1 ;; --skipchecksums) SKIPCHECKSUMS=1 ;; --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;; --skippgpcheck) SKIPPGPCHECK=1;; --sign) SIGNPKG='y' ;; -s|--syncdeps) DEP_BIN=1 ;; -S|--source) SOURCEONLY=1 ;; -h|--help) usage; exit 0 ;; # E_OK -V|--version) version; exit 0 ;; # E_OK --) OPT_IND=0; shift; break;; *) usage; exit 1 ;; # E_INVALID_OPTION esac shift done # setup signal traps trap 'clean_up' 0 for signal in TERM HUP QUIT; do trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal" done trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR # preserve environment variables and canonicalize path [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST}) [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST}) [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST}) [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR}) [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT} [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT} [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY} [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER} # default config is makepkg.conf MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} # Source the config file; fail if it is not found if [[ -r $MAKEPKG_CONF ]]; then source_safe "$MAKEPKG_CONF" else error "$(gettext "%s not found.")" "$MAKEPKG_CONF" plain "$(gettext "Aborting...")" exit 1 # $E_CONFIG_ERROR fi # Source user-specific makepkg.conf overrides, but only if no override config # file was specified if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then source_safe ~/.makepkg.conf fi # set pacman command if not already defined PACMAN=${PACMAN:-pacman} # check if messages are to be printed using color unset ALL_OFF BOLD BLUE GREEN RED YELLOW if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then # prefer terminal safe colored and bold text when tput is supported if tput setaf 0 &>/dev/null; then ALL_OFF="$(tput sgr0)" BOLD="$(tput bold)" BLUE="${BOLD}$(tput setaf 4)" GREEN="${BOLD}$(tput setaf 2)" RED="${BOLD}$(tput setaf 1)" YELLOW="${BOLD}$(tput setaf 3)" else ALL_OFF="\e[1;0m" BOLD="\e[1;1m" BLUE="${BOLD}\e[1;34m" GREEN="${BOLD}\e[1;32m" RED="${BOLD}\e[1;31m" YELLOW="${BOLD}\e[1;33m" fi fi readonly ALL_OFF BOLD BLUE GREEN RED YELLOW # override settings with an environment variable for batch processing BUILDDIR=${_BUILDDIR:-$BUILDDIR} BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined if [[ ! -d $BUILDDIR ]]; then if ! mkdir -p "$BUILDDIR"; then error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR" plain "$(gettext "Aborting...")" exit 1 fi chmod a-s "$BUILDDIR" fi if [[ ! -w $BUILDDIR ]]; then error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR" plain "$(gettext "Aborting...")" exit 1 fi PKGDEST=${_PKGDEST:-$PKGDEST} PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST" plain "$(gettext "Aborting...")" exit 1 fi SRCDEST=${_SRCDEST:-$SRCDEST} SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined if [[ ! -w $SRCDEST ]] ; then error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST" plain "$(gettext "Aborting...")" exit 1 fi SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST} SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST" plain "$(gettext "Aborting...")" exit 1 fi PKGEXT=${_PKGEXT:-$PKGEXT} SRCEXT=${_SRCEXT:-$SRCEXT} GPGKEY=${_GPGKEY:-$GPGKEY} PACKAGER=${_PACKAGER:-$PACKAGER} if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then # The '\\0' is here to prevent gettext from thinking --holdver is an option error "$(gettext "\\0%s and %s cannot both be specified" )" "--holdver" "--forcever" exit 1 fi if (( ! INFAKEROOT )); then if (( EUID == 0 && ! ASROOT )); then # Warn those who like to live dangerously. error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\ catastrophic damage to your system. If you wish to run as root, please\n\ use the %s option.")" "makepkg" "--asroot" exit 1 # $E_USER_ABORT elif (( EUID > 0 && ASROOT )); then # Warn those who try to use the --asroot option when they are not root error "$(gettext "The %s option is meant for the root user only. Please\n\ rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot" exit 1 # $E_USER_ABORT elif (( EUID > 0 )) && [[ $(check_buildenv fakeroot) != "y" ]]; then warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\ ownership of the packaged files. Try using the %s environment by\n\ placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF" sleep 1 fi else if [[ -z $FAKEROOTKEY ]]; then error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg" exit 1 # TODO: error code fi fi unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides unset md5sums replaces depends conflicts backup source install changelog build unset makedepends optdepends options noextract BUILDFILE=${BUILDFILE:-$BUILDSCRIPT} if [[ ! -f $BUILDFILE ]]; then if [[ -t 0 ]]; then error "$(gettext "%s does not exist.")" "$BUILDFILE" exit 1 else # PKGBUILD passed through a pipe BUILDFILE=/dev/stdin source_safe "$BUILDFILE" fi else crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true) if [[ -n $crlftest ]]; then error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF" exit 1 fi if [[ ${BUILDFILE:0:1} != "/" ]]; then BUILDFILE="$startdir/$BUILDFILE" fi source_safe "$BUILDFILE" fi # set defaults if they weren't specified in buildfile pkgbase=${pkgbase:-${pkgname[0]}} epoch=${epoch:-0} if [[ $BUILDDIR = "$startdir" ]]; then srcdir="$BUILDDIR/src" pkgdir="$BUILDDIR/pkg" else srcdir="$BUILDDIR/$pkgbase/src" pkgdir="$BUILDDIR/$pkgbase/pkg" fi if (( GENINTEG )); then mkdir -p "$srcdir" chmod a-s "$srcdir" cd_safe "$srcdir" download_sources generate_checksums exit 0 # $E_OK fi # check the PKGBUILD for some basic requirements check_sanity || exit 1 # check we have the software required to process the PKGBUILD check_software || exit 1 # We need to run devel_update regardless of whether we are in the fakeroot # build process so that if the user runs makepkg --forcever manually, we # 1) output the correct pkgver, and 2) use the correct filename when # checking if the package file already exists - fixes FS #9194 devel_check devel_update if (( ${#pkgname[@]} > 1 )); then SPLITPKG=1 fi # test for available PKGBUILD functions if declare -f build >/dev/null; then BUILDFUNC=1 fi if declare -f check >/dev/null; then # "Hide" check() function if not going to be run if [[ $RUN_CHECK = 'y' || (! $(check_buildenv check) = "n" && ! $RUN_CHECK = "n") ]]; then CHECKFUNC=1 fi fi if declare -f package >/dev/null; then PKGFUNC=1 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then SPLITPKG=1 fi if [[ -n "${PKGLIST[@]}" ]]; then unset pkgname pkgname=("${PKGLIST[@]}") fi # check if gpg signature is to be created and if signing key is valid [[ -z $SIGNPKG ]] && SIGNPKG=$(check_buildenv sign) if [[ $SIGNPKG == 'y' ]]; then if ! gpg --list-key ${GPGKEY} &>/dev/null; then if [[ ! -z $GPGKEY ]]; then error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}" else error "$(gettext "There is no key in your keyring.")" fi exit 1 fi fi if (( ! SPLITPKG )); then fullver=$(get_full_version) if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \ || -f $PKGDEST/${pkgname}-${fullver}-any${PKGEXT} ]] \ && ! (( FORCE || SOURCEONLY || NOBUILD )); then if (( INSTALL )); then warning "$(gettext "A package has already been built, installing existing package...")" install_package exit $? else error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f" exit 1 fi fi else allpkgbuilt=1 somepkgbuilt=0 for pkg in ${pkgname[@]}; do fullver=$(get_full_version $pkg) if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} \ || -f $PKGDEST/${pkg}-${fullver}-any${PKGEXT} ]]; then somepkgbuilt=1 else allpkgbuilt=0 fi done if ! (( FORCE || SOURCEONLY || NOBUILD )); then if (( allpkgbuilt )); then if (( INSTALL )); then warning "$(gettext "The package group has already been built, installing existing packages...")" install_package exit $? else error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f" exit 1 fi fi if (( somepkgbuilt )); then error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f" exit 1 fi fi unset allpkgbuilt somepkgbuilt fi # Run the bare minimum in fakeroot if (( INFAKEROOT )); then if (( SOURCEONLY )); then create_srcpackage msg "$(gettext "Leaving %s environment.")" "fakeroot" exit 0 # $E_OK fi if (( ! SPLITPKG )); then if (( ! PKGFUNC )); then if (( ! REPKG )); then if (( BUILDFUNC )); then run_build (( CHECKFUNC )) && run_check tidy_install fi else warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()" plain "$(gettext "File permissions may not be preserved.")" fi else run_package tidy_install fi create_package else run_split_packaging fi msg "$(gettext "Leaving %s environment.")" "fakeroot" exit 0 # $E_OK fi fullver=$(get_full_version) msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))" # if we are creating a source-only package, go no further if (( SOURCEONLY )); then if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \ && (( ! FORCE )); then error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f" exit 1 fi # Get back to our src directory so we can begin with sources. mkdir -p "$srcdir" chmod a-s "$srcdir" cd_safe "$srcdir" if ( (( ! SKIPCHECKSUMS )) || \ ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \ (( SOURCEONLY == 2 )); then download_sources fi check_source_integrity cd_safe "$startdir" # if we are root or if fakeroot is not enabled, then we don't use it if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then create_srcpackage else enter_fakeroot fi msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))" exit 0 fi if (( NODEPS || ( (NOBUILD || REPKG) && !DEP_BIN ) )); then # no warning message needed for nobuild, repkg if (( NODEPS || ( REPKG && PKGFUNC ) )); then warning "$(gettext "Skipping dependency checks.")" fi elif type -p "${PACMAN%% *}" >/dev/null; then if (( RMDEPS && ! INSTALL )); then original_pkglist=($(run_pacman -Qq)) # required by remove_dep fi deperr=0 msg "$(gettext "Checking runtime dependencies...")" resolve_deps ${depends[@]} || deperr=1 if (( RMDEPS && INSTALL )); then original_pkglist=($(run_pacman -Qq)) # required by remove_dep fi msg "$(gettext "Checking buildtime dependencies...")" resolve_deps ${makedepends[@]} || deperr=1 if (( CHECKFUNC )); then resolve_deps ${checkdepends[@]} || deperr=1 fi if (( RMDEPS )); then current_pkglist=($(run_pacman -Qq)) # required by remove_deps fi if (( deperr )); then error "$(gettext "Could not resolve all dependencies.")" exit 1 fi else warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH" fi # ensure we have a sane umask set umask 0022 # get back to our src directory so we can begin with sources mkdir -p "$srcdir" chmod a-s "$srcdir" cd_safe "$srcdir" if (( NOEXTRACT )); then warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/" warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/" warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/" if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then error "$(gettext "The source directory is empty, there is nothing to build!")" plain "$(gettext "Aborting...")" exit 1 fi elif (( REPKG )); then if (( ! PKGFUNC && ! SPLITPKG )) \ && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then error "$(gettext "The package directory is empty, there is nothing to repackage!")" plain "$(gettext "Aborting...")" exit 1 fi else download_sources check_source_integrity extract_sources fi if (( NOBUILD )); then msg "$(gettext "Sources are ready.")" exit 0 #E_OK else # check for existing pkg directory; don't remove if we are repackaging if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then msg "$(gettext "Removing existing %s directory...")" "pkg/" rm -rf "$pkgdir" fi mkdir -p "$pkgdir" chmod a-s "$pkgdir" cd_safe "$startdir" # if we are root or if fakeroot is not enabled, then we don't use it if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then if (( ! REPKG )); then devel_update (( BUILDFUNC )) && run_build (( CHECKFUNC )) && run_check fi if (( ! SPLITPKG )); then if (( PKGFUNC )); then run_package tidy_install else if (( ! REPKG )); then tidy_install else warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()" plain "$(gettext "File permissions may not be preserved.")" fi fi create_package else run_split_packaging fi else if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then devel_update (( BUILDFUNC )) && run_build (( CHECKFUNC )) && run_check cd_safe "$startdir" fi enter_fakeroot fi fi fullver=$(get_full_version) msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))" install_package exit 0 #E_OK # vim: set ts=2 sw=2 noet: