makepkg: enforce decimal format for pkgrel
[pacman-ng.git] / scripts / makepkg.sh.in
blob14e2f6a00bea4eddd639efb31610193a109ccfe2
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 if (( ! INFAKEROOT )); then
122 echo
123 error "$@"
125 [[ -n $srclinks ]] && rm -rf "$srclinks"
126 exit 1
131 # Clean up function. Called automatically when the script exits.
133 clean_up() {
134 local EXIT_CODE=$?
136 if (( INFAKEROOT )); then
137 # Don't clean up when leaving fakeroot, we're not done yet.
138 return
141 if (( ! EXIT_CODE && CLEANUP )); then
142 local pkg file
144 # If it's a clean exit and -c/--clean has been passed...
145 msg "$(gettext "Cleaning up...")"
146 rm -rf "$pkgdir" "$srcdir"
147 if [[ -n $pkgbase ]]; then
148 local fullver=$(get_full_version)
149 # Can't do this unless the BUILDSCRIPT has been sourced.
150 if (( BUILDFUNC )); then
151 rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"*
153 if (( CHECKFUNC )); then
154 rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
156 if (( PKGFUNC )); then
157 rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
158 elif (( SPLITPKG )); then
159 for pkg in ${pkgname[@]}; do
160 rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"*
161 done
164 # clean up dangling symlinks to packages
165 for pkg in ${pkgname[@]}; do
166 for file in ${pkg}-*-*-${CARCH}{${PKGEXT},${SRCEXT}}; do
167 if [[ -h $file && ! -e $file ]]; then
168 rm -f $file
170 done
171 done
175 remove_deps
179 enter_fakeroot() {
180 msg "$(gettext "Entering %s environment...")" "fakeroot"
182 if [[ -n $newpkgver ]]; then
183 fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $?
184 else
185 fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
190 # a source entry can have two forms :
191 # 1) "filename::http://path/to/file"
192 # 2) "http://path/to/file"
194 # Return the absolute filename of a source entry
196 # This function accepts a source entry or the already extracted filename of a
197 # source entry as input
198 get_filepath() {
199 local file="$(get_filename "$1")"
201 if [[ -f "$startdir/$file" ]]; then
202 file="$startdir/$file"
203 elif [[ -f "$SRCDEST/$file" ]]; then
204 file="$SRCDEST/$file"
205 else
206 return 1
209 echo "$file"
212 # Print 'source not found' error message and exit makepkg
213 missing_source_file() {
214 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
215 plain "$(gettext "Aborting...")"
216 exit 1 # $E_MISSING_FILE
219 # extract the filename from a source entry
220 get_filename() {
221 # if a filename is specified, use it
222 local filename="${1%%::*}"
223 # if it is just an URL, we only keep the last component
224 echo "${filename##*/}"
227 # extract the URL from a source entry
228 get_url() {
229 # strip an eventual filename
230 echo "${1#*::}"
234 # usage : get_full_version( [$pkgname] )
235 # return : full version spec, including epoch (if necessary), pkgver, pkgrel
237 get_full_version() {
238 if [[ -z $1 ]]; then
239 if [[ $epoch ]] && (( ! $epoch )); then
240 echo $pkgver-$pkgrel
241 else
242 echo $epoch:$pkgver-$pkgrel
244 else
245 for i in pkgver pkgrel epoch; do
246 local indirect="${i}_override"
247 eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
248 [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
249 done
250 if (( ! $epoch_override )); then
251 echo $pkgver_override-$pkgrel_override
252 else
253 echo $epoch_override:$pkgver_override-$pkgrel_override
259 # Checks to see if options are present in makepkg.conf or PKGBUILD;
260 # PKGBUILD options always take precedence.
262 # usage : check_option( $option )
263 # return : y - enabled
264 # n - disabled
265 # ? - not found
267 check_option() {
268 local ret=$(in_opt_array "$1" ${options[@]})
269 if [[ $ret != '?' ]]; then
270 echo $ret
271 return
274 # fall back to makepkg.conf options
275 ret=$(in_opt_array "$1" ${OPTIONS[@]})
276 if [[ $ret != '?' ]]; then
277 echo $ret
278 return
281 echo '?' # Not Found
286 # Check if option is present in BUILDENV
288 # usage : check_buildenv( $option )
289 # return : y - enabled
290 # n - disabled
291 # ? - not found
293 check_buildenv() {
294 in_opt_array "$1" ${BUILDENV[@]}
299 # usage : in_opt_array( $needle, $haystack )
300 # return : y - enabled
301 # n - disabled
302 # ? - not found
304 in_opt_array() {
305 local needle=$1; shift
307 local opt
308 for opt in "$@"; do
309 if [[ $opt = $needle ]]; then
310 echo 'y' # Enabled
311 return
312 elif [[ $opt = "!$needle" ]]; then
313 echo 'n' # Disabled
314 return
316 done
318 echo '?' # Not Found
323 # usage : in_array( $needle, $haystack )
324 # return : 0 - found
325 # 1 - not found
327 in_array() {
328 local needle=$1; shift
329 local item
330 for item in "$@"; do
331 [[ $item = $needle ]] && return 0 # Found
332 done
333 return 1 # Not Found
336 source_has_signatures() {
337 local file
338 for file in "${source[@]}"; do
339 if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
340 return 0
342 done
343 return 1
346 get_downloadclient() {
347 # $1 = URL with valid protocol prefix
348 local url=$1
349 local proto="${url%%://*}"
351 # loop through DOWNLOAD_AGENTS variable looking for protocol
352 local i
353 for i in "${DLAGENTS[@]}"; do
354 local handler="${i%%::*}"
355 if [[ $proto = $handler ]]; then
356 local agent="${i##*::}"
357 break
359 done
361 # if we didn't find an agent, return an error
362 if [[ -z $agent ]]; then
363 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
364 plain "$(gettext "Aborting...")"
365 exit 1 # $E_CONFIG_ERROR
368 # ensure specified program is installed
369 local program="${agent%% *}"
370 if [[ ! -x $program ]]; then
371 local baseprog="${program##*/}"
372 error "$(gettext "The download program %s is not installed.")" "$baseprog"
373 plain "$(gettext "Aborting...")"
374 exit 1 # $E_MISSING_PROGRAM
377 echo "$agent"
380 download_file() {
381 # download command
382 local dlcmd=$1
383 # URL of the file
384 local url=$2
385 # destination file
386 local file=$3
387 # temporary download file, default to last component of the URL
388 local dlfile="${url##*/}"
390 # replace %o by the temporary dlfile if it exists
391 if [[ $dlcmd = *%o* ]]; then
392 dlcmd=${dlcmd//\%o/\"$file.part\"}
393 dlfile="$file.part"
395 # add the URL, either in place of %u or at the end
396 if [[ $dlcmd = *%u* ]]; then
397 dlcmd=${dlcmd//\%u/\"$url\"}
398 else
399 dlcmd="$dlcmd \"$url\""
402 local ret=0
403 eval "$dlcmd || ret=\$?"
404 if (( ret )); then
405 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
406 return $ret
409 # rename the temporary download file to the final destination
410 if [[ $dlfile != "$file" ]]; then
411 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$file"
415 run_pacman() {
416 local cmd
417 if [[ ! $1 = -@(T|Qq) ]]; then
418 printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@"
419 else
420 printf -v cmd "%q " "$PACMAN" "$@"
422 if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then
423 if type -p sudo >/dev/null; then
424 cmd="sudo $cmd"
425 else
426 cmd="su root -c '$cmd'"
429 eval "$cmd"
432 check_deps() {
433 (( $# > 0 )) || return 0
435 # Disable error trap in pacman subshell call as this breaks bash-3.2 compatibility
436 # Also, a non-zero return value is not unexpected and we are manually dealing them
437 set +E
438 local ret=0
439 local pmout
440 pmout=$(run_pacman -T "$@") || ret=$?
441 set -E
443 if (( ret == 127 )); then #unresolved deps
444 echo "$pmout"
445 elif (( ret )); then
446 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
447 return "$ret"
451 handle_deps() {
452 local R_DEPS_SATISFIED=0
453 local R_DEPS_MISSING=1
455 (( $# == 0 )) && return $R_DEPS_SATISFIED
457 local deplist="$*"
459 if (( ! DEP_BIN )); then
460 return $R_DEPS_MISSING
463 if (( DEP_BIN )); then
464 # install missing deps from binary packages (using pacman -S)
465 msg "$(gettext "Installing missing dependencies...")"
467 if ! run_pacman -S --asdeps $deplist; then
468 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
469 exit 1 # TODO: error code
473 # we might need the new system environment
474 # avoid triggering the ERR trap and exiting
475 set +e
476 local restoretrap=$(trap -p ERR)
477 trap - ERR
478 source /etc/profile &>/dev/null
479 eval $restoretrap
480 set -e
482 return $R_DEPS_SATISFIED
485 resolve_deps() {
486 local R_DEPS_SATISFIED=0
487 local R_DEPS_MISSING=1
489 # deplist cannot be declared like this: local deplist=$(foo)
490 # Otherwise, the return value will depend on the assignment.
491 local deplist
492 deplist="$(set +E; check_deps $*)" || exit 1
493 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
495 if handle_deps $deplist; then
496 # check deps again to make sure they were resolved
497 deplist="$(set +E; check_deps $*)" || exit 1
498 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
501 msg "$(gettext "Missing Dependencies:")"
502 local dep
503 for dep in $deplist; do
504 msg2 "$dep"
505 done
507 return $R_DEPS_MISSING
510 remove_deps() {
511 (( ! RMDEPS )) && return
513 # check for packages removed during dependency install (e.g. due to conflicts)
514 # removing all installed packages is risky in this case
515 if [[ -n $(grep -xvFf <(printf '%s\n' "${current_packagelist[@]}") \
516 <(printf '%s\n' "${original_packagelist[@]}") || true) ]]; then
517 warning "$(gettext "Failed to remove installed dependencies.")"
518 return 0
521 local deplist
522 deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \
523 <(printf "%s\n" "${current_pkglist[@]}") || true))
524 if [[ -z $deplist ]]; then
525 return
528 msg "Removing installed dependencies..."
529 # exit cleanly on failure to remove deps as package has been built successfully
530 if ! run_pacman -Rn ${deplist[@]}; then
531 warning "$(gettext "Failed to remove installed dependencies.")"
532 return 0
536 download_sources() {
537 msg "$(gettext "Retrieving Sources...")"
539 pushd "$SRCDEST" &>/dev/null
541 local netfile
542 for netfile in "${source[@]}"; do
543 local file=$(get_filepath "$netfile" || true)
544 if [[ -n "$file" ]]; then
545 msg2 "$(gettext "Found %s")" "${file##*/}"
546 rm -f "$srcdir/${file##*/}"
547 ln -s "$file" "$srcdir/"
548 continue
551 file=$(get_filename "$netfile")
552 local url=$(get_url "$netfile")
554 # if we get here, check to make sure it was a URL, else fail
555 if [[ $file = $url ]]; then
556 error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file"
557 exit 1 # $E_MISSING_FILE
560 # find the client we should use for this URL
561 local dlclient
562 dlclient=$(get_downloadclient "$url") || exit $?
564 msg2 "$(gettext "Downloading %s...")" "$file"
565 # fix flyspray bug #3289
566 local ret=0
567 download_file "$dlclient" "$url" "$file" || ret=$?
568 if (( ret )); then
569 error "$(gettext "Failure while downloading %s")" "$file"
570 plain "$(gettext "Aborting...")"
571 exit 1
573 rm -f "$srcdir/$file"
574 ln -s "$SRCDEST/$file" "$srcdir/"
575 done
577 popd &>/dev/null
580 get_integlist() {
581 local integ
582 local integlist=()
584 for integ in md5 sha1 sha256 sha384 sha512; do
585 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
586 if [[ -n "$integrity_sums" ]]; then
587 integlist=(${integlist[@]} $integ)
589 done
591 if (( ${#integlist[@]} > 0 )); then
592 echo ${integlist[@]}
593 else
594 echo ${INTEGRITY_CHECK[@]}
598 generate_checksums() {
599 msg "$(gettext "Generating checksums for source files...")"
600 plain ""
602 if ! type -p openssl >/dev/null; then
603 error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
604 exit 1 # $E_MISSING_PROGRAM
607 local integlist
608 if (( $# == 0 )); then
609 integlist=$(get_integlist)
610 else
611 integlist=$@
614 local integ
615 for integ in ${integlist[@]}; do
616 case "$integ" in
617 md5|sha1|sha256|sha384|sha512) : ;;
619 error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
620 exit 1;; # $E_CONFIG_ERROR
621 esac
623 local ct=0
624 local numsrc=${#source[@]}
625 echo -n "${integ}sums=("
627 local i
628 local indent=''
629 for (( i = 0; i < ${#integ} + 6; i++ )); do
630 indent="$indent "
631 done
633 local netfile
634 for netfile in "${source[@]}"; do
635 local file
636 file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
637 local sum="$(openssl dgst -${integ} "$file")"
638 sum=${sum##* }
639 (( ct )) && echo -n "$indent"
640 echo -n "'$sum'"
641 ct=$(($ct+1))
642 (( $ct < $numsrc )) && echo
643 done
645 echo ")"
646 done
649 check_checksums() {
650 (( SKIPCHECKSUMS )) && return 0
651 (( ! ${#source[@]} )) && return 0
653 local correlation=0
654 local integ required
655 for integ in md5 sha1 sha256 sha384 sha512; do
656 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
657 if (( ${#integrity_sums[@]} == ${#source[@]} )); then
658 msg "$(gettext "Validating source files with %s...")" "${integ}sums"
659 correlation=1
660 local errors=0
661 local idx=0
662 local file
663 for file in "${source[@]}"; do
664 local found=1
665 file="$(get_filename "$file")"
666 echo -n " $file ... " >&2
668 if ! file="$(get_filepath "$file")"; then
669 printf -- "$(gettext "NOT FOUND")\n" >&2
670 errors=1
671 found=0
674 if (( $found )) ; then
675 if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then
676 echo "$(gettext "Skipped")" >&2
677 else
678 local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}")
679 local realsum="$(openssl dgst -${integ} "$file")"
680 realsum="${realsum##* }"
681 if [[ $expectedsum = $realsum ]]; then
682 printf -- "$(gettext "Passed")\n" >&2
683 else
684 printf -- "$(gettext "FAILED")\n" >&2
685 errors=1
690 idx=$((idx + 1))
691 done
693 if (( errors )); then
694 error "$(gettext "One or more files did not pass the validity check!")"
695 exit 1 # TODO: error code
697 elif (( ${#integrity_sums[@]} )); then
698 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
699 exit 1 # TODO: error code
701 done
703 if (( ! correlation )); then
704 error "$(gettext "Integrity checks are missing.")"
705 exit 1 # TODO: error code
709 check_pgpsigs() {
710 (( SKIPPGPCHECK )) && return 0
711 ! source_has_signatures && return 0
713 msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
715 local file pubkey
716 local warning=0
717 local errors=0
718 local statusfile=$(mktemp)
720 for file in "${source[@]}"; do
721 file="$(get_filename "$file")"
722 if [[ ! $file = *.@(sig?(n)|asc) ]]; then
723 continue
726 printf " %s ... " "${file%.*}" >&2
728 if ! file="$(get_filepath "$file")"; then
729 printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
730 errors=1
731 continue
734 if ! sourcefile="$(get_filepath "${file%.*}")"; then
735 printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
736 errors=1
737 continue
740 if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
741 printf '%s' "$(gettext "FAILED")" >&2
742 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then
743 printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
744 warnings=1
745 else
746 errors=1
748 printf '\n' >&2
749 else
750 if grep -q "REVKEYSIG" "$statusfile"; then
751 printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2
752 errors=1
753 else
754 printf '%s' "$(gettext "Passed")" >&2
755 if grep -q "EXPSIG" "$statusfile"; then
756 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
757 warnings=1
758 elif grep -q "EXPKEYSIG" "$statusfile"; then
759 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
760 warnings=1
763 printf '\n' >&2
765 done
767 rm -f "$statusfile"
769 if (( errors )); then
770 error "$(gettext "One or more PGP signatures could not be verified!")"
771 exit 1
774 if (( warnings )); then
775 warning "$(gettext "Warnings have occurred while verifying the signatures.")"
776 plain "$(gettext "Please make sure you really trust them.")"
780 check_source_integrity() {
781 if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
782 warning "$(gettext "Skipping all source file integrity checks.")"
783 elif (( SKIPCHECKSUMS )); then
784 warning "$(gettext "Skipping verification of source file checksums.")"
785 check_pgpsigs
786 elif (( SKIPPGPCHECK )); then
787 warning "$(gettext "Skipping verification of source file PGP signatures.")"
788 check_checksums
789 else
790 check_checksums
791 check_pgpsigs
795 extract_sources() {
796 msg "$(gettext "Extracting Sources...")"
797 local netfile
798 for netfile in "${source[@]}"; do
799 local file=$(get_filename "$netfile")
800 if in_array "$file" "${noextract[@]}"; then
801 #skip source files in the noextract=() array
802 # these are marked explicitly to NOT be extracted
803 continue
807 # fix flyspray #6246
808 local file_type=$(file -bizL "$file")
809 local ext=${file##*.}
810 local cmd=''
811 case "$file_type" in
812 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
813 cmd="bsdtar" ;;
814 *application/x-gzip*)
815 case "$ext" in
816 gz|z|Z) cmd="gzip" ;;
817 *) continue;;
818 esac ;;
819 *application/x-bzip*)
820 case "$ext" in
821 bz2|bz) cmd="bzip2" ;;
822 *) continue;;
823 esac ;;
824 *application/x-xz*)
825 case "$ext" in
826 xz) cmd="xz" ;;
827 *) continue;;
828 esac ;;
830 # See if bsdtar can recognize the file
831 if bsdtar -tf "$file" -q '*' &>/dev/null; then
832 cmd="bsdtar"
833 else
834 continue
835 fi ;;
836 esac
838 local ret=0
839 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
840 if [[ $cmd = bsdtar ]]; then
841 $cmd -xf "$file" || ret=$?
842 else
843 rm -f "${file%.*}"
844 $cmd -dcf "$file" > "${file%.*}" || ret=$?
846 if (( ret )); then
847 error "$(gettext "Failed to extract %s")" "$file"
848 plain "$(gettext "Aborting...")"
849 exit 1
851 done
853 if (( EUID == 0 )); then
854 # change perms of all source files to root user & root group
855 chown -R 0:0 "$srcdir"
859 error_function() {
860 if [[ -p $logpipe ]]; then
861 rm "$logpipe"
863 # first exit all subshells, then print the error
864 if (( ! BASH_SUBSHELL )); then
865 error "$(gettext "A failure occurred in %s().")" "$1"
866 plain "$(gettext "Aborting...")"
867 remove_deps
869 exit 2 # $E_BUILD_FAILED
872 run_function() {
873 if [[ -z $1 ]]; then
874 return 1
876 local pkgfunc="$1"
878 # clear user-specified buildflags if requested
879 if [[ $(check_option buildflags) = "n" ]]; then
880 unset CFLAGS CXXFLAGS LDFLAGS
883 # clear user-specified makeflags if requested
884 if [[ $(check_option makeflags) = "n" ]]; then
885 unset MAKEFLAGS
888 msg "$(gettext "Starting %s()...")" "$pkgfunc"
889 cd "$srcdir"
891 # ensure all necessary build variables are exported
892 export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
893 # save our shell options so pkgfunc() can't override what we need
894 local shellopts=$(shopt -p)
896 local ret=0
897 local restoretrap
898 if (( LOGGING )); then
899 local fullver=$(get_full_version)
900 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
901 if [[ -f $BUILDLOG ]]; then
902 local i=1
903 while true; do
904 if [[ -f $BUILDLOG.$i ]]; then
905 i=$(($i +1))
906 else
907 break
909 done
910 mv "$BUILDLOG" "$BUILDLOG.$i"
913 # ensure overridden package variables survive tee with split packages
914 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
915 mkfifo "$logpipe"
916 tee "$BUILDLOG" < "$logpipe" &
917 local teepid=$!
919 restoretrap=$(trap -p ERR)
920 trap 'error_function $pkgfunc' ERR
921 $pkgfunc &>"$logpipe"
922 eval $restoretrap
924 wait $teepid
925 rm "$logpipe"
926 else
927 restoretrap=$(trap -p ERR)
928 trap 'error_function $pkgfunc' ERR
929 $pkgfunc 2>&1
930 eval $restoretrap
932 # reset our shell options
933 eval "$shellopts"
936 run_build() {
937 # use distcc if it is requested (check buildenv and PKGBUILD opts)
938 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
939 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
940 export DISTCC_HOSTS
943 # use ccache if it is requested (check buildenv and PKGBUILD opts)
944 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
945 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
948 run_function "build"
951 run_check() {
952 run_function "check"
955 run_package() {
956 local pkgfunc
957 if [[ -z $1 ]]; then
958 pkgfunc="package"
959 else
960 pkgfunc="package_$1"
963 run_function "$pkgfunc"
966 tidy_install() {
967 cd "$pkgdir"
968 msg "$(gettext "Tidying install...")"
970 if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then
971 msg2 "$(gettext "Removing doc files...")"
972 rm -rf ${DOC_DIRS[@]}
975 if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then
976 msg2 "$(gettext "Purging unwanted files...")"
977 local pt
978 for pt in "${PURGE_TARGETS[@]}"; do
979 if [[ ${pt} = ${pt//\/} ]]; then
980 find . -type f -name "${pt}" -exec rm -f -- '{}' \;
981 else
982 rm -f ${pt}
984 done
987 if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then
988 msg2 "$(gettext "Compressing man and info pages...")"
989 local manpage ext file link hardlinks hl
990 find ${MAN_DIRS[@]} -type f 2>/dev/null |
991 while read manpage ; do
992 ext="${manpage##*.}"
993 file="${manpage##*/}"
994 if [[ $ext != gz && $ext != bz2 ]]; then
995 # update symlinks to this manpage
996 find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null |
997 while read link ; do
998 rm -f "$link" "${link}.gz"
999 ln -s "${file}.gz" "${link}.gz"
1000 done
1002 # check file still exists (potentially already compressed due to hardlink)
1003 if [[ -f ${manpage} ]]; then
1004 # find hard links and remove them
1005 # the '|| true' part keeps the script from bailing on the EOF returned
1006 # by read at the end of the find output
1007 IFS=$'\n' read -rd '' -a hardlinks < \
1008 <(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" \
1009 2>/dev/null || true) || true
1010 rm -f "${hardlinks[@]}"
1011 # compress the original
1012 gzip -9 "$manpage"
1013 # recreate hard links removed earlier
1014 for hl in "${hardlinks[@]}"; do
1015 ln "${manpage}.gz" "${hl}.gz"
1016 chmod 644 ${hl}.gz
1017 done
1020 done
1023 if [[ $(check_option strip) = y ]]; then
1024 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1025 # make sure library stripping variables are defined to prevent excess stripping
1026 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1027 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1028 local binary
1029 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1030 case "$(file -bi "$binary")" in
1031 *application/x-sharedlib*) # Libraries (.so)
1032 strip $STRIP_SHARED "$binary";;
1033 *application/x-archive*) # Libraries (.a)
1034 strip $STRIP_STATIC "$binary";;
1035 *application/x-executable*) # Binaries
1036 strip $STRIP_BINARIES "$binary";;
1037 esac
1038 done
1041 if [[ $(check_option libtool) = "n" ]]; then
1042 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1043 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1046 if [[ $(check_option emptydirs) = "n" ]]; then
1047 msg2 "$(gettext "Removing empty directories...")"
1048 find . -depth -type d -empty -delete
1051 if [[ $(check_option upx) = "y" ]]; then
1052 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1053 local binary
1054 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1055 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1056 upx $UPXFLAGS "$binary" &>/dev/null ||
1057 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1059 done
1063 find_libdepends() {
1064 local libdepends
1065 find "$pkgdir" -type f -perm -u+x | while read filename
1067 # get architecture of the file; if soarch is empty it's not an ELF binary
1068 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1069 [ -n "$soarch" ] || continue
1070 # process all libraries needed by the binary
1071 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1073 # extract the library name: libfoo.so
1074 soname="${sofile%%\.so\.*}.so"
1075 # extract the major version: 1
1076 soversion="${sofile##*\.so\.}"
1077 if in_array "${soname}" ${depends[@]}; then
1078 if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then
1079 # libfoo.so=1-64
1080 echo "${soname}=${soversion}-${soarch}"
1081 libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}")
1084 done
1085 done
1088 find_libprovides() {
1089 local libprovides missing
1090 for p in ${provides[@]}; do
1091 missing=0
1092 case "$p" in
1093 *.so)
1094 local filename=$(find "$pkgdir" -type f -name $p\*)
1095 if [[ $filename ]]; then
1096 # packages may provide multiple versions of the same library
1097 for fn in ${filename[@]}; do
1098 # check if we really have a shared object
1099 if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1100 # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1)
1101 local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1102 if [[ -z "$sofile" ]]; then
1103 warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p"
1104 libprovides=(${libprovides[@]} "$p")
1105 continue
1108 # get the library architecture (32 or 64 bit)
1109 local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1111 # extract the library major version
1112 local soversion="${sofile##*\.so\.}"
1114 libprovides=(${libprovides[@]} "${p}=${soversion}-${soarch}")
1115 else
1116 warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p"
1117 libprovides=(${libprovides[@]} "$p")
1119 done
1120 else
1121 libprovides=(${libprovides[@]} "$p")
1122 missing=1
1126 libprovides=(${libprovides[@]} "$p")
1128 esac
1130 if (( missing )); then
1131 warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p"
1133 done
1135 echo ${libprovides[@]}
1138 check_license() {
1139 # TODO maybe remove this at some point
1140 # warn if license array is not present or empty
1141 if [[ -z $license ]]; then
1142 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1143 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1147 write_pkginfo() {
1148 local builddate=$(date -u "+%s")
1149 if [[ -n $PACKAGER ]]; then
1150 local packager="$PACKAGER"
1151 else
1152 local packager="Unknown Packager"
1154 local size="$(find . -print0 | xargs -0 @SIZECMD@ | awk '{ sum += $1 } END { print sum }')"
1156 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1157 echo "# Generated by makepkg $myver"
1158 if (( INFAKEROOT )); then
1159 echo "# using $(fakeroot -v)"
1161 echo "# $(LC_ALL=C date -u)"
1162 echo "pkgname = $1"
1163 (( SPLITPKG )) && echo pkgbase = $pkgbase
1164 echo "pkgver = $(get_full_version)"
1165 echo "pkgdesc = $pkgdesc"
1166 echo "url = $url"
1167 echo "builddate = $builddate"
1168 echo "packager = $packager"
1169 echo "size = $size"
1170 echo "arch = $PKGARCH"
1172 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1173 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1174 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1175 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1176 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1178 provides=($(find_libprovides))
1179 [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
1181 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1184 local it
1185 libdepends=$(find_libdepends)
1186 depends=("${depends[@]}" ${libdepends})
1188 for it in "${depends[@]}"; do
1189 if [[ $it = *.so ]]; then
1190 # check if the entry has been found by find_libdepends
1191 # if not, it's unneeded; tell the user so he can remove it
1192 if [[ ! $libdepends =~ (^|\s)${it}=.* ]]; then
1193 error "$(gettext "Cannot find library listed in %s: %s")" "'depends'" "$it"
1194 return 1
1196 else
1197 echo "depend = $it"
1199 done
1201 for it in "${packaging_options[@]}"; do
1202 local ret="$(check_option $it)"
1203 if [[ $ret != "?" ]]; then
1204 if [[ $ret = y ]]; then
1205 echo "makepkgopt = $it"
1206 else
1207 echo "makepkgopt = !$it"
1210 done
1212 check_license
1215 check_package() {
1216 cd "$pkgdir"
1218 # check existence of backup files
1219 local file
1220 for file in "${backup[@]}"; do
1221 if [[ ! -f $file ]]; then
1222 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1224 done
1226 # check for references to the build and package directory
1227 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1228 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1230 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1231 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1236 create_package() {
1237 if [[ ! -d $pkgdir ]]; then
1238 error "$(gettext "Missing %s directory.")" "pkg/"
1239 plain "$(gettext "Aborting...")"
1240 exit 1 # $E_MISSING_PKGDIR
1243 check_package
1245 cd "$pkgdir"
1246 msg "$(gettext "Creating package...")"
1248 local nameofpkg
1249 if [[ -z $1 ]]; then
1250 nameofpkg="$pkgname"
1251 else
1252 nameofpkg="$1"
1255 if [[ $arch = "any" ]]; then
1256 PKGARCH="any"
1257 else
1258 PKGARCH=$CARCH
1261 write_pkginfo $nameofpkg > .PKGINFO
1263 local comp_files=".PKGINFO"
1265 # check for changelog/install files
1266 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1267 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1269 if [[ -n ${!orig} ]]; then
1270 msg2 "$(gettext "Adding %s file...")" "$orig"
1271 cp "$startdir/${!orig}" "$dest"
1272 chmod 644 "$dest"
1273 comp_files+=" $dest"
1275 done
1277 # tar it up
1278 msg2 "$(gettext "Compressing package...")"
1280 local fullver=$(get_full_version)
1281 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}"
1282 local ret=0
1284 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1285 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1287 # when fileglobbing, we want * in an empty directory to expand to
1288 # the null string rather than itself
1289 shopt -s nullglob
1290 # TODO: Maybe this can be set globally for robustness
1291 shopt -s -o pipefail
1292 # bsdtar's gzip compression always saves the time stamp, making one
1293 # archive created using the same command line distinct from another.
1294 # Disable bsdtar compression and use gzip -n for now.
1295 bsdtar -cf - $comp_files * |
1296 case "$PKGEXT" in
1297 *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;;
1298 *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;;
1299 *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;;
1300 *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;;
1301 *tar) cat ;;
1302 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1303 "$PKGEXT"; cat ;;
1304 esac > "${pkg_file}" || ret=$?
1306 shopt -u nullglob
1307 shopt -u -o pipefail
1309 if (( ret )); then
1310 error "$(gettext "Failed to create package file.")"
1311 exit 1 # TODO: error code
1314 create_signature "$pkg_file"
1316 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1317 rm -f "${pkg_file/$PKGDEST/$startdir}"
1318 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1319 ret=$?
1320 if [[ -f $pkg_file.sig ]]; then
1321 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1322 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1326 if (( ret )); then
1327 warning "$(gettext "Failed to create symlink to package file.")"
1331 create_signature() {
1332 if [[ $SIGNPKG != 'y' ]]; then
1333 return
1335 local ret=0
1336 local filename="$1"
1337 msg "$(gettext "Signing package...")"
1339 local SIGNWITHKEY=""
1340 if [[ -n $GPGKEY ]]; then
1341 SIGNWITHKEY="-u ${GPGKEY}"
1343 # The signature will be generated directly in ascii-friendly format
1344 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1347 if (( ! ret )); then
1348 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1349 else
1350 warning "$(gettext "Failed to sign package file.")"
1354 create_srcpackage() {
1355 local ret=0
1356 msg "$(gettext "Creating source package...")"
1357 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1358 mkdir "${srclinks}"/${pkgbase}
1360 check_license
1362 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1363 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1365 local file
1366 for file in "${source[@]}"; do
1367 if [[ "$file" == $(get_filename "$file") ]] || (( SOURCEONLY == 2 )); then
1368 local absfile
1369 absfile=$(get_filepath "$file") || missing_source_file "$file"
1370 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1371 ln -s "$absfile" "$srclinks/$pkgbase"
1373 done
1375 local i
1376 for i in 'changelog' 'install'; do
1377 local file
1378 while read -r file; do
1379 # evaluate any bash variables used
1380 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1381 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1382 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1383 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1385 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1386 done
1388 local TAR_OPT
1389 case "$SRCEXT" in
1390 *tar.gz) TAR_OPT="z" ;;
1391 *tar.bz2) TAR_OPT="j" ;;
1392 *tar.xz) TAR_OPT="J" ;;
1393 *tar.Z) TAR_OPT="Z" ;;
1394 *tar) TAR_OPT="" ;;
1395 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1396 "$SRCEXT" ;;
1397 esac
1399 local fullver=$(get_full_version)
1400 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1402 # tar it up
1403 msg2 "$(gettext "Compressing source package...")"
1404 cd "${srclinks}"
1405 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1406 error "$(gettext "Failed to create source package file.")"
1407 exit 1 # TODO: error code
1410 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1411 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1412 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1413 ret=$?
1416 if (( ret )); then
1417 warning "$(gettext "Failed to create symlink to source package file.")"
1420 cd "${startdir}"
1421 rm -rf "${srclinks}"
1424 install_package() {
1425 (( ! INSTALL )) && return
1427 if (( ! SPLITPKG )); then
1428 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1429 else
1430 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1433 local fullver pkg pkglist
1434 for pkg in ${pkgname[@]}; do
1435 fullver=$(get_full_version $pkg)
1436 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} ]]; then
1437 pkglist+=" $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT}"
1438 else
1439 pkglist+=" $PKGDEST/${pkg}-${fullver}-any${PKGEXT}"
1441 done
1443 if ! run_pacman -U $pkglist; then
1444 warning "$(gettext "Failed to install built package(s).")"
1445 return 0
1449 check_sanity() {
1450 # check for no-no's in the build script
1451 local i
1452 local ret=0
1453 for i in 'pkgname' 'pkgrel' 'pkgver'; do
1454 if [[ -z ${!i} ]]; then
1455 error "$(gettext "%s is not allowed to be empty.")" "$i"
1456 ret=1
1458 done
1460 for i in "${pkgname[@]}"; do
1461 if [[ ${i:0:1} = "-" ]]; then
1462 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1463 ret=1
1465 done
1467 if [[ ${pkgbase:0:1} = "-" ]]; then
1468 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1469 ret=1
1472 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1473 while IFS='=' read -r _ i; do
1474 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1475 if [[ $i = *[[:space:]:-]* ]]; then
1476 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
1477 return 1
1479 done || ret=1
1481 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1482 while IFS='=' read -r _ i; do
1483 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1484 if [[ $i != +([0-9])?(.+([0-9])) ]]; then
1485 error "$(gettext "%s must be a decimal.")" "pkgrel"
1486 return 1
1488 done || ret=1
1490 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1491 while IFS='=' read -r _ i; do
1492 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1493 if [[ $i != *([[:digit:]]) ]]; then
1494 error "$(gettext "%s must be an integer.")" "epoch"
1495 return 1
1497 done || ret=1
1499 if [[ $arch != 'any' ]]; then
1500 if ! in_array $CARCH ${arch[@]}; then
1501 if (( ! IGNOREARCH )); then
1502 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1503 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1504 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1505 ret=1
1510 if (( ${#pkgname[@]} > 1 )); then
1511 for i in ${pkgname[@]}; do
1512 local arch_list=""
1513 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1514 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1515 if ! in_array $CARCH ${arch_list[@]}; then
1516 if (( ! IGNOREARCH )); then
1517 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1518 ret=1
1522 done
1525 local provides_list=()
1526 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1527 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1528 for i in ${provides_list[@]}; do
1529 if [[ $i == *['<>']* ]]; then
1530 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1531 ret=1
1533 done
1535 local backup_list=()
1536 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1537 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1538 for i in "${backup_list[@]}"; do
1539 if [[ ${i:0:1} = "/" ]]; then
1540 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1541 ret=1
1543 done
1545 local optdepends_list=()
1546 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1547 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1548 for i in "${optdepends_list[@]}"; do
1549 local pkg=${i%%:[[:space:]]*}
1550 # the '-' character _must_ be first or last in the character range
1551 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1552 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1553 ret=1
1555 done
1557 for i in 'changelog' 'install'; do
1558 local file
1559 while read -r file; do
1560 # evaluate any bash variables used
1561 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1562 if [[ $file && ! -f $file ]]; then
1563 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1564 ret=1
1566 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1567 done
1569 local valid_options=1
1570 local known kopt options_list
1571 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1572 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1573 for i in ${options_list[@]}; do
1574 known=0
1575 # check if option matches a known option or its inverse
1576 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1577 if [[ ${i} = ${kopt} || ${i} = "!${kopt}" ]]; then
1578 known=1
1580 done
1581 if (( ! known )); then
1582 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1583 valid_options=0
1585 done
1586 if (( ! valid_options )); then
1587 ret=1
1590 if (( ${#pkgname[@]} > 1 )); then
1591 for i in ${pkgname[@]}; do
1592 if ! declare -f package_${i} >/dev/null; then
1593 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1594 ret=1
1596 done
1599 for i in ${PKGLIST[@]}; do
1600 if ! in_array $i ${pkgname[@]}; then
1601 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1602 ret=1
1604 done
1606 return $ret
1609 check_software() {
1610 # check for needed software
1611 local ret=0
1613 # check for sudo if we will need it during makepkg execution
1614 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1615 if ! type -p sudo >/dev/null; then
1616 warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")"
1620 # fakeroot - building as non-root user
1621 if [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then
1622 if ! type -p fakeroot >/dev/null; then
1623 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
1624 ret=1
1628 # gpg - package signing
1629 if [[ $SIGNPKG == 'y' || (-z "$SIGNPKG" && $(check_buildenv sign) == 'y') ]]; then
1630 if ! type -p gpg >/dev/null; then
1631 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
1632 ret=1
1636 # gpg - source verification
1637 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
1638 if ! type -p gpg >/dev/null; then
1639 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
1640 ret=1
1644 # openssl - checksum operations
1645 if (( ! SKIPCHECKSUMS )); then
1646 if ! type -p openssl >/dev/null; then
1647 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
1648 ret=1
1652 # upx - binary compression
1653 if [[ $(check_option upx) == 'y' ]]; then
1654 if ! type -p upx >/dev/null; then
1655 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
1656 ret=1
1660 # distcc - compilation with distcc
1661 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
1662 if ! type -p distcc >/dev/null; then
1663 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
1664 ret=1
1668 # ccache - compilation with ccache
1669 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
1670 if ! type -p ccache >/dev/null; then
1671 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
1672 ret=1
1676 # strip - strip symbols from binaries/libraries
1677 if [[ $(check_option strip) = "y" ]]; then
1678 if ! type -p strip >/dev/null; then
1679 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
1680 ret=1
1684 # gzip - compressig man and info pages
1685 if [[ $(check_option zipman) = "y" ]]; then
1686 if ! type -p gzip >/dev/null; then
1687 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
1688 ret=1
1692 return $ret
1695 devel_check() {
1696 newpkgver=""
1698 # Do not update pkgver if --holdver is set, when building a source package, repackaging,
1699 # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w)
1700 if (( HOLDVER || SOURCEONLY || REPKG )) ||
1701 [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = /dev/stdin ]]; then
1702 return
1705 if [[ -z $FORCE_VER ]]; then
1706 # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so.
1707 # This will only be used on the first call to makepkg; subsequent
1708 # calls to makepkg via fakeroot will explicitly pass the version
1709 # number to avoid having to determine the version number twice.
1710 # Also do a check to make sure we have the VCS tool available.
1711 oldpkgver=$pkgver
1712 if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then
1713 if ! type -p darcs >/dev/null; then
1714 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "darcs" "darcs"
1715 return 0
1717 msg "$(gettext "Determining latest %s revision...")" 'darcs'
1718 newpkgver=$(date +%Y%m%d)
1719 elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then
1720 if ! type -p cvs >/dev/null; then
1721 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "cvs" "cvs"
1722 return 0
1724 msg "$(gettext "Determining latest %s revision...")" 'cvs'
1725 newpkgver=$(date +%Y%m%d)
1726 elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then
1727 if ! type -p git >/dev/null; then
1728 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "git" "git"
1729 return 0
1731 msg "$(gettext "Determining latest %s revision...")" 'git'
1732 newpkgver=$(date +%Y%m%d)
1733 elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then
1734 if ! type -p svn >/dev/null; then
1735 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "svn" "svn"
1736 return 0
1738 msg "$(gettext "Determining latest %s revision...")" 'svn'
1739 newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p')
1740 elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then
1741 if ! type -p bzr >/dev/null; then
1742 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "bzr" "bzr"
1743 return 0
1745 msg "$(gettext "Determining latest %s revision...")" 'bzr'
1746 newpkgver=$(bzr revno ${_bzrtrunk})
1747 elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then
1748 if ! type -p hg >/dev/null; then
1749 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "hg" "hg"
1750 return 0
1752 msg "$(gettext "Determining latest %s revision...")" 'hg'
1753 if [[ -d ./src/$_hgrepo ]] ; then
1754 cd ./src/$_hgrepo
1755 local ret=0
1756 hg pull || ret=$?
1757 if (( ! ret )); then
1758 hg update
1759 elif (( ret != 1 )); then
1760 return 1
1762 else
1763 [[ ! -d ./src/ ]] && mkdir ./src/
1764 hg clone $_hgroot/$_hgrepo ./src/$_hgrepo
1765 cd ./src/$_hgrepo
1767 newpkgver=$(hg tip --template "{rev}")
1768 cd ../../
1771 if [[ -n $newpkgver ]]; then
1772 msg2 "$(gettext "Version found: %s")" "$newpkgver"
1775 else
1776 # Version number retrieved from fakeroot->makepkg argument
1777 newpkgver=$FORCE_VER
1781 devel_update() {
1782 # This is lame, but if we're wanting to use an updated pkgver for
1783 # retrieving svn/cvs/etc sources, we'll update the PKGBUILD with
1784 # the new pkgver and then re-source it. This is the most robust
1785 # method for dealing with PKGBUILDs that use, e.g.:
1787 # pkgver=23
1788 # ...
1789 # _foo=pkgver
1791 if [[ -n $newpkgver ]]; then
1792 if [[ $newpkgver != "$pkgver" ]]; then
1793 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
1794 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
1795 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
1796 source "$BUILDFILE"
1802 backup_package_variables() {
1803 local var
1804 for var in ${splitpkg_overrides[@]}; do
1805 local indirect="${var}_backup"
1806 eval "${indirect}=(\"\${$var[@]}\")"
1807 done
1810 restore_package_variables() {
1811 local var
1812 for var in ${splitpkg_overrides[@]}; do
1813 local indirect="${var}_backup"
1814 if [[ -n ${!indirect} ]]; then
1815 eval "${var}=(\"\${$indirect[@]}\")"
1816 else
1817 unset ${var}
1819 done
1822 run_split_packaging() {
1823 local pkgname_backup=${pkgname[@]}
1824 for pkgname in ${pkgname_backup[@]}; do
1825 pkgdir="$pkgdir/$pkgname"
1826 mkdir -p "$pkgdir"
1827 chmod a-s "$pkgdir"
1828 backup_package_variables
1829 run_package $pkgname
1830 tidy_install
1831 create_package $pkgname
1832 restore_package_variables
1833 pkgdir="${pkgdir%/*}"
1834 done
1835 pkgname=${pkgname_backup[@]}
1838 # Canonicalize a directory path if it exists
1839 canonicalize_path() {
1840 local path="$1";
1842 if [[ -d $path ]]; then
1844 cd "$path"
1845 pwd -P
1847 else
1848 echo "$path"
1852 m4_include(library/parse_options.sh)
1854 usage() {
1855 printf "makepkg (pacman) %s\n" "$myver"
1856 echo
1857 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
1858 echo
1859 printf -- "$(gettext "Options:")\n"
1860 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
1861 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
1862 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
1863 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
1864 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
1865 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
1866 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
1867 printf -- "$(gettext " -i, --install Install package after successful build")\n"
1868 printf -- "$(gettext " -L, --log Log package build process")\n"
1869 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
1870 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
1871 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
1872 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
1873 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
1874 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
1875 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
1876 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
1877 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
1878 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1879 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
1880 printf -- "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT"
1881 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
1882 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1883 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
1884 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
1885 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
1886 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
1887 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
1888 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
1889 echo
1890 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
1891 echo
1892 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
1893 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
1894 echo
1895 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
1896 echo
1899 version() {
1900 printf "makepkg (pacman) %s\n" "$myver"
1901 printf -- "$(gettext "\
1902 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
1903 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
1904 This is free software; see the source for copying conditions.\n\
1905 There is NO WARRANTY, to the extent permitted by law.\n")"
1908 # PROGRAM START
1910 # determine whether we have gettext; make it a no-op if we do not
1911 if ! type -p gettext >/dev/null; then
1912 gettext() {
1913 echo "$@"
1917 ARGLIST=("$@")
1919 # Parse Command Line Options.
1920 OPT_SHORT="AcdefFghiLmop:rRsSV"
1921 OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps"
1922 OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver,skippgpcheck"
1923 OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps"
1924 OPT_LONG+=",repackage,skipchecksums,skipinteg,skippgpcheck,sign,source,syncdeps"
1925 OPT_LONG+=",version,config:"
1927 # Pacman Options
1928 OPT_LONG+=",noconfirm,noprogressbar"
1929 if ! parse_options $OPT_SHORT $OPT_LONG "$@"; then
1930 echo; usage; exit 1 # E_INVALID_OPTION;
1932 set -- "${OPTRET[@]}"
1933 unset OPT_SHORT OPT_LONG OPTRET
1935 while true; do
1936 case "$1" in
1937 # Pacman Options
1938 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
1939 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
1941 # Makepkg Options
1942 --allsource) SOURCEONLY=2 ;;
1943 --asroot) ASROOT=1 ;;
1944 -A|--ignorearch) IGNOREARCH=1 ;;
1945 -c|--clean) CLEANUP=1 ;;
1946 --check) RUN_CHECK='y' ;;
1947 --config) shift; MAKEPKG_CONF=$1 ;;
1948 -d|--nodeps) NODEPS=1 ;;
1949 -e|--noextract) NOEXTRACT=1 ;;
1950 -f|--force) FORCE=1 ;;
1951 #hidden opt used by fakeroot call for svn/cvs/etc PKGBUILDs to set pkgver
1952 --forcever) shift; FORCE_VER=$1;;
1953 -F) INFAKEROOT=1 ;;
1954 -g|--geninteg) GENINTEG=1 ;;
1955 --holdver) HOLDVER=1 ;;
1956 -i|--install) INSTALL=1 ;;
1957 --key) shift; GPGKEY=$1 ;;
1958 -L|--log) LOGGING=1 ;;
1959 -m|--nocolor) USE_COLOR='n' ;;
1960 --nocheck) RUN_CHECK='n' ;;
1961 --nosign) SIGNPKG='n' ;;
1962 -o|--nobuild) NOBUILD=1 ;;
1963 -p) shift; BUILDFILE=$1 ;;
1964 --pkg) shift; PKGLIST=($1) ;;
1965 -r|--rmdeps) RMDEPS=1 ;;
1966 -R|--repackage) REPKG=1 ;;
1967 --skipchecksums) SKIPCHECKSUMS=1 ;;
1968 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
1969 --skippgpcheck) SKIPPGPCHECK=1;;
1970 --sign) SIGNPKG='y' ;;
1971 -s|--syncdeps) DEP_BIN=1 ;;
1972 -S|--source) SOURCEONLY=1 ;;
1974 -h|--help) usage; exit 0 ;; # E_OK
1975 -V|--version) version; exit 0 ;; # E_OK
1977 --) OPT_IND=0; shift; break;;
1978 *) usage; exit 1 ;; # E_INVALID_OPTION
1979 esac
1980 shift
1981 done
1983 # setup signal traps
1984 trap 'clean_up' 0
1985 for signal in TERM HUP QUIT; do
1986 trap "trap_exit \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
1987 done
1988 trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT
1989 trap 'trap_exit "$(gettext "An unknown error has occurred. Exiting...")"' ERR
1990 set -E
1992 # preserve environment variables and canonicalize path
1993 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
1994 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
1995 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
1996 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
1997 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
1998 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
1999 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
2000 [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
2002 # default config is makepkg.conf
2003 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
2005 # Source the config file; fail if it is not found
2006 if [[ -r $MAKEPKG_CONF ]]; then
2007 source "$MAKEPKG_CONF"
2008 else
2009 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
2010 plain "$(gettext "Aborting...")"
2011 exit 1 # $E_CONFIG_ERROR
2014 # Source user-specific makepkg.conf overrides, but only if no override config
2015 # file was specified
2016 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
2017 source ~/.makepkg.conf
2020 # set pacman command if not already defined
2021 PACMAN=${PACMAN:-pacman}
2023 # check if messages are to be printed using color
2024 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2025 if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then
2026 # prefer terminal safe colored and bold text when tput is supported
2027 if tput setaf 0 &>/dev/null; then
2028 ALL_OFF="$(tput sgr0)"
2029 BOLD="$(tput bold)"
2030 BLUE="${BOLD}$(tput setaf 4)"
2031 GREEN="${BOLD}$(tput setaf 2)"
2032 RED="${BOLD}$(tput setaf 1)"
2033 YELLOW="${BOLD}$(tput setaf 3)"
2034 else
2035 ALL_OFF="\e[1;0m"
2036 BOLD="\e[1;1m"
2037 BLUE="${BOLD}\e[1;34m"
2038 GREEN="${BOLD}\e[1;32m"
2039 RED="${BOLD}\e[1;31m"
2040 YELLOW="${BOLD}\e[1;33m"
2043 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2045 # override settings with an environment variable for batch processing
2046 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2047 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2048 if [[ ! -d $BUILDDIR ]]; then
2049 mkdir -p "$BUILDDIR" ||
2050 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2051 chmod a-s "$BUILDDIR"
2053 if [[ ! -w $BUILDDIR ]]; then
2054 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2055 plain "$(gettext "Aborting...")"
2056 exit 1
2058 srcdir="$BUILDDIR/src"
2059 pkgdir="$BUILDDIR/pkg"
2061 PKGDEST=${_PKGDEST:-$PKGDEST}
2062 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2063 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2064 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2065 plain "$(gettext "Aborting...")"
2066 exit 1
2069 SRCDEST=${_SRCDEST:-$SRCDEST}
2070 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2071 if [[ ! -w $SRCDEST ]] ; then
2072 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2073 plain "$(gettext "Aborting...")"
2074 exit 1
2077 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2078 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2079 if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then
2080 error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
2081 plain "$(gettext "Aborting...")"
2082 exit 1
2085 PKGEXT=${_PKGEXT:-$PKGEXT}
2086 SRCEXT=${_SRCEXT:-$SRCEXT}
2087 GPGKEY=${_GPGKEY:-$GPGKEY}
2088 PACKAGER=${_PACKAGER:-$PACKAGER}
2090 if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then
2091 # The '\\0' is here to prevent gettext from thinking --holdver is an option
2092 error "$(gettext "\\0%s and %s cannot both be specified" )" "--holdver" "--forcever"
2093 exit 1
2096 if (( ! INFAKEROOT )); then
2097 if (( EUID == 0 && ! ASROOT )); then
2098 # Warn those who like to live dangerously.
2099 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2100 catastrophic damage to your system. If you wish to run as root, please\n\
2101 use the %s option.")" "makepkg" "--asroot"
2102 exit 1 # $E_USER_ABORT
2103 elif (( EUID > 0 && ASROOT )); then
2104 # Warn those who try to use the --asroot option when they are not root
2105 error "$(gettext "The %s option is meant for the root user only. Please\n\
2106 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2107 exit 1 # $E_USER_ABORT
2108 elif (( EUID > 0 )) && [[ $(check_buildenv fakeroot) != "y" ]]; then
2109 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2110 ownership of the packaged files. Try using the %s environment by\n\
2111 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2112 sleep 1
2114 else
2115 if [[ -z $FAKEROOTKEY ]]; then
2116 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2117 exit 1 # TODO: error code
2121 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2122 unset md5sums replaces depends conflicts backup source install changelog build
2123 unset makedepends optdepends options noextract
2125 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2126 if [[ ! -f $BUILDFILE ]]; then
2127 if [[ -t 0 ]]; then
2128 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2129 exit 1
2130 else
2131 # PKGBUILD passed through a pipe
2132 BUILDFILE=/dev/stdin
2133 shopt -u extglob
2134 source "$BUILDFILE"
2135 shopt -s extglob
2137 else
2138 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2139 if [[ -n $crlftest ]]; then
2140 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2141 exit 1
2144 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2145 BUILDFILE="$startdir/$BUILDFILE"
2147 shopt -u extglob
2148 source "$BUILDFILE"
2149 shopt -s extglob
2152 # set defaults if they weren't specified in buildfile
2153 pkgbase=${pkgbase:-${pkgname[0]}}
2154 epoch=${epoch:-0}
2156 if (( GENINTEG )); then
2157 mkdir -p "$srcdir"
2158 chmod a-s "$srcdir"
2159 cd "$srcdir"
2160 download_sources
2161 generate_checksums
2162 exit 0 # $E_OK
2165 # check the PKGBUILD for some basic requirements
2166 check_sanity || exit 1
2168 # check we have the software required to process the PKGBUILD
2169 check_software || exit 1
2171 # We need to run devel_update regardless of whether we are in the fakeroot
2172 # build process so that if the user runs makepkg --forcever manually, we
2173 # 1) output the correct pkgver, and 2) use the correct filename when
2174 # checking if the package file already exists - fixes FS #9194
2175 devel_check
2176 devel_update
2178 if (( ${#pkgname[@]} > 1 )); then
2179 SPLITPKG=1
2182 # test for available PKGBUILD functions
2183 if declare -f build >/dev/null; then
2184 BUILDFUNC=1
2186 if declare -f check >/dev/null; then
2187 # "Hide" check() function if not going to be run
2188 if [[ $RUN_CHECK = 'y' || (! $(check_buildenv check) = "n" && ! $RUN_CHECK = "n") ]]; then
2189 CHECKFUNC=1
2192 if declare -f package >/dev/null; then
2193 PKGFUNC=1
2194 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2195 SPLITPKG=1
2198 if [[ -n "${PKGLIST[@]}" ]]; then
2199 unset pkgname
2200 pkgname=("${PKGLIST[@]}")
2203 # check if gpg signature is to be created and if signing key is valid
2204 [[ -z $SIGNPKG ]] && SIGNPKG=$(check_buildenv sign)
2205 if [[ $SIGNPKG == 'y' ]]; then
2206 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2207 if [[ ! -z $GPGKEY ]]; then
2208 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2209 else
2210 error "$(gettext "There is no key in your keyring.")"
2212 exit 1
2217 if (( ! SPLITPKG )); then
2218 fullver=$(get_full_version)
2219 if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \
2220 || -f $PKGDEST/${pkgname}-${fullver}-any${PKGEXT} ]] \
2221 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2222 if (( INSTALL )); then
2223 warning "$(gettext "A package has already been built, installing existing package...")"
2224 install_package
2225 exit $?
2226 else
2227 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2228 exit 1
2231 else
2232 allpkgbuilt=1
2233 somepkgbuilt=0
2234 for pkg in ${pkgname[@]}; do
2235 fullver=$(get_full_version $pkg)
2236 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} \
2237 || -f $PKGDEST/${pkg}-${fullver}-any${PKGEXT} ]]; then
2238 somepkgbuilt=1
2239 else
2240 allpkgbuilt=0
2242 done
2243 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2244 if (( allpkgbuilt )); then
2245 if (( INSTALL )); then
2246 warning "$(gettext "The package group has already been built, installing existing packages...")"
2247 install_package
2248 exit $?
2249 else
2250 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2251 exit 1
2254 if (( somepkgbuilt )); then
2255 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2256 exit 1
2259 unset allpkgbuilt somepkgbuilt
2262 # Run the bare minimum in fakeroot
2263 if (( INFAKEROOT )); then
2264 if (( SOURCEONLY )); then
2265 create_srcpackage
2266 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2267 exit 0 # $E_OK
2270 if (( ! SPLITPKG )); then
2271 if (( ! PKGFUNC )); then
2272 if (( ! REPKG )); then
2273 if (( BUILDFUNC )); then
2274 run_build
2275 (( CHECKFUNC )) && run_check
2276 tidy_install
2278 else
2279 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2280 plain "$(gettext "File permissions may not be preserved.")"
2282 else
2283 run_package
2284 tidy_install
2286 create_package
2287 else
2288 run_split_packaging
2291 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2292 exit 0 # $E_OK
2295 fullver=$(get_full_version)
2296 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2298 # if we are creating a source-only package, go no further
2299 if (( SOURCEONLY )); then
2300 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2301 && (( ! FORCE )); then
2302 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2303 exit 1
2306 # Get back to our src directory so we can begin with sources.
2307 mkdir -p "$srcdir"
2308 chmod a-s "$srcdir"
2309 cd "$srcdir"
2310 if ( (( ! SKIPCHECKSUMS )) || \
2311 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \
2312 (( SOURCEONLY == 2 )); then
2313 download_sources
2315 check_source_integrity
2316 cd "$startdir"
2318 # if we are root or if fakeroot is not enabled, then we don't use it
2319 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2320 create_srcpackage
2321 else
2322 enter_fakeroot
2325 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2326 exit 0
2329 if (( NODEPS || ( (NOBUILD || REPKG) && !DEP_BIN ) )); then
2330 # no warning message needed for nobuild, repkg
2331 if (( NODEPS || ( REPKG && PKGFUNC ) )); then
2332 warning "$(gettext "Skipping dependency checks.")"
2334 elif type -p "${PACMAN%% *}" >/dev/null; then
2335 if (( RMDEPS && ! INSTALL )); then
2336 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2338 deperr=0
2340 msg "$(gettext "Checking runtime dependencies...")"
2341 resolve_deps ${depends[@]} || deperr=1
2343 if (( RMDEPS && INSTALL )); then
2344 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2347 msg "$(gettext "Checking buildtime dependencies...")"
2348 resolve_deps ${makedepends[@]} || deperr=1
2350 if (( CHECKFUNC )); then
2351 resolve_deps ${checkdepends[@]} || deperr=1
2354 if (( RMDEPS )); then
2355 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2358 if (( deperr )); then
2359 error "$(gettext "Could not resolve all dependencies.")"
2360 exit 1
2362 else
2363 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2366 # ensure we have a sane umask set
2367 umask 0022
2369 # get back to our src directory so we can begin with sources
2370 mkdir -p "$srcdir"
2371 chmod a-s "$srcdir"
2372 cd "$srcdir"
2374 if (( NOEXTRACT )); then
2375 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2376 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2377 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2379 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2380 error "$(gettext "The source directory is empty, there is nothing to build!")"
2381 plain "$(gettext "Aborting...")"
2382 exit 1
2384 elif (( REPKG )); then
2385 if (( ! PKGFUNC && ! SPLITPKG )) \
2386 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2387 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2388 plain "$(gettext "Aborting...")"
2389 exit 1
2391 else
2392 download_sources
2393 check_source_integrity
2394 extract_sources
2397 if (( NOBUILD )); then
2398 msg "$(gettext "Sources are ready.")"
2399 exit 0 #E_OK
2400 else
2401 # check for existing pkg directory; don't remove if we are repackaging
2402 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2403 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2404 rm -rf "$pkgdir"
2406 mkdir -p "$pkgdir"
2407 chmod a-s "$pkgdir"
2408 cd "$startdir"
2410 # if we are root or if fakeroot is not enabled, then we don't use it
2411 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2412 if (( ! REPKG )); then
2413 devel_update
2414 (( BUILDFUNC )) && run_build
2415 (( CHECKFUNC )) && run_check
2417 if (( ! SPLITPKG )); then
2418 if (( PKGFUNC )); then
2419 run_package
2420 tidy_install
2421 else
2422 if (( ! REPKG )); then
2423 tidy_install
2424 else
2425 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2426 plain "$(gettext "File permissions may not be preserved.")"
2429 create_package
2430 else
2431 run_split_packaging
2433 else
2434 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2435 devel_update
2436 (( BUILDFUNC )) && run_build
2437 (( CHECKFUNC )) && run_check
2438 cd "$startdir"
2441 enter_fakeroot
2445 fullver=$(get_full_version)
2446 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2448 install_package
2450 exit 0 #E_OK
2452 # vim: set ts=2 sw=2 noet: