makepkg: devel_check(): consolidate common code
[pacman-ng.git] / scripts / makepkg.sh.in
blob2502e881eb3a4c39899f62fd992f88ccb3d87c76
1 #!/bin/bash -e
3 # makepkg - make packages compatible for use with pacman
4 # @configure_input@
6 # Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
7 # Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
8 # Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
9 # Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org>
10 # Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
11 # Copyright (c) 2006 by Alex Smith <alex@alex-smith.me.uk>
12 # Copyright (c) 2006 by Andras Voroskoi <voroskoi@frugalware.org>
14 # This program is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
28 # makepkg uses quite a few external programs during its execution. You
29 # need to have at least the following installed for makepkg to function:
30 # awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils),
31 # gettext, gpg, grep, gzip, openssl, sed, tput (ncurses), xz
33 # gettext initialization
34 export TEXTDOMAIN='pacman-scripts'
35 export TEXTDOMAINDIR='@localedir@'
37 # file -i does not work on Mac OSX unless legacy mode is set
38 export COMMAND_MODE='legacy'
39 # Ensure CDPATH doesn't screw with our cd calls
40 unset CDPATH
42 declare -r myver='@PACKAGE_VERSION@'
43 declare -r confdir='@sysconfdir@'
44 declare -r BUILDSCRIPT='@BUILDSCRIPT@'
45 declare -r startdir="$PWD"
47 packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge' 'upx')
48 other_options=('ccache' 'distcc' 'buildflags' 'makeflags')
49 splitpkg_overrides=('pkgver' 'pkgrel' 'epoch' 'pkgdesc' 'arch' 'license' \
50 'groups' 'depends' 'optdepends' 'provides' 'conflicts' \
51 'replaces' 'backup' 'options' 'install' 'changelog')
52 readonly -a packaging_options other_options splitpkg_overrides
54 # Options
55 ASROOT=0
56 CLEANUP=0
57 DEP_BIN=0
58 FORCE=0
59 INFAKEROOT=0
60 GENINTEG=0
61 SKIPCHECKSUMS=0
62 SKIPPGPCHECK=0
63 INSTALL=0
64 NOBUILD=0
65 NODEPS=0
66 NOEXTRACT=0
67 RMDEPS=0
68 REPKG=0
69 LOGGING=0
70 SOURCEONLY=0
71 IGNOREARCH=0
72 HOLDVER=0
73 BUILDFUNC=0
74 CHECKFUNC=0
75 PKGFUNC=0
76 SPLITPKG=0
77 PKGLIST=()
78 SIGNPKG=''
80 # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call
81 # when dealing with svn/cvs/etc PKGBUILDs.
82 FORCE_VER=""
84 PACMAN_OPTS=
86 shopt -s extglob
88 ### SUBROUTINES ###
90 plain() {
91 local mesg=$1; shift
92 printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
95 msg() {
96 local mesg=$1; shift
97 printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
100 msg2() {
101 local mesg=$1; shift
102 printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
105 warning() {
106 local mesg=$1; shift
107 printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
110 error() {
111 local mesg=$1; shift
112 printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
117 # Special exit call for traps, Don't print any error messages when inside,
118 # the fakeroot call, the error message will be printed by the main call.
120 trap_exit() {
121 local signal=$1; shift
123 if (( ! INFAKEROOT )); then
124 echo
125 error "$@"
127 [[ -n $srclinks ]] && rm -rf "$srclinks"
129 # unset the trap for this signal, and then call the default handler
130 trap -- "$signal"
131 kill "-$signal" "$$"
136 # Clean up function. Called automatically when the script exits.
138 clean_up() {
139 local EXIT_CODE=$?
141 if (( INFAKEROOT )); then
142 # Don't clean up when leaving fakeroot, we're not done yet.
143 return
146 if (( ! EXIT_CODE && CLEANUP )); then
147 local pkg file
149 # If it's a clean exit and -c/--clean has been passed...
150 msg "$(gettext "Cleaning up...")"
151 rm -rf "$pkgdir" "$srcdir"
152 if [[ -n $pkgbase ]]; then
153 local fullver=$(get_full_version)
154 # Can't do this unless the BUILDSCRIPT has been sourced.
155 if (( BUILDFUNC )); then
156 rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"*
158 if (( CHECKFUNC )); then
159 rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
161 if (( PKGFUNC )); then
162 rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
163 elif (( SPLITPKG )); then
164 for pkg in ${pkgname[@]}; do
165 rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"*
166 done
169 # clean up dangling symlinks to packages
170 for pkg in ${pkgname[@]}; do
171 for file in ${pkg}-*-*-${CARCH}{${PKGEXT},${SRCEXT}}; do
172 if [[ -h $file && ! -e $file ]]; then
173 rm -f "$file"
175 done
176 done
180 remove_deps
184 enter_fakeroot() {
185 msg "$(gettext "Entering %s environment...")" "fakeroot"
187 if [[ -n $newpkgver ]]; then
188 fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $?
189 else
190 fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
195 # a source entry can have two forms :
196 # 1) "filename::http://path/to/file"
197 # 2) "http://path/to/file"
199 # Return the absolute filename of a source entry
201 # This function accepts a source entry or the already extracted filename of a
202 # source entry as input
203 get_filepath() {
204 local file="$(get_filename "$1")"
206 if [[ -f "$startdir/$file" ]]; then
207 file="$startdir/$file"
208 elif [[ -f "$SRCDEST/$file" ]]; then
209 file="$SRCDEST/$file"
210 else
211 return 1
214 echo "$file"
217 # Print 'source not found' error message and exit makepkg
218 missing_source_file() {
219 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
220 plain "$(gettext "Aborting...")"
221 exit 1 # $E_MISSING_FILE
224 # extract the filename from a source entry
225 get_filename() {
226 # if a filename is specified, use it
227 local filename="${1%%::*}"
228 # if it is just an URL, we only keep the last component
229 echo "${filename##*/}"
232 # extract the URL from a source entry
233 get_url() {
234 # strip an eventual filename
235 echo "${1#*::}"
239 # usage : get_full_version( [$pkgname] )
240 # return : full version spec, including epoch (if necessary), pkgver, pkgrel
242 get_full_version() {
243 if [[ -z $1 ]]; then
244 if [[ $epoch ]] && (( ! $epoch )); then
245 echo $pkgver-$pkgrel
246 else
247 echo $epoch:$pkgver-$pkgrel
249 else
250 for i in pkgver pkgrel epoch; do
251 local indirect="${i}_override"
252 eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
253 [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
254 done
255 if (( ! $epoch_override )); then
256 echo $pkgver_override-$pkgrel_override
257 else
258 echo $epoch_override:$pkgver_override-$pkgrel_override
264 # Checks to see if options are present in makepkg.conf or PKGBUILD;
265 # PKGBUILD options always take precedence.
267 # usage : check_option( $option )
268 # return : y - enabled
269 # n - disabled
270 # ? - not found
272 check_option() {
273 local ret=$(in_opt_array "$1" ${options[@]})
274 if [[ $ret != '?' ]]; then
275 echo $ret
276 return
279 # fall back to makepkg.conf options
280 ret=$(in_opt_array "$1" ${OPTIONS[@]})
281 if [[ $ret != '?' ]]; then
282 echo $ret
283 return
286 echo '?' # Not Found
291 # Check if option is present in BUILDENV
293 # usage : check_buildenv( $option )
294 # return : y - enabled
295 # n - disabled
296 # ? - not found
298 check_buildenv() {
299 in_opt_array "$1" ${BUILDENV[@]}
304 # usage : in_opt_array( $needle, $haystack )
305 # return : y - enabled
306 # n - disabled
307 # ? - not found
309 in_opt_array() {
310 local needle=$1; shift
312 local opt
313 for opt in "$@"; do
314 if [[ $opt = $needle ]]; then
315 echo 'y' # Enabled
316 return
317 elif [[ $opt = "!$needle" ]]; then
318 echo 'n' # Disabled
319 return
321 done
323 echo '?' # Not Found
328 # usage : in_array( $needle, $haystack )
329 # return : 0 - found
330 # 1 - not found
332 in_array() {
333 local needle=$1; shift
334 local item
335 for item in "$@"; do
336 [[ $item = $needle ]] && return 0 # Found
337 done
338 return 1 # Not Found
341 source_has_signatures() {
342 local file
343 for file in "${source[@]}"; do
344 if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
345 return 0
347 done
348 return 1
351 get_downloadclient() {
352 # $1 = URL with valid protocol prefix
353 local url=$1
354 local proto="${url%%://*}"
356 # loop through DOWNLOAD_AGENTS variable looking for protocol
357 local i
358 for i in "${DLAGENTS[@]}"; do
359 local handler="${i%%::*}"
360 if [[ $proto = $handler ]]; then
361 local agent="${i##*::}"
362 break
364 done
366 # if we didn't find an agent, return an error
367 if [[ -z $agent ]]; then
368 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
369 plain "$(gettext "Aborting...")"
370 exit 1 # $E_CONFIG_ERROR
373 # ensure specified program is installed
374 local program="${agent%% *}"
375 if [[ ! -x $program ]]; then
376 local baseprog="${program##*/}"
377 error "$(gettext "The download program %s is not installed.")" "$baseprog"
378 plain "$(gettext "Aborting...")"
379 exit 1 # $E_MISSING_PROGRAM
382 echo "$agent"
385 download_file() {
386 # download command
387 local dlcmd=$1
388 # URL of the file
389 local url=$2
390 # destination file
391 local file=$3
392 # temporary download file, default to last component of the URL
393 local dlfile="${url##*/}"
395 # replace %o by the temporary dlfile if it exists
396 if [[ $dlcmd = *%o* ]]; then
397 dlcmd=${dlcmd//\%o/\"$file.part\"}
398 dlfile="$file.part"
400 # add the URL, either in place of %u or at the end
401 if [[ $dlcmd = *%u* ]]; then
402 dlcmd=${dlcmd//\%u/\"$url\"}
403 else
404 dlcmd="$dlcmd \"$url\""
407 local ret=0
408 eval "$dlcmd || ret=\$?"
409 if (( ret )); then
410 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
411 return $ret
414 # rename the temporary download file to the final destination
415 if [[ $dlfile != "$file" ]]; then
416 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$file"
420 run_pacman() {
421 local cmd
422 if [[ ! $1 = -@(T|Qq) ]]; then
423 cmd=("$PACMAN" $PACMAN_OPTS "$@")
424 else
425 cmd=("$PACMAN" "$@")
427 if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then
428 if type -p sudo >/dev/null; then
429 cmd=(sudo "${cmd[@]}")
430 else
431 cmd=(su root -c "$(printf '%q ' "${cmd[@]}")")
434 "${cmd[@]}"
437 check_deps() {
438 (( $# > 0 )) || return 0
440 # Disable error trap in pacman subshell call as this breaks bash-3.2 compatibility
441 # Also, a non-zero return value is not unexpected and we are manually dealing them
442 set +E
443 local ret=0
444 local pmout
445 pmout=$(run_pacman -T "$@") || ret=$?
446 set -E
448 if (( ret == 127 )); then #unresolved deps
449 echo "$pmout"
450 elif (( ret )); then
451 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
452 return "$ret"
456 handle_deps() {
457 local R_DEPS_SATISFIED=0
458 local R_DEPS_MISSING=1
460 (( $# == 0 )) && return $R_DEPS_SATISFIED
462 local deplist="$*"
464 if (( ! DEP_BIN )); then
465 return $R_DEPS_MISSING
468 if (( DEP_BIN )); then
469 # install missing deps from binary packages (using pacman -S)
470 msg "$(gettext "Installing missing dependencies...")"
472 if ! run_pacman -S --asdeps $deplist; then
473 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
474 exit 1 # TODO: error code
478 # we might need the new system environment
479 # avoid triggering the ERR trap and exiting
480 set +e
481 local restoretrap=$(trap -p ERR)
482 trap - ERR
483 source /etc/profile &>/dev/null
484 eval $restoretrap
485 set -e
487 return $R_DEPS_SATISFIED
490 resolve_deps() {
491 local R_DEPS_SATISFIED=0
492 local R_DEPS_MISSING=1
494 # deplist cannot be declared like this: local deplist=$(foo)
495 # Otherwise, the return value will depend on the assignment.
496 local deplist
497 deplist="$(set +E; check_deps $*)" || exit 1
498 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
500 if handle_deps $deplist; then
501 # check deps again to make sure they were resolved
502 deplist="$(set +E; check_deps $*)" || exit 1
503 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
506 msg "$(gettext "Missing Dependencies:")"
507 local dep
508 for dep in $deplist; do
509 msg2 "$dep"
510 done
512 return $R_DEPS_MISSING
515 remove_deps() {
516 (( ! RMDEPS )) && return
518 # check for packages removed during dependency install (e.g. due to conflicts)
519 # removing all installed packages is risky in this case
520 if [[ -n $(grep -xvFf <(printf '%s\n' "${current_packagelist[@]}") \
521 <(printf '%s\n' "${original_packagelist[@]}") || true) ]]; then
522 warning "$(gettext "Failed to remove installed dependencies.")"
523 return 0
526 local deplist
527 deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \
528 <(printf "%s\n" "${current_pkglist[@]}") || true))
529 if [[ -z $deplist ]]; then
530 return
533 msg "Removing installed dependencies..."
534 # exit cleanly on failure to remove deps as package has been built successfully
535 if ! run_pacman -Rn ${deplist[@]}; then
536 warning "$(gettext "Failed to remove installed dependencies.")"
537 return 0
541 download_sources() {
542 msg "$(gettext "Retrieving Sources...")"
544 pushd "$SRCDEST" &>/dev/null
546 local netfile
547 for netfile in "${source[@]}"; do
548 local file=$(get_filepath "$netfile" || true)
549 if [[ -n "$file" ]]; then
550 msg2 "$(gettext "Found %s")" "${file##*/}"
551 rm -f "$srcdir/${file##*/}"
552 ln -s "$file" "$srcdir/"
553 continue
556 file=$(get_filename "$netfile")
557 local url=$(get_url "$netfile")
559 # if we get here, check to make sure it was a URL, else fail
560 if [[ $file = $url ]]; then
561 error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file"
562 exit 1 # $E_MISSING_FILE
565 # find the client we should use for this URL
566 local dlclient
567 dlclient=$(get_downloadclient "$url") || exit $?
569 msg2 "$(gettext "Downloading %s...")" "$file"
570 # fix flyspray bug #3289
571 local ret=0
572 download_file "$dlclient" "$url" "$file" || ret=$?
573 if (( ret )); then
574 error "$(gettext "Failure while downloading %s")" "$file"
575 plain "$(gettext "Aborting...")"
576 exit 1
578 rm -f "$srcdir/$file"
579 ln -s "$SRCDEST/$file" "$srcdir/"
580 done
582 popd &>/dev/null
585 get_integlist() {
586 local integ
587 local integlist=()
589 for integ in md5 sha1 sha256 sha384 sha512; do
590 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
591 if [[ -n "$integrity_sums" ]]; then
592 integlist=(${integlist[@]} $integ)
594 done
596 if (( ${#integlist[@]} > 0 )); then
597 echo ${integlist[@]}
598 else
599 echo ${INTEGRITY_CHECK[@]}
603 generate_checksums() {
604 msg "$(gettext "Generating checksums for source files...")"
605 plain ""
607 if ! type -p openssl >/dev/null; then
608 error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
609 exit 1 # $E_MISSING_PROGRAM
612 local integlist
613 if (( $# == 0 )); then
614 integlist=$(get_integlist)
615 else
616 integlist=$@
619 local integ
620 for integ in ${integlist[@]}; do
621 case "$integ" in
622 md5|sha1|sha256|sha384|sha512) : ;;
624 error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
625 exit 1;; # $E_CONFIG_ERROR
626 esac
628 local ct=0
629 local numsrc=${#source[@]}
630 echo -n "${integ}sums=("
632 local i
633 local indent=''
634 for (( i = 0; i < ${#integ} + 6; i++ )); do
635 indent="$indent "
636 done
638 local netfile
639 for netfile in "${source[@]}"; do
640 local file
641 file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
642 local sum="$(openssl dgst -${integ} "$file")"
643 sum=${sum##* }
644 (( ct )) && echo -n "$indent"
645 echo -n "'$sum'"
646 ct=$(($ct+1))
647 (( $ct < $numsrc )) && echo
648 done
650 echo ")"
651 done
654 check_checksums() {
655 (( SKIPCHECKSUMS )) && return 0
656 (( ! ${#source[@]} )) && return 0
658 local correlation=0
659 local integ required
660 for integ in md5 sha1 sha256 sha384 sha512; do
661 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
662 if (( ${#integrity_sums[@]} == ${#source[@]} )); then
663 msg "$(gettext "Validating source files with %s...")" "${integ}sums"
664 correlation=1
665 local errors=0
666 local idx=0
667 local file
668 for file in "${source[@]}"; do
669 local found=1
670 file="$(get_filename "$file")"
671 echo -n " $file ... " >&2
673 if ! file="$(get_filepath "$file")"; then
674 printf -- "$(gettext "NOT FOUND")\n" >&2
675 errors=1
676 found=0
679 if (( $found )) ; then
680 if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then
681 echo "$(gettext "Skipped")" >&2
682 else
683 local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}")
684 local realsum="$(openssl dgst -${integ} "$file")"
685 realsum="${realsum##* }"
686 if [[ $expectedsum = $realsum ]]; then
687 printf -- "$(gettext "Passed")\n" >&2
688 else
689 printf -- "$(gettext "FAILED")\n" >&2
690 errors=1
695 idx=$((idx + 1))
696 done
698 if (( errors )); then
699 error "$(gettext "One or more files did not pass the validity check!")"
700 exit 1 # TODO: error code
702 elif (( ${#integrity_sums[@]} )); then
703 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
704 exit 1 # TODO: error code
706 done
708 if (( ! correlation )); then
709 error "$(gettext "Integrity checks are missing.")"
710 exit 1 # TODO: error code
714 check_pgpsigs() {
715 (( SKIPPGPCHECK )) && return 0
716 ! source_has_signatures && return 0
718 msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
720 local file pubkey
721 local warning=0
722 local errors=0
723 local statusfile=$(mktemp)
725 for file in "${source[@]}"; do
726 file="$(get_filename "$file")"
727 if [[ ! $file = *.@(sig?(n)|asc) ]]; then
728 continue
731 printf " %s ... " "${file%.*}" >&2
733 if ! file="$(get_filepath "$file")"; then
734 printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
735 errors=1
736 continue
739 if ! sourcefile="$(get_filepath "${file%.*}")"; then
740 printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
741 errors=1
742 continue
745 if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
746 printf '%s' "$(gettext "FAILED")" >&2
747 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then
748 printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
749 warnings=1
750 else
751 errors=1
753 printf '\n' >&2
754 else
755 if grep -q "REVKEYSIG" "$statusfile"; then
756 printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2
757 errors=1
758 else
759 printf '%s' "$(gettext "Passed")" >&2
760 if grep -q "EXPSIG" "$statusfile"; then
761 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
762 warnings=1
763 elif grep -q "EXPKEYSIG" "$statusfile"; then
764 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
765 warnings=1
768 printf '\n' >&2
770 done
772 rm -f "$statusfile"
774 if (( errors )); then
775 error "$(gettext "One or more PGP signatures could not be verified!")"
776 exit 1
779 if (( warnings )); then
780 warning "$(gettext "Warnings have occurred while verifying the signatures.")"
781 plain "$(gettext "Please make sure you really trust them.")"
785 check_source_integrity() {
786 if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
787 warning "$(gettext "Skipping all source file integrity checks.")"
788 elif (( SKIPCHECKSUMS )); then
789 warning "$(gettext "Skipping verification of source file checksums.")"
790 check_pgpsigs
791 elif (( SKIPPGPCHECK )); then
792 warning "$(gettext "Skipping verification of source file PGP signatures.")"
793 check_checksums
794 else
795 check_checksums
796 check_pgpsigs
800 extract_sources() {
801 msg "$(gettext "Extracting Sources...")"
802 local netfile
803 for netfile in "${source[@]}"; do
804 local file=$(get_filename "$netfile")
805 if in_array "$file" "${noextract[@]}"; then
806 #skip source files in the noextract=() array
807 # these are marked explicitly to NOT be extracted
808 continue
812 # fix flyspray #6246
813 local file_type=$(file -bizL "$file")
814 local ext=${file##*.}
815 local cmd=''
816 case "$file_type" in
817 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
818 cmd="bsdtar" ;;
819 *application/x-gzip*)
820 case "$ext" in
821 gz|z|Z) cmd="gzip" ;;
822 *) continue;;
823 esac ;;
824 *application/x-bzip*)
825 case "$ext" in
826 bz2|bz) cmd="bzip2" ;;
827 *) continue;;
828 esac ;;
829 *application/x-xz*)
830 case "$ext" in
831 xz) cmd="xz" ;;
832 *) continue;;
833 esac ;;
835 # See if bsdtar can recognize the file
836 if bsdtar -tf "$file" -q '*' &>/dev/null; then
837 cmd="bsdtar"
838 else
839 continue
840 fi ;;
841 esac
843 local ret=0
844 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
845 if [[ $cmd = bsdtar ]]; then
846 $cmd -xf "$file" || ret=$?
847 else
848 rm -f -- "${file%.*}"
849 $cmd -dcf "$file" > "${file%.*}" || ret=$?
851 if (( ret )); then
852 error "$(gettext "Failed to extract %s")" "$file"
853 plain "$(gettext "Aborting...")"
854 exit 1
856 done
858 if (( EUID == 0 )); then
859 # change perms of all source files to root user & root group
860 chown -R 0:0 "$srcdir"
864 error_function() {
865 if [[ -p $logpipe ]]; then
866 rm "$logpipe"
868 # first exit all subshells, then print the error
869 if (( ! BASH_SUBSHELL )); then
870 error "$(gettext "A failure occurred in %s().")" "$1"
871 plain "$(gettext "Aborting...")"
872 remove_deps
874 exit 2 # $E_BUILD_FAILED
877 run_function() {
878 if [[ -z $1 ]]; then
879 return 1
881 local pkgfunc="$1"
883 # clear user-specified buildflags if requested
884 if [[ $(check_option buildflags) = "n" ]]; then
885 unset CFLAGS CXXFLAGS LDFLAGS
888 # clear user-specified makeflags if requested
889 if [[ $(check_option makeflags) = "n" ]]; then
890 unset MAKEFLAGS
893 msg "$(gettext "Starting %s()...")" "$pkgfunc"
894 cd "$srcdir"
896 # ensure all necessary build variables are exported
897 export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
898 # save our shell options so pkgfunc() can't override what we need
899 local shellopts=$(shopt -p)
901 local ret=0
902 local restoretrap
903 if (( LOGGING )); then
904 local fullver=$(get_full_version)
905 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
906 if [[ -f $BUILDLOG ]]; then
907 local i=1
908 while true; do
909 if [[ -f $BUILDLOG.$i ]]; then
910 i=$(($i +1))
911 else
912 break
914 done
915 mv "$BUILDLOG" "$BUILDLOG.$i"
918 # ensure overridden package variables survive tee with split packages
919 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
920 mkfifo "$logpipe"
921 tee "$BUILDLOG" < "$logpipe" &
922 local teepid=$!
924 restoretrap=$(trap -p ERR)
925 trap 'error_function $pkgfunc' ERR
926 $pkgfunc &>"$logpipe"
927 eval $restoretrap
929 wait $teepid
930 rm "$logpipe"
931 else
932 restoretrap=$(trap -p ERR)
933 trap 'error_function $pkgfunc' ERR
934 $pkgfunc 2>&1
935 eval $restoretrap
937 # reset our shell options
938 eval "$shellopts"
941 run_build() {
942 # use distcc if it is requested (check buildenv and PKGBUILD opts)
943 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
944 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
945 export DISTCC_HOSTS
948 # use ccache if it is requested (check buildenv and PKGBUILD opts)
949 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
950 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
953 run_function "build"
956 run_check() {
957 run_function "check"
960 run_package() {
961 local pkgfunc
962 if [[ -z $1 ]]; then
963 pkgfunc="package"
964 else
965 pkgfunc="package_$1"
968 run_function "$pkgfunc"
971 tidy_install() {
972 cd "$pkgdir"
973 msg "$(gettext "Tidying install...")"
975 if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then
976 msg2 "$(gettext "Removing doc files...")"
977 rm -rf -- ${DOC_DIRS[@]}
980 if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then
981 msg2 "$(gettext "Purging unwanted files...")"
982 local pt
983 for pt in "${PURGE_TARGETS[@]}"; do
984 if [[ ${pt} = ${pt//\/} ]]; then
985 find . -type f -name "${pt}" -exec rm -f -- '{}' \;
986 else
987 rm -f ${pt}
989 done
992 if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then
993 msg2 "$(gettext "Compressing man and info pages...")"
994 local manpage ext file link hardlinks hl
995 find ${MAN_DIRS[@]} -type f 2>/dev/null |
996 while read manpage ; do
997 ext="${manpage##*.}"
998 file="${manpage##*/}"
999 if [[ $ext != gz && $ext != bz2 ]]; then
1000 # update symlinks to this manpage
1001 find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null |
1002 while read link ; do
1003 rm -f "$link" "${link}.gz"
1004 ln -s -- "${file}.gz" "${link}.gz"
1005 done
1007 # check file still exists (potentially already compressed due to hardlink)
1008 if [[ -f ${manpage} ]]; then
1009 # find hard links and remove them
1010 # the '|| true' part keeps the script from bailing on the EOF returned
1011 # by read at the end of the find output
1012 IFS=$'\n' read -rd '' -a hardlinks < \
1013 <(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" \
1014 2>/dev/null || true) || true
1015 rm -f "${hardlinks[@]}"
1016 # compress the original
1017 gzip -9 "$manpage"
1018 # recreate hard links removed earlier
1019 for hl in "${hardlinks[@]}"; do
1020 ln "${manpage}.gz" "${hl}.gz"
1021 chmod 644 ${hl}.gz
1022 done
1025 done
1028 if [[ $(check_option strip) = y ]]; then
1029 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1030 # make sure library stripping variables are defined to prevent excess stripping
1031 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1032 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1033 local binary
1034 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1035 case "$(file -bi "$binary")" in
1036 *application/x-sharedlib*) # Libraries (.so)
1037 strip $STRIP_SHARED "$binary";;
1038 *application/x-archive*) # Libraries (.a)
1039 strip $STRIP_STATIC "$binary";;
1040 *application/x-executable*) # Binaries
1041 strip $STRIP_BINARIES "$binary";;
1042 esac
1043 done
1046 if [[ $(check_option libtool) = "n" ]]; then
1047 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1048 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1051 if [[ $(check_option emptydirs) = "n" ]]; then
1052 msg2 "$(gettext "Removing empty directories...")"
1053 find . -depth -type d -empty -delete
1056 if [[ $(check_option upx) = "y" ]]; then
1057 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1058 local binary
1059 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1060 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1061 upx $UPXFLAGS "$binary" &>/dev/null ||
1062 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1064 done
1068 find_libdepends() {
1069 local libdepends
1070 find "$pkgdir" -type f -perm -u+x | while read filename
1072 # get architecture of the file; if soarch is empty it's not an ELF binary
1073 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1074 [ -n "$soarch" ] || continue
1075 # process all libraries needed by the binary
1076 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1078 # extract the library name: libfoo.so
1079 soname="${sofile%.so?(+(.+([0-9])))}".so
1080 # extract the major version: 1
1081 soversion="${sofile##*\.so\.}"
1082 if in_array "${soname}" ${depends[@]}; then
1083 if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then
1084 # libfoo.so=1-64
1085 echo "${soname}=${soversion}-${soarch}"
1086 libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}")
1089 done
1090 done
1093 find_libprovides() {
1094 local libprovides missing
1095 for p in ${provides[@]}; do
1096 missing=0
1097 case "$p" in
1098 *.so)
1099 local filename=$(find "$pkgdir" -type f -name $p\*)
1100 if [[ $filename ]]; then
1101 # packages may provide multiple versions of the same library
1102 for fn in ${filename[@]}; do
1103 # check if we really have a shared object
1104 if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1105 # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1)
1106 local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1107 if [[ -z "$sofile" ]]; then
1108 warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p"
1109 libprovides=(${libprovides[@]} "$p")
1110 continue
1113 # get the library architecture (32 or 64 bit)
1114 local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1116 # extract the library major version
1117 local soversion="${sofile##*\.so\.}"
1119 libprovides=(${libprovides[@]} "${p}=${soversion}-${soarch}")
1120 else
1121 warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p"
1122 libprovides=(${libprovides[@]} "$p")
1124 done
1125 else
1126 libprovides=(${libprovides[@]} "$p")
1127 missing=1
1131 libprovides=(${libprovides[@]} "$p")
1133 esac
1135 if (( missing )); then
1136 warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p"
1138 done
1140 echo ${libprovides[@]}
1143 check_license() {
1144 # TODO maybe remove this at some point
1145 # warn if license array is not present or empty
1146 if [[ -z $license ]]; then
1147 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1148 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1152 write_pkginfo() {
1153 local builddate=$(date -u "+%s")
1154 if [[ -n $PACKAGER ]]; then
1155 local packager="$PACKAGER"
1156 else
1157 local packager="Unknown Packager"
1160 # btrfs's delayed allocation causes the stat buffers from the kernel to "lie"
1161 # to us momentarily and report 0 blocks allocated (which is how du calculates
1162 # size). Sleeping for a second here is about the dirtiest thing possible,
1163 # but avoids reporting entirely bogus install sizes.
1164 sleep 1
1165 local size="$(@DUPATH@ -sk)"
1166 size="$(( ${size%%[^0-9]*} * 1024 ))"
1168 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1169 echo "# Generated by makepkg $myver"
1170 if (( INFAKEROOT )); then
1171 echo "# using $(fakeroot -v)"
1173 echo "# $(LC_ALL=C date -u)"
1174 echo "pkgname = $1"
1175 (( SPLITPKG )) && echo pkgbase = $pkgbase
1176 echo "pkgver = $(get_full_version)"
1177 echo "pkgdesc = $pkgdesc"
1178 echo "url = $url"
1179 echo "builddate = $builddate"
1180 echo "packager = $packager"
1181 echo "size = $size"
1182 echo "arch = $PKGARCH"
1184 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1185 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1186 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1187 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1188 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1190 provides=($(find_libprovides))
1191 [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
1193 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1196 local it
1197 libdepends=$(find_libdepends)
1198 depends=("${depends[@]}" ${libdepends})
1200 for it in "${depends[@]}"; do
1201 if [[ $it = *.so ]]; then
1202 # check if the entry has been found by find_libdepends
1203 # if not, it's unneeded; tell the user so he can remove it
1204 printf -v re '(^|\s)%s=.*' "$it"
1205 if [[ ! $libdepends =~ $re ]]; then
1206 error "$(gettext "Cannot find library listed in %s: %s")" "'depends'" "$it"
1207 return 1
1209 else
1210 echo "depend = $it"
1212 done
1214 for it in "${packaging_options[@]}"; do
1215 local ret="$(check_option $it)"
1216 if [[ $ret != "?" ]]; then
1217 if [[ $ret = y ]]; then
1218 echo "makepkgopt = $it"
1219 else
1220 echo "makepkgopt = !$it"
1223 done
1225 check_license
1228 check_package() {
1229 cd "$pkgdir"
1231 # check existence of backup files
1232 local file
1233 for file in "${backup[@]}"; do
1234 if [[ ! -f $file ]]; then
1235 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1237 done
1239 # check for references to the build and package directory
1240 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1241 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1243 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1244 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1249 create_package() {
1250 if [[ ! -d $pkgdir ]]; then
1251 error "$(gettext "Missing %s directory.")" "pkg/"
1252 plain "$(gettext "Aborting...")"
1253 exit 1 # $E_MISSING_PKGDIR
1256 check_package
1258 cd "$pkgdir"
1259 msg "$(gettext "Creating package...")"
1261 local nameofpkg
1262 if [[ -z $1 ]]; then
1263 nameofpkg="$pkgname"
1264 else
1265 nameofpkg="$1"
1268 if [[ $arch = "any" ]]; then
1269 PKGARCH="any"
1270 else
1271 PKGARCH=$CARCH
1274 write_pkginfo $nameofpkg > .PKGINFO
1276 local comp_files=('.PKGINFO')
1278 # check for changelog/install files
1279 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1280 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1282 if [[ -n ${!orig} ]]; then
1283 msg2 "$(gettext "Adding %s file...")" "$orig"
1284 cp "$startdir/${!orig}" "$dest"
1285 chmod 644 "$dest"
1286 comp_files+=("$dest")
1288 done
1290 # tar it up
1291 msg2 "$(gettext "Compressing package...")"
1293 local fullver=$(get_full_version)
1294 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}"
1295 local ret=0
1297 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1298 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1300 # when fileglobbing, we want * in an empty directory to expand to
1301 # the null string rather than itself
1302 shopt -s nullglob
1303 # TODO: Maybe this can be set globally for robustness
1304 shopt -s -o pipefail
1305 # bsdtar's gzip compression always saves the time stamp, making one
1306 # archive created using the same command line distinct from another.
1307 # Disable bsdtar compression and use gzip -n for now.
1308 bsdtar -cf - "${comp_files[@]}" * |
1309 case "$PKGEXT" in
1310 *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;;
1311 *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;;
1312 *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;;
1313 *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;;
1314 *tar) cat ;;
1315 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1316 "$PKGEXT"; cat ;;
1317 esac > "${pkg_file}" || ret=$?
1319 shopt -u nullglob
1320 shopt -u -o pipefail
1322 if (( ret )); then
1323 error "$(gettext "Failed to create package file.")"
1324 exit 1 # TODO: error code
1327 create_signature "$pkg_file"
1329 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1330 rm -f "${pkg_file/$PKGDEST/$startdir}"
1331 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1332 ret=$?
1333 if [[ -f $pkg_file.sig ]]; then
1334 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1335 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1339 if (( ret )); then
1340 warning "$(gettext "Failed to create symlink to package file.")"
1344 create_signature() {
1345 if [[ $SIGNPKG != 'y' ]]; then
1346 return
1348 local ret=0
1349 local filename="$1"
1350 msg "$(gettext "Signing package...")"
1352 local SIGNWITHKEY=""
1353 if [[ -n $GPGKEY ]]; then
1354 SIGNWITHKEY="-u ${GPGKEY}"
1356 # The signature will be generated directly in ascii-friendly format
1357 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1360 if (( ! ret )); then
1361 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1362 else
1363 warning "$(gettext "Failed to sign package file.")"
1367 create_srcpackage() {
1368 local ret=0
1369 msg "$(gettext "Creating source package...")"
1370 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1371 mkdir "${srclinks}"/${pkgbase}
1373 check_license
1375 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1376 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1378 local file
1379 for file in "${source[@]}"; do
1380 if [[ "$file" == $(get_filename "$file") ]] || (( SOURCEONLY == 2 )); then
1381 local absfile
1382 absfile=$(get_filepath "$file") || missing_source_file "$file"
1383 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1384 ln -s "$absfile" "$srclinks/$pkgbase"
1386 done
1388 local i
1389 for i in 'changelog' 'install'; do
1390 local file
1391 while read -r file; do
1392 # evaluate any bash variables used
1393 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1394 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1395 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1396 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1398 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1399 done
1401 local TAR_OPT
1402 case "$SRCEXT" in
1403 *tar.gz) TAR_OPT="z" ;;
1404 *tar.bz2) TAR_OPT="j" ;;
1405 *tar.xz) TAR_OPT="J" ;;
1406 *tar.Z) TAR_OPT="Z" ;;
1407 *tar) TAR_OPT="" ;;
1408 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1409 "$SRCEXT" ;;
1410 esac
1412 local fullver=$(get_full_version)
1413 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1415 # tar it up
1416 msg2 "$(gettext "Compressing source package...")"
1417 cd "${srclinks}"
1418 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1419 error "$(gettext "Failed to create source package file.")"
1420 exit 1 # TODO: error code
1423 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1424 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1425 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1426 ret=$?
1429 if (( ret )); then
1430 warning "$(gettext "Failed to create symlink to source package file.")"
1433 cd "${startdir}"
1434 rm -rf "${srclinks}"
1437 install_package() {
1438 (( ! INSTALL )) && return
1440 if (( ! SPLITPKG )); then
1441 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1442 else
1443 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1446 local fullver pkg pkglist
1447 for pkg in ${pkgname[@]}; do
1448 fullver=$(get_full_version $pkg)
1449 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} ]]; then
1450 pkglist+=" $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT}"
1451 else
1452 pkglist+=" $PKGDEST/${pkg}-${fullver}-any${PKGEXT}"
1454 done
1456 if ! run_pacman -U $pkglist; then
1457 warning "$(gettext "Failed to install built package(s).")"
1458 return 0
1462 check_sanity() {
1463 # check for no-no's in the build script
1464 local i
1465 local ret=0
1466 for i in 'pkgname' 'pkgrel' 'pkgver'; do
1467 if [[ -z ${!i} ]]; then
1468 error "$(gettext "%s is not allowed to be empty.")" "$i"
1469 ret=1
1471 done
1473 for i in "${pkgname[@]}"; do
1474 if [[ ${i:0:1} = "-" ]]; then
1475 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1476 ret=1
1478 done
1480 if [[ ${pkgbase:0:1} = "-" ]]; then
1481 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1482 ret=1
1485 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1486 while IFS='=' read -r _ i; do
1487 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1488 if [[ $i = *[[:space:]:-]* ]]; then
1489 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
1490 return 1
1492 done || ret=1
1494 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1495 while IFS='=' read -r _ i; do
1496 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1497 if [[ $i != +([0-9])?(.+([0-9])) ]]; then
1498 error "$(gettext "%s must be a decimal.")" "pkgrel"
1499 return 1
1501 done || ret=1
1503 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1504 while IFS='=' read -r _ i; do
1505 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1506 if [[ $i != *([[:digit:]]) ]]; then
1507 error "$(gettext "%s must be an integer.")" "epoch"
1508 return 1
1510 done || ret=1
1512 if [[ $arch != 'any' ]]; then
1513 if ! in_array $CARCH ${arch[@]}; then
1514 if (( ! IGNOREARCH )); then
1515 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1516 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1517 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1518 ret=1
1523 if (( ${#pkgname[@]} > 1 )); then
1524 for i in ${pkgname[@]}; do
1525 local arch_list=""
1526 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1527 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1528 if ! in_array $CARCH ${arch_list[@]}; then
1529 if (( ! IGNOREARCH )); then
1530 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1531 ret=1
1535 done
1538 local provides_list=()
1539 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1540 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1541 for i in ${provides_list[@]}; do
1542 if [[ $i == *['<>']* ]]; then
1543 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1544 ret=1
1546 done
1548 local backup_list=()
1549 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1550 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1551 for i in "${backup_list[@]}"; do
1552 if [[ ${i:0:1} = "/" ]]; then
1553 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1554 ret=1
1556 done
1558 local optdepends_list=()
1559 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1560 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1561 for i in "${optdepends_list[@]}"; do
1562 local pkg=${i%%:[[:space:]]*}
1563 # the '-' character _must_ be first or last in the character range
1564 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1565 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1566 ret=1
1568 done
1570 for i in 'changelog' 'install'; do
1571 local file
1572 while read -r file; do
1573 # evaluate any bash variables used
1574 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1575 if [[ $file && ! -f $file ]]; then
1576 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1577 ret=1
1579 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1580 done
1582 local valid_options=1
1583 local known kopt options_list
1584 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1585 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1586 for i in ${options_list[@]}; do
1587 known=0
1588 # check if option matches a known option or its inverse
1589 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1590 if [[ ${i} = ${kopt} || ${i} = "!${kopt}" ]]; then
1591 known=1
1593 done
1594 if (( ! known )); then
1595 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1596 valid_options=0
1598 done
1599 if (( ! valid_options )); then
1600 ret=1
1603 if (( ${#pkgname[@]} > 1 )); then
1604 for i in ${pkgname[@]}; do
1605 if ! declare -f package_${i} >/dev/null; then
1606 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1607 ret=1
1609 done
1612 for i in ${PKGLIST[@]}; do
1613 if ! in_array $i ${pkgname[@]}; then
1614 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1615 ret=1
1617 done
1619 return $ret
1622 check_software() {
1623 # check for needed software
1624 local ret=0
1626 # check for sudo if we will need it during makepkg execution
1627 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1628 if ! type -p sudo >/dev/null; then
1629 warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")"
1633 # fakeroot - building as non-root user
1634 if [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then
1635 if ! type -p fakeroot >/dev/null; then
1636 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
1637 ret=1
1641 # gpg - package signing
1642 if [[ $SIGNPKG == 'y' || (-z "$SIGNPKG" && $(check_buildenv sign) == 'y') ]]; then
1643 if ! type -p gpg >/dev/null; then
1644 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
1645 ret=1
1649 # gpg - source verification
1650 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
1651 if ! type -p gpg >/dev/null; then
1652 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
1653 ret=1
1657 # openssl - checksum operations
1658 if (( ! SKIPCHECKSUMS )); then
1659 if ! type -p openssl >/dev/null; then
1660 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
1661 ret=1
1665 # upx - binary compression
1666 if [[ $(check_option upx) == 'y' ]]; then
1667 if ! type -p upx >/dev/null; then
1668 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
1669 ret=1
1673 # distcc - compilation with distcc
1674 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
1675 if ! type -p distcc >/dev/null; then
1676 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
1677 ret=1
1681 # ccache - compilation with ccache
1682 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
1683 if ! type -p ccache >/dev/null; then
1684 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
1685 ret=1
1689 # strip - strip symbols from binaries/libraries
1690 if [[ $(check_option strip) = "y" ]]; then
1691 if ! type -p strip >/dev/null; then
1692 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
1693 ret=1
1697 # gzip - compressig man and info pages
1698 if [[ $(check_option zipman) = "y" ]]; then
1699 if ! type -p gzip >/dev/null; then
1700 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
1701 ret=1
1705 return $ret
1708 devel_check() {
1709 newpkgver=""
1711 # Do not update pkgver if --holdver is set, when building a source package, repackaging,
1712 # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w)
1713 if (( HOLDVER || SOURCEONLY || REPKG )) ||
1714 [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = /dev/stdin ]]; then
1715 return
1718 if [[ -z $FORCE_VER ]]; then
1719 # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so.
1720 # This will only be used on the first call to makepkg; subsequent
1721 # calls to makepkg via fakeroot will explicitly pass the version
1722 # number to avoid having to determine the version number twice.
1723 # Also do a check to make sure we have the VCS tool available.
1724 local vcs=()
1726 [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] && vcs+=("darcs")
1727 [[ -n ${_cvsroot} && -n ${_cvsmod} ]] && vcs+=("cvs")
1728 [[ -n ${_gitroot} && -n ${_gitname} ]] && vcs+=("git")
1729 [[ -n ${_svntrunk} && -n ${_svnmod} ]] && vcs+=("svn")
1730 [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] && vcs+=("bzr")
1731 [[ -n ${_hgroot} && -n ${_hgrepo} ]] && vcs+=("hg")
1733 if (( ${#vcs[@]} == 0 )); then
1734 return
1735 elif (( ${#vcs[@]} > 1 )); then
1736 warning "$(gettext "Ambiguous VCS package. Cannot pick from: %s.")" "${vcs[*]}"
1737 return 0
1740 if ! type -p "$vcs" >/dev/null; then
1741 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "$vcs" "$vcs"
1742 return 0
1745 msg "$(gettext "Determining latest %s revision...")" "$vcs"
1747 if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then
1748 newpkgver=$(date +%Y%m%d)
1749 elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then
1750 newpkgver=$(date +%Y%m%d)
1751 elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then
1752 newpkgver=$(date +%Y%m%d)
1753 elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then
1754 newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p')
1755 elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then
1756 newpkgver=$(bzr revno ${_bzrtrunk})
1757 elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then
1758 if [[ -d ./src/$_hgrepo ]] ; then
1759 cd ./src/$_hgrepo
1760 local ret=0
1761 hg pull || ret=$?
1762 if (( ! ret )); then
1763 hg update
1764 elif (( ret != 1 )); then
1765 return 1
1767 else
1768 [[ ! -d ./src/ ]] && mkdir ./src/
1769 hg clone $_hgroot/$_hgrepo ./src/$_hgrepo
1770 cd ./src/$_hgrepo
1772 newpkgver=$(hg tip --template "{rev}")
1773 cd ../../
1776 if [[ -n $newpkgver ]]; then
1777 msg2 "$(gettext "Version found: %s")" "$newpkgver"
1780 else
1781 # Version number retrieved from fakeroot->makepkg argument
1782 newpkgver=$FORCE_VER
1786 devel_update() {
1787 # This is lame, but if we're wanting to use an updated pkgver for
1788 # retrieving svn/cvs/etc sources, we'll update the PKGBUILD with
1789 # the new pkgver and then re-source it. This is the most robust
1790 # method for dealing with PKGBUILDs that use, e.g.:
1792 # pkgver=23
1793 # ...
1794 # _foo=pkgver
1796 if [[ -n $newpkgver ]]; then
1797 if [[ $newpkgver != "$pkgver" ]]; then
1798 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
1799 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
1800 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
1801 source "$BUILDFILE"
1807 backup_package_variables() {
1808 local var
1809 for var in ${splitpkg_overrides[@]}; do
1810 local indirect="${var}_backup"
1811 eval "${indirect}=(\"\${$var[@]}\")"
1812 done
1815 restore_package_variables() {
1816 local var
1817 for var in ${splitpkg_overrides[@]}; do
1818 local indirect="${var}_backup"
1819 if [[ -n ${!indirect} ]]; then
1820 eval "${var}=(\"\${$indirect[@]}\")"
1821 else
1822 unset ${var}
1824 done
1827 run_split_packaging() {
1828 local pkgname_backup=${pkgname[@]}
1829 for pkgname in ${pkgname_backup[@]}; do
1830 pkgdir="$pkgdir/$pkgname"
1831 mkdir -p "$pkgdir"
1832 chmod a-s "$pkgdir"
1833 backup_package_variables
1834 run_package $pkgname
1835 tidy_install
1836 create_package $pkgname
1837 restore_package_variables
1838 pkgdir="${pkgdir%/*}"
1839 done
1840 pkgname=${pkgname_backup[@]}
1843 # Canonicalize a directory path if it exists
1844 canonicalize_path() {
1845 local path="$1";
1847 if [[ -d $path ]]; then
1849 cd "$path"
1850 pwd -P
1852 else
1853 echo "$path"
1857 m4_include(library/parse_options.sh)
1859 usage() {
1860 printf "makepkg (pacman) %s\n" "$myver"
1861 echo
1862 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
1863 echo
1864 printf -- "$(gettext "Options:")\n"
1865 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
1866 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
1867 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
1868 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
1869 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
1870 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
1871 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
1872 printf -- "$(gettext " -i, --install Install package after successful build")\n"
1873 printf -- "$(gettext " -L, --log Log package build process")\n"
1874 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
1875 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
1876 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
1877 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
1878 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
1879 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
1880 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
1881 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
1882 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
1883 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1884 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
1885 printf -- "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT"
1886 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
1887 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1888 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
1889 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
1890 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
1891 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
1892 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
1893 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
1894 echo
1895 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
1896 echo
1897 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
1898 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
1899 echo
1900 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
1901 echo
1904 version() {
1905 printf "makepkg (pacman) %s\n" "$myver"
1906 printf -- "$(gettext "\
1907 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
1908 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
1909 This is free software; see the source for copying conditions.\n\
1910 There is NO WARRANTY, to the extent permitted by law.\n")"
1913 # PROGRAM START
1915 # determine whether we have gettext; make it a no-op if we do not
1916 if ! type -p gettext >/dev/null; then
1917 gettext() {
1918 echo "$@"
1922 ARGLIST=("$@")
1924 # Parse Command Line Options.
1925 OPT_SHORT="AcdefFghiLmop:rRsSV"
1926 OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps"
1927 OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver,skippgpcheck"
1928 OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps"
1929 OPT_LONG+=",repackage,skipchecksums,skipinteg,skippgpcheck,sign,source,syncdeps"
1930 OPT_LONG+=",version,config:"
1932 # Pacman Options
1933 OPT_LONG+=",noconfirm,noprogressbar"
1934 if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then
1935 echo; usage; exit 1 # E_INVALID_OPTION;
1937 eval set -- "$OPT_TEMP"
1938 unset OPT_SHORT OPT_LONG OPT_TEMP
1940 while true; do
1941 case "$1" in
1942 # Pacman Options
1943 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
1944 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
1946 # Makepkg Options
1947 --allsource) SOURCEONLY=2 ;;
1948 --asroot) ASROOT=1 ;;
1949 -A|--ignorearch) IGNOREARCH=1 ;;
1950 -c|--clean) CLEANUP=1 ;;
1951 --check) RUN_CHECK='y' ;;
1952 --config) shift; MAKEPKG_CONF=$1 ;;
1953 -d|--nodeps) NODEPS=1 ;;
1954 -e|--noextract) NOEXTRACT=1 ;;
1955 -f|--force) FORCE=1 ;;
1956 #hidden opt used by fakeroot call for svn/cvs/etc PKGBUILDs to set pkgver
1957 --forcever) shift; FORCE_VER=$1;;
1958 -F) INFAKEROOT=1 ;;
1959 -g|--geninteg) GENINTEG=1 ;;
1960 --holdver) HOLDVER=1 ;;
1961 -i|--install) INSTALL=1 ;;
1962 --key) shift; GPGKEY=$1 ;;
1963 -L|--log) LOGGING=1 ;;
1964 -m|--nocolor) USE_COLOR='n' ;;
1965 --nocheck) RUN_CHECK='n' ;;
1966 --nosign) SIGNPKG='n' ;;
1967 -o|--nobuild) NOBUILD=1 ;;
1968 -p) shift; BUILDFILE=$1 ;;
1969 --pkg) shift; PKGLIST=($1) ;;
1970 -r|--rmdeps) RMDEPS=1 ;;
1971 -R|--repackage) REPKG=1 ;;
1972 --skipchecksums) SKIPCHECKSUMS=1 ;;
1973 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
1974 --skippgpcheck) SKIPPGPCHECK=1;;
1975 --sign) SIGNPKG='y' ;;
1976 -s|--syncdeps) DEP_BIN=1 ;;
1977 -S|--source) SOURCEONLY=1 ;;
1979 -h|--help) usage; exit 0 ;; # E_OK
1980 -V|--version) version; exit 0 ;; # E_OK
1982 --) OPT_IND=0; shift; break;;
1983 *) usage; exit 1 ;; # E_INVALID_OPTION
1984 esac
1985 shift
1986 done
1988 # setup signal traps
1989 trap 'clean_up' 0
1990 for signal in TERM HUP QUIT; do
1991 trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
1992 done
1993 trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT
1994 trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR
1995 set -E
1997 # preserve environment variables and canonicalize path
1998 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
1999 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
2000 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
2001 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
2002 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
2003 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
2004 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
2005 [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
2007 # default config is makepkg.conf
2008 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
2010 # Source the config file; fail if it is not found
2011 if [[ -r $MAKEPKG_CONF ]]; then
2012 source "$MAKEPKG_CONF"
2013 else
2014 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
2015 plain "$(gettext "Aborting...")"
2016 exit 1 # $E_CONFIG_ERROR
2019 # Source user-specific makepkg.conf overrides, but only if no override config
2020 # file was specified
2021 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
2022 source ~/.makepkg.conf
2025 # set pacman command if not already defined
2026 PACMAN=${PACMAN:-pacman}
2028 # check if messages are to be printed using color
2029 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2030 if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then
2031 # prefer terminal safe colored and bold text when tput is supported
2032 if tput setaf 0 &>/dev/null; then
2033 ALL_OFF="$(tput sgr0)"
2034 BOLD="$(tput bold)"
2035 BLUE="${BOLD}$(tput setaf 4)"
2036 GREEN="${BOLD}$(tput setaf 2)"
2037 RED="${BOLD}$(tput setaf 1)"
2038 YELLOW="${BOLD}$(tput setaf 3)"
2039 else
2040 ALL_OFF="\e[1;0m"
2041 BOLD="\e[1;1m"
2042 BLUE="${BOLD}\e[1;34m"
2043 GREEN="${BOLD}\e[1;32m"
2044 RED="${BOLD}\e[1;31m"
2045 YELLOW="${BOLD}\e[1;33m"
2048 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2050 # override settings with an environment variable for batch processing
2051 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2052 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2053 if [[ ! -d $BUILDDIR ]]; then
2054 if ! mkdir -p "$BUILDDIR"; then
2055 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2056 plain "$(gettext "Aborting...")"
2057 exit 1
2059 chmod a-s "$BUILDDIR"
2061 if [[ ! -w $BUILDDIR ]]; then
2062 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2063 plain "$(gettext "Aborting...")"
2064 exit 1
2067 PKGDEST=${_PKGDEST:-$PKGDEST}
2068 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2069 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2070 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2071 plain "$(gettext "Aborting...")"
2072 exit 1
2075 SRCDEST=${_SRCDEST:-$SRCDEST}
2076 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2077 if [[ ! -w $SRCDEST ]] ; then
2078 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2079 plain "$(gettext "Aborting...")"
2080 exit 1
2083 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2084 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2085 if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then
2086 error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
2087 plain "$(gettext "Aborting...")"
2088 exit 1
2091 PKGEXT=${_PKGEXT:-$PKGEXT}
2092 SRCEXT=${_SRCEXT:-$SRCEXT}
2093 GPGKEY=${_GPGKEY:-$GPGKEY}
2094 PACKAGER=${_PACKAGER:-$PACKAGER}
2096 if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then
2097 # The '\\0' is here to prevent gettext from thinking --holdver is an option
2098 error "$(gettext "\\0%s and %s cannot both be specified" )" "--holdver" "--forcever"
2099 exit 1
2102 if (( ! INFAKEROOT )); then
2103 if (( EUID == 0 && ! ASROOT )); then
2104 # Warn those who like to live dangerously.
2105 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2106 catastrophic damage to your system. If you wish to run as root, please\n\
2107 use the %s option.")" "makepkg" "--asroot"
2108 exit 1 # $E_USER_ABORT
2109 elif (( EUID > 0 && ASROOT )); then
2110 # Warn those who try to use the --asroot option when they are not root
2111 error "$(gettext "The %s option is meant for the root user only. Please\n\
2112 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2113 exit 1 # $E_USER_ABORT
2114 elif (( EUID > 0 )) && [[ $(check_buildenv fakeroot) != "y" ]]; then
2115 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2116 ownership of the packaged files. Try using the %s environment by\n\
2117 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2118 sleep 1
2120 else
2121 if [[ -z $FAKEROOTKEY ]]; then
2122 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2123 exit 1 # TODO: error code
2127 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2128 unset md5sums replaces depends conflicts backup source install changelog build
2129 unset makedepends optdepends options noextract
2131 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2132 if [[ ! -f $BUILDFILE ]]; then
2133 if [[ -t 0 ]]; then
2134 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2135 exit 1
2136 else
2137 # PKGBUILD passed through a pipe
2138 BUILDFILE=/dev/stdin
2139 shopt -u extglob
2140 source "$BUILDFILE"
2141 shopt -s extglob
2143 else
2144 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2145 if [[ -n $crlftest ]]; then
2146 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2147 exit 1
2150 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2151 BUILDFILE="$startdir/$BUILDFILE"
2153 shopt -u extglob
2154 source "$BUILDFILE"
2155 shopt -s extglob
2158 # set defaults if they weren't specified in buildfile
2159 pkgbase=${pkgbase:-${pkgname[0]}}
2160 epoch=${epoch:-0}
2162 if [[ $BUILDDIR = "$startdir" ]]; then
2163 srcdir="$BUILDDIR/src"
2164 pkgdir="$BUILDDIR/pkg"
2165 else
2166 srcdir="$BUILDDIR/$pkgbase/src"
2167 pkgdir="$BUILDDIR/$pkgbase/pkg"
2170 if (( GENINTEG )); then
2171 mkdir -p "$srcdir"
2172 chmod a-s "$srcdir"
2173 cd "$srcdir"
2174 download_sources
2175 generate_checksums
2176 exit 0 # $E_OK
2179 # check the PKGBUILD for some basic requirements
2180 check_sanity || exit 1
2182 # check we have the software required to process the PKGBUILD
2183 check_software || exit 1
2185 # We need to run devel_update regardless of whether we are in the fakeroot
2186 # build process so that if the user runs makepkg --forcever manually, we
2187 # 1) output the correct pkgver, and 2) use the correct filename when
2188 # checking if the package file already exists - fixes FS #9194
2189 devel_check
2190 devel_update
2192 if (( ${#pkgname[@]} > 1 )); then
2193 SPLITPKG=1
2196 # test for available PKGBUILD functions
2197 if declare -f build >/dev/null; then
2198 BUILDFUNC=1
2200 if declare -f check >/dev/null; then
2201 # "Hide" check() function if not going to be run
2202 if [[ $RUN_CHECK = 'y' || (! $(check_buildenv check) = "n" && ! $RUN_CHECK = "n") ]]; then
2203 CHECKFUNC=1
2206 if declare -f package >/dev/null; then
2207 PKGFUNC=1
2208 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2209 SPLITPKG=1
2212 if [[ -n "${PKGLIST[@]}" ]]; then
2213 unset pkgname
2214 pkgname=("${PKGLIST[@]}")
2217 # check if gpg signature is to be created and if signing key is valid
2218 [[ -z $SIGNPKG ]] && SIGNPKG=$(check_buildenv sign)
2219 if [[ $SIGNPKG == 'y' ]]; then
2220 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2221 if [[ ! -z $GPGKEY ]]; then
2222 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2223 else
2224 error "$(gettext "There is no key in your keyring.")"
2226 exit 1
2231 if (( ! SPLITPKG )); then
2232 fullver=$(get_full_version)
2233 if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \
2234 || -f $PKGDEST/${pkgname}-${fullver}-any${PKGEXT} ]] \
2235 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2236 if (( INSTALL )); then
2237 warning "$(gettext "A package has already been built, installing existing package...")"
2238 install_package
2239 exit $?
2240 else
2241 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2242 exit 1
2245 else
2246 allpkgbuilt=1
2247 somepkgbuilt=0
2248 for pkg in ${pkgname[@]}; do
2249 fullver=$(get_full_version $pkg)
2250 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} \
2251 || -f $PKGDEST/${pkg}-${fullver}-any${PKGEXT} ]]; then
2252 somepkgbuilt=1
2253 else
2254 allpkgbuilt=0
2256 done
2257 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2258 if (( allpkgbuilt )); then
2259 if (( INSTALL )); then
2260 warning "$(gettext "The package group has already been built, installing existing packages...")"
2261 install_package
2262 exit $?
2263 else
2264 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2265 exit 1
2268 if (( somepkgbuilt )); then
2269 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2270 exit 1
2273 unset allpkgbuilt somepkgbuilt
2276 # Run the bare minimum in fakeroot
2277 if (( INFAKEROOT )); then
2278 if (( SOURCEONLY )); then
2279 create_srcpackage
2280 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2281 exit 0 # $E_OK
2284 if (( ! SPLITPKG )); then
2285 if (( ! PKGFUNC )); then
2286 if (( ! REPKG )); then
2287 if (( BUILDFUNC )); then
2288 run_build
2289 (( CHECKFUNC )) && run_check
2290 tidy_install
2292 else
2293 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2294 plain "$(gettext "File permissions may not be preserved.")"
2296 else
2297 run_package
2298 tidy_install
2300 create_package
2301 else
2302 run_split_packaging
2305 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2306 exit 0 # $E_OK
2309 fullver=$(get_full_version)
2310 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2312 # if we are creating a source-only package, go no further
2313 if (( SOURCEONLY )); then
2314 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2315 && (( ! FORCE )); then
2316 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2317 exit 1
2320 # Get back to our src directory so we can begin with sources.
2321 mkdir -p "$srcdir"
2322 chmod a-s "$srcdir"
2323 cd "$srcdir"
2324 if ( (( ! SKIPCHECKSUMS )) || \
2325 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \
2326 (( SOURCEONLY == 2 )); then
2327 download_sources
2329 check_source_integrity
2330 cd "$startdir"
2332 # if we are root or if fakeroot is not enabled, then we don't use it
2333 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2334 create_srcpackage
2335 else
2336 enter_fakeroot
2339 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2340 exit 0
2343 if (( NODEPS || ( (NOBUILD || REPKG) && !DEP_BIN ) )); then
2344 # no warning message needed for nobuild, repkg
2345 if (( NODEPS || ( REPKG && PKGFUNC ) )); then
2346 warning "$(gettext "Skipping dependency checks.")"
2348 elif type -p "${PACMAN%% *}" >/dev/null; then
2349 if (( RMDEPS && ! INSTALL )); then
2350 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2352 deperr=0
2354 msg "$(gettext "Checking runtime dependencies...")"
2355 resolve_deps ${depends[@]} || deperr=1
2357 if (( RMDEPS && INSTALL )); then
2358 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2361 msg "$(gettext "Checking buildtime dependencies...")"
2362 resolve_deps ${makedepends[@]} || deperr=1
2364 if (( CHECKFUNC )); then
2365 resolve_deps ${checkdepends[@]} || deperr=1
2368 if (( RMDEPS )); then
2369 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2372 if (( deperr )); then
2373 error "$(gettext "Could not resolve all dependencies.")"
2374 exit 1
2376 else
2377 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2380 # ensure we have a sane umask set
2381 umask 0022
2383 # get back to our src directory so we can begin with sources
2384 mkdir -p "$srcdir"
2385 chmod a-s "$srcdir"
2386 cd "$srcdir"
2388 if (( NOEXTRACT )); then
2389 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2390 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2391 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2393 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2394 error "$(gettext "The source directory is empty, there is nothing to build!")"
2395 plain "$(gettext "Aborting...")"
2396 exit 1
2398 elif (( REPKG )); then
2399 if (( ! PKGFUNC && ! SPLITPKG )) \
2400 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2401 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2402 plain "$(gettext "Aborting...")"
2403 exit 1
2405 else
2406 download_sources
2407 check_source_integrity
2408 extract_sources
2411 if (( NOBUILD )); then
2412 msg "$(gettext "Sources are ready.")"
2413 exit 0 #E_OK
2414 else
2415 # check for existing pkg directory; don't remove if we are repackaging
2416 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2417 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2418 rm -rf "$pkgdir"
2420 mkdir -p "$pkgdir"
2421 chmod a-s "$pkgdir"
2422 cd "$startdir"
2424 # if we are root or if fakeroot is not enabled, then we don't use it
2425 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2426 if (( ! REPKG )); then
2427 devel_update
2428 (( BUILDFUNC )) && run_build
2429 (( CHECKFUNC )) && run_check
2431 if (( ! SPLITPKG )); then
2432 if (( PKGFUNC )); then
2433 run_package
2434 tidy_install
2435 else
2436 if (( ! REPKG )); then
2437 tidy_install
2438 else
2439 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2440 plain "$(gettext "File permissions may not be preserved.")"
2443 create_package
2444 else
2445 run_split_packaging
2447 else
2448 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2449 devel_update
2450 (( BUILDFUNC )) && run_build
2451 (( CHECKFUNC )) && run_check
2452 cd "$startdir"
2455 enter_fakeroot
2459 fullver=$(get_full_version)
2460 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2462 install_package
2464 exit 0 #E_OK
2466 # vim: set ts=2 sw=2 noet: