Give better error messages on database locking failures
[pacman-ng.git] / scripts / makepkg.sh.in
blob805c31a917abc54adcd458d6c50d10c425744599
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 myver='@PACKAGE_VERSION@'
43 confdir='@sysconfdir@'
44 BUILDSCRIPT='@BUILDSCRIPT@'
45 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 local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}")
676 local realsum="$(openssl dgst -${integ} "$file")"
677 realsum="${realsum##* }"
678 if [[ $expectedsum = $realsum ]]; then
679 printf -- "$(gettext "Passed")\n" >&2
680 else
681 printf -- "$(gettext "FAILED")\n" >&2
682 errors=1
686 idx=$((idx + 1))
687 done
689 if (( errors )); then
690 error "$(gettext "One or more files did not pass the validity check!")"
691 exit 1 # TODO: error code
693 elif (( ${#integrity_sums[@]} )); then
694 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
695 exit 1 # TODO: error code
697 done
699 if (( ! correlation )); then
700 error "$(gettext "Integrity checks are missing.")"
701 exit 1 # TODO: error code
705 check_pgpsigs() {
706 (( SKIPPGPCHECK )) && return 0
707 ! source_has_signatures && return 0
709 msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
711 local file pubkey
712 local warning=0
713 local errors=0
714 local statusfile=$(mktemp)
716 for file in "${source[@]}"; do
717 file="$(get_filename "$file")"
718 if [[ ! $file = *.@(sig?(n)|asc) ]]; then
719 continue
722 printf " %s ... " "${file%.*}" >&2
724 if ! file="$(get_filepath "$file")"; then
725 printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
726 errors=1
727 continue
730 if ! sourcefile="$(get_filepath "${file%.*}")"; then
731 printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
732 errors=1
733 continue
736 if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
737 printf '%s' "$(gettext "FAILED")" >&2
738 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then
739 printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
740 warnings=1
741 else
742 errors=1
744 printf '\n' >&2
745 else
746 if grep -q "REVKEYSIG" "$statusfile"; then
747 printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2
748 errors=1
749 else
750 printf '%s' "$(gettext "Passed")" >&2
751 if grep -q "EXPSIG" "$statusfile"; then
752 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
753 warnings=1
754 elif grep -q "EXPKEYSIG" "$statusfile"; then
755 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
756 warnings=1
759 printf '\n' >&2
761 done
763 rm -f "$statusfile"
765 if (( errors )); then
766 error "$(gettext "One or more PGP signatures could not be verified!")"
767 exit 1
770 if (( warnings )); then
771 warning "$(gettext "Warnings have occurred while verifying the signatures.")"
772 plain "$(gettext "Please make sure you really trust them.")"
776 check_source_integrity() {
777 if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
778 warning "$(gettext "Skipping all source file integrity checks.")"
779 elif (( SKIPCHECKSUMS )); then
780 warning "$(gettext "Skipping verification of source file checksums.")"
781 check_pgpsigs
782 elif (( SKIPPGPCHECK )); then
783 warning "$(gettext "Skipping verification of source file PGP signatures.")"
784 check_checksums
785 else
786 check_checksums
787 check_pgpsigs
791 extract_sources() {
792 msg "$(gettext "Extracting Sources...")"
793 local netfile
794 for netfile in "${source[@]}"; do
795 local file=$(get_filename "$netfile")
796 if in_array "$file" "${noextract[@]}"; then
797 #skip source files in the noextract=() array
798 # these are marked explicitly to NOT be extracted
799 continue
803 # fix flyspray #6246
804 local file_type=$(file -bizL "$file")
805 local ext=${file##*.}
806 local cmd=''
807 case "$file_type" in
808 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
809 cmd="bsdtar" ;;
810 *application/x-gzip*)
811 case "$ext" in
812 gz|z|Z) cmd="gzip" ;;
813 *) continue;;
814 esac ;;
815 *application/x-bzip*)
816 case "$ext" in
817 bz2|bz) cmd="bzip2" ;;
818 *) continue;;
819 esac ;;
820 *application/x-xz*)
821 case "$ext" in
822 xz) cmd="xz" ;;
823 *) continue;;
824 esac ;;
826 # See if bsdtar can recognize the file
827 if bsdtar -tf "$file" -q '*' &>/dev/null; then
828 cmd="bsdtar"
829 else
830 continue
831 fi ;;
832 esac
834 local ret=0
835 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
836 if [[ $cmd = bsdtar ]]; then
837 $cmd -xf "$file" || ret=$?
838 else
839 rm -f "${file%.*}"
840 $cmd -dcf "$file" > "${file%.*}" || ret=$?
842 if (( ret )); then
843 error "$(gettext "Failed to extract %s")" "$file"
844 plain "$(gettext "Aborting...")"
845 exit 1
847 done
849 if (( EUID == 0 )); then
850 # change perms of all source files to root user & root group
851 chown -R 0:0 "$srcdir"
855 error_function() {
856 if [[ -p $logpipe ]]; then
857 rm "$logpipe"
859 # first exit all subshells, then print the error
860 if (( ! BASH_SUBSHELL )); then
861 error "$(gettext "A failure occurred in %s().")" "$1"
862 plain "$(gettext "Aborting...")"
863 remove_deps
865 exit 2 # $E_BUILD_FAILED
868 run_function() {
869 if [[ -z $1 ]]; then
870 return 1
872 local pkgfunc="$1"
874 # clear user-specified buildflags if requested
875 if [[ $(check_option buildflags) = "n" ]]; then
876 unset CFLAGS CXXFLAGS LDFLAGS
879 # clear user-specified makeflags if requested
880 if [[ $(check_option makeflags) = "n" ]]; then
881 unset MAKEFLAGS
884 msg "$(gettext "Starting %s()...")" "$pkgfunc"
885 cd "$srcdir"
887 # ensure all necessary build variables are exported
888 export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
889 # save our shell options so pkgfunc() can't override what we need
890 local shellopts=$(shopt -p)
892 local ret=0
893 local restoretrap
894 if (( LOGGING )); then
895 local fullver=$(get_full_version)
896 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
897 if [[ -f $BUILDLOG ]]; then
898 local i=1
899 while true; do
900 if [[ -f $BUILDLOG.$i ]]; then
901 i=$(($i +1))
902 else
903 break
905 done
906 mv "$BUILDLOG" "$BUILDLOG.$i"
909 # ensure overridden package variables survive tee with split packages
910 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
911 mkfifo "$logpipe"
912 tee "$BUILDLOG" < "$logpipe" &
913 local teepid=$!
915 restoretrap=$(trap -p ERR)
916 trap 'error_function $pkgfunc' ERR
917 $pkgfunc &>"$logpipe"
918 eval $restoretrap
920 wait $teepid
921 rm "$logpipe"
922 else
923 restoretrap=$(trap -p ERR)
924 trap 'error_function $pkgfunc' ERR
925 $pkgfunc 2>&1
926 eval $restoretrap
928 # reset our shell options
929 eval "$shellopts"
932 run_build() {
933 # use distcc if it is requested (check buildenv and PKGBUILD opts)
934 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
935 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
936 export DISTCC_HOSTS
939 # use ccache if it is requested (check buildenv and PKGBUILD opts)
940 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
941 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
944 run_function "build"
947 run_check() {
948 run_function "check"
951 run_package() {
952 local pkgfunc
953 if [[ -z $1 ]]; then
954 pkgfunc="package"
955 else
956 pkgfunc="package_$1"
959 run_function "$pkgfunc"
962 tidy_install() {
963 cd "$pkgdir"
964 msg "$(gettext "Tidying install...")"
966 if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then
967 msg2 "$(gettext "Removing doc files...")"
968 rm -rf ${DOC_DIRS[@]}
971 if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then
972 msg2 "$(gettext "Purging unwanted files...")"
973 local pt
974 for pt in "${PURGE_TARGETS[@]}"; do
975 if [[ ${pt} = ${pt//\/} ]]; then
976 find . -type f -name "${pt}" -exec rm -f -- '{}' \;
977 else
978 rm -f ${pt}
980 done
983 if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then
984 msg2 "$(gettext "Compressing man and info pages...")"
985 local manpage ext file link hardlinks hl
986 find ${MAN_DIRS[@]} -type f 2>/dev/null |
987 while read manpage ; do
988 ext="${manpage##*.}"
989 file="${manpage##*/}"
990 if [[ $ext != gz && $ext != bz2 ]]; then
991 # update symlinks to this manpage
992 find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null |
993 while read link ; do
994 rm -f "$link" "${link}.gz"
995 ln -s "${file}.gz" "${link}.gz"
996 done
998 # check file still exists (potentially already compressed due to hardlink)
999 if [[ -f ${manpage} ]]; then
1000 # find hard links and remove them
1001 # the '|| true' part keeps the script from bailing on the EOF returned
1002 # by read at the end of the find output
1003 IFS=$'\n' read -rd '' -a hardlinks < \
1004 <(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" \
1005 2>/dev/null || true) || true
1006 rm -f "${hardlinks[@]}"
1007 # compress the original
1008 gzip -9 "$manpage"
1009 # recreate hard links removed earlier
1010 for hl in "${hardlinks[@]}"; do
1011 ln "${manpage}.gz" "${hl}.gz"
1012 chmod 644 ${hl}.gz
1013 done
1016 done
1019 if [[ $(check_option strip) = y ]]; then
1020 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1021 # make sure library stripping variables are defined to prevent excess stripping
1022 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1023 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1024 local binary
1025 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1026 case "$(file -bi "$binary")" in
1027 *application/x-sharedlib*) # Libraries (.so)
1028 strip $STRIP_SHARED "$binary";;
1029 *application/x-archive*) # Libraries (.a)
1030 strip $STRIP_STATIC "$binary";;
1031 *application/x-executable*) # Binaries
1032 strip $STRIP_BINARIES "$binary";;
1033 esac
1034 done
1037 if [[ $(check_option libtool) = "n" ]]; then
1038 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1039 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1042 if [[ $(check_option emptydirs) = "n" ]]; then
1043 msg2 "$(gettext "Removing empty directories...")"
1044 find . -depth -type d -empty -delete
1047 if [[ $(check_option upx) = "y" ]]; then
1048 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1049 local binary
1050 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1051 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1052 upx $UPXFLAGS "$binary" &>/dev/null ||
1053 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1055 done
1059 find_libdepends() {
1060 local libdepends
1061 find "$pkgdir" -type f -perm -u+x | while read filename
1063 # get architecture of the file; if soarch is empty it's not an ELF binary
1064 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1065 [ -n "$soarch" ] || continue
1066 # process all libraries needed by the binary
1067 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1069 # extract the library name: libfoo.so
1070 soname="${sofile%%\.so\.*}.so"
1071 # extract the major version: 1
1072 soversion="${sofile##*\.so\.}"
1073 if in_array "${soname}" ${depends[@]}; then
1074 if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then
1075 # libfoo.so=1-64
1076 echo "${soname}=${soversion}-${soarch}"
1077 libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}")
1080 done
1081 done
1084 find_libprovides() {
1085 local libprovides
1086 find "$pkgdir" -type f -name \*.so\* | while read filename
1088 # check if we really have a shared object
1089 if LC_ALL=C readelf -h "$filename" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1090 # 64
1091 soarch=$(LC_ALL=C readelf -h "$filename" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1092 # get the string binaries link to: libfoo.so.1.2 -> libfoo.so.1
1093 sofile=$(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1094 [ -z "$sofile" ] && sofile="${filename##*/}"
1096 # extract the library name: libfoo.so
1097 soname="${sofile%%\.so\.*}.so"
1098 # extract the major version: 1
1099 soversion="${sofile##*\.so\.}"
1100 if in_array "${soname}" ${provides[@]}; then
1101 if ! in_array "${soname}=${soversion}-${soarch}" ${libprovides[@]}; then
1102 # libfoo.so=1-64
1103 echo "${soname}=${soversion}-${soarch}"
1104 libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}")
1108 done
1111 write_pkginfo() {
1112 local builddate=$(date -u "+%s")
1113 if [[ -n $PACKAGER ]]; then
1114 local packager="$PACKAGER"
1115 else
1116 local packager="Unknown Packager"
1118 local size="$(@DUPATH@ -sk)"
1119 size="$(( ${size%%[^0-9]*} * 1024 ))"
1121 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1122 echo "# Generated by makepkg $myver"
1123 if (( INFAKEROOT )); then
1124 echo "# using $(fakeroot -v)"
1126 echo "# $(LC_ALL=C date -u)"
1127 echo "pkgname = $1"
1128 (( SPLITPKG )) && echo pkgbase = $pkgbase
1129 echo "pkgver = $(get_full_version)"
1130 echo "pkgdesc = $pkgdesc"
1131 echo "url = $url"
1132 echo "builddate = $builddate"
1133 echo "packager = $packager"
1134 echo "size = $size"
1135 echo "arch = $PKGARCH"
1137 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1138 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1139 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1140 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1141 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1142 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1144 local it
1146 libprovides=$(find_libprovides)
1147 libdepends=$(find_libdepends)
1148 provides=("${provides[@]}" ${libprovides})
1149 depends=("${depends[@]}" ${libdepends})
1151 for it in "${depends[@]}"; do
1152 if [[ $it = *.so ]]; then
1153 # check if the entry has been found by find_libdepends
1154 # if not, it's unneeded; tell the user so he can remove it
1155 if [[ ! $libdepends =~ (^|\s)${it}=.* ]]; then
1156 error "$(gettext "Cannot find library listed in %s: %s")" "'depends'" "$it"
1157 return 1
1159 else
1160 echo "depend = $it"
1162 done
1164 for it in "${provides[@]}"; do
1165 # ignore versionless entires (those come from the PKGBUILD)
1166 if [[ $it = *.so ]]; then
1167 # check if the entry has been found by find_libprovides
1168 # if not, it's unneeded; tell the user so he can remove it
1169 if [[ ! $libprovides =~ (^|\s)${it}=.* ]]; then
1170 error "$(gettext "Cannot find library listed in %s: %s")" "'provides'" "$it"
1171 return 1
1173 else
1174 echo "provides = $it"
1176 done
1178 for it in "${packaging_options[@]}"; do
1179 local ret="$(check_option $it)"
1180 if [[ $ret != "?" ]]; then
1181 if [[ $ret = y ]]; then
1182 echo "makepkgopt = $it"
1183 else
1184 echo "makepkgopt = !$it"
1187 done
1189 # TODO maybe remove this at some point
1190 # warn if license array is not present or empty
1191 if [[ -z $license ]]; then
1192 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1193 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1197 check_package() {
1198 cd "$pkgdir"
1200 # check existence of backup files
1201 local file
1202 for file in "${backup[@]}"; do
1203 if [[ ! -f $file ]]; then
1204 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1206 done
1208 # check for references to the build and package directory
1209 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1210 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1212 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1213 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1218 create_package() {
1219 if [[ ! -d $pkgdir ]]; then
1220 error "$(gettext "Missing %s directory.")" "pkg/"
1221 plain "$(gettext "Aborting...")"
1222 exit 1 # $E_MISSING_PKGDIR
1225 check_package
1227 cd "$pkgdir"
1228 msg "$(gettext "Creating package...")"
1230 local nameofpkg
1231 if [[ -z $1 ]]; then
1232 nameofpkg="$pkgname"
1233 else
1234 nameofpkg="$1"
1237 if [[ $arch = "any" ]]; then
1238 PKGARCH="any"
1239 else
1240 PKGARCH=$CARCH
1243 write_pkginfo $nameofpkg > .PKGINFO
1245 local comp_files=".PKGINFO"
1247 # check for changelog/install files
1248 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1249 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1251 if [[ -n ${!orig} ]]; then
1252 msg2 "$(gettext "Adding %s file...")" "$orig"
1253 cp "$startdir/${!orig}" "$dest"
1254 chmod 644 "$dest"
1255 comp_files+=" $dest"
1257 done
1259 # tar it up
1260 msg2 "$(gettext "Compressing package...")"
1262 local fullver=$(get_full_version)
1263 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}"
1264 local ret=0
1266 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1267 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1269 # when fileglobbing, we want * in an empty directory to expand to
1270 # the null string rather than itself
1271 shopt -s nullglob
1272 # TODO: Maybe this can be set globally for robustness
1273 shopt -s -o pipefail
1274 # bsdtar's gzip compression always saves the time stamp, making one
1275 # archive created using the same command line distinct from another.
1276 # Disable bsdtar compression and use gzip -n for now.
1277 bsdtar -cf - $comp_files * |
1278 case "$PKGEXT" in
1279 *tar.gz) gzip -c -f -n ;;
1280 *tar.bz2) bzip2 -c -f ;;
1281 *tar.xz) xz -c -z - ;;
1282 *tar.Z) compress -c -f ;;
1283 *tar) cat ;;
1284 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1285 "$PKGEXT"; cat ;;
1286 esac > "${pkg_file}" || ret=$?
1288 shopt -u nullglob
1289 shopt -u -o pipefail
1291 if (( ret )); then
1292 error "$(gettext "Failed to create package file.")"
1293 exit 1 # TODO: error code
1296 create_signature "$pkg_file"
1298 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1299 rm -f "${pkg_file/$PKGDEST/$startdir}"
1300 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1301 ret=$?
1302 if [[ -f $pkg_file.sig ]]; then
1303 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1304 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1308 if (( ret )); then
1309 warning "$(gettext "Failed to create symlink to package file.")"
1313 create_signature() {
1314 if [[ $SIGNPKG != 'y' ]]; then
1315 return
1317 local ret=0
1318 local filename="$1"
1319 msg "$(gettext "Signing package...")"
1321 local SIGNWITHKEY=""
1322 if [[ -n $GPGKEY ]]; then
1323 SIGNWITHKEY="-u ${GPGKEY}"
1325 # The signature will be generated directly in ascii-friendly format
1326 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1329 if (( ! ret )); then
1330 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1331 else
1332 warning "$(gettext "Failed to sign package file.")"
1336 create_srcpackage() {
1337 local ret=0
1338 msg "$(gettext "Creating source package...")"
1339 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1340 mkdir "${srclinks}"/${pkgbase}
1342 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1343 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1345 local file
1346 for file in "${source[@]}"; do
1347 if [[ "$file" == $(get_filename "$file") ]] || (( SOURCEONLY == 2 )); then
1348 local absfile
1349 absfile=$(get_filepath "$file") || missing_source_file "$file"
1350 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1351 ln -s "$absfile" "$srclinks/$pkgbase"
1353 done
1355 local i
1356 for i in 'changelog' 'install'; do
1357 local file
1358 while read -r file; do
1359 # evaluate any bash variables used
1360 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1361 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1362 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1363 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1365 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1366 done
1368 local TAR_OPT
1369 case "$SRCEXT" in
1370 *tar.gz) TAR_OPT="z" ;;
1371 *tar.bz2) TAR_OPT="j" ;;
1372 *tar.xz) TAR_OPT="J" ;;
1373 *tar.Z) TAR_OPT="Z" ;;
1374 *tar) TAR_OPT="" ;;
1375 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1376 "$SRCEXT" ;;
1377 esac
1379 local fullver=$(get_full_version)
1380 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1382 # tar it up
1383 msg2 "$(gettext "Compressing source package...")"
1384 cd "${srclinks}"
1385 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1386 error "$(gettext "Failed to create source package file.")"
1387 exit 1 # TODO: error code
1390 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1391 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1392 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1393 ret=$?
1396 if (( ret )); then
1397 warning "$(gettext "Failed to create symlink to source package file.")"
1400 cd "${startdir}"
1401 rm -rf "${srclinks}"
1404 install_package() {
1405 (( ! INSTALL )) && return
1407 if (( ! SPLITPKG )); then
1408 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1409 else
1410 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1413 local fullver pkg pkglist
1414 for pkg in ${pkgname[@]}; do
1415 fullver=$(get_full_version $pkg)
1416 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} ]]; then
1417 pkglist+=" $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT}"
1418 else
1419 pkglist+=" $PKGDEST/${pkg}-${fullver}-any${PKGEXT}"
1421 done
1423 if ! run_pacman -U $pkglist; then
1424 warning "$(gettext "Failed to install built package(s).")"
1425 return 0
1429 check_sanity() {
1430 # check for no-no's in the build script
1431 local i
1432 local ret=0
1433 for i in 'pkgname' 'pkgrel' 'pkgver'; do
1434 if [[ -z ${!i} ]]; then
1435 error "$(gettext "%s is not allowed to be empty.")" "$i"
1436 ret=1
1438 done
1440 for i in "${pkgname[@]}"; do
1441 if [[ ${i:0:1} = "-" ]]; then
1442 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1443 ret=1
1445 done
1447 if [[ ${pkgbase:0:1} = "-" ]]; then
1448 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1449 ret=1
1452 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1453 while IFS='=' read -r _ i; do
1454 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1455 if [[ $i = *[[:space:]:-]* ]]; then
1456 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
1457 return 1
1459 done || ret=1
1461 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1462 while IFS='=' read -r _ i; do
1463 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1464 if [[ $i = *[[:space:]-]* ]]; then
1465 error "$(gettext "%s is not allowed to contain hyphens or whitespace.")" "pkgrel"
1466 return 1
1468 done || ret=1
1470 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1471 while IFS='=' read -r _ i; do
1472 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1473 if [[ $i != *([[:digit:]]) ]]; then
1474 error "$(gettext "%s must be an integer.")" "epoch"
1475 return 1
1477 done || ret=1
1479 if [[ $arch != 'any' ]]; then
1480 if ! in_array $CARCH ${arch[@]}; then
1481 if (( ! IGNOREARCH )); then
1482 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1483 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1484 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1485 ret=1
1490 if (( ${#pkgname[@]} > 1 )); then
1491 for i in ${pkgname[@]}; do
1492 local arch_list=""
1493 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1494 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1495 if ! in_array $CARCH ${arch_list[@]}; then
1496 if (( ! IGNOREARCH )); then
1497 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1498 ret=1
1502 done
1505 local provides_list=()
1506 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1507 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1508 for i in ${provides_list[@]}; do
1509 if [[ $i == *['<>']* ]]; then
1510 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1511 ret=1
1513 done
1515 local backup_list=()
1516 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1517 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1518 for i in "${backup_list[@]}"; do
1519 if [[ ${i:0:1} = "/" ]]; then
1520 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1521 ret=1
1523 done
1525 local optdepends_list=()
1526 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1527 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1528 for i in "${optdepends_list[@]}"; do
1529 local pkg=${i%%:[[:space:]]*}
1530 # the '-' character _must_ be first or last in the character range
1531 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1532 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1533 ret=1
1535 done
1537 for i in 'changelog' 'install'; do
1538 local file
1539 while read -r file; do
1540 # evaluate any bash variables used
1541 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1542 if [[ $file && ! -f $file ]]; then
1543 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1544 ret=1
1546 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1547 done
1549 local valid_options=1
1550 local known kopt options_list
1551 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1552 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1553 for i in ${options_list[@]}; do
1554 known=0
1555 # check if option matches a known option or its inverse
1556 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1557 if [[ ${i} = ${kopt} || ${i} = "!${kopt}" ]]; then
1558 known=1
1560 done
1561 if (( ! known )); then
1562 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1563 valid_options=0
1565 done
1566 if (( ! valid_options )); then
1567 ret=1
1570 if (( ${#pkgname[@]} > 1 )); then
1571 for i in ${pkgname[@]}; do
1572 if ! declare -f package_${i} >/dev/null; then
1573 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1574 ret=1
1576 done
1579 for i in ${PKGLIST[@]}; do
1580 if ! in_array $i ${pkgname[@]}; then
1581 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1582 ret=1
1584 done
1586 return $ret
1589 check_software() {
1590 # check for needed software
1591 local ret=0
1593 # check for sudo if we will need it during makepkg execution
1594 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1595 if ! type -p sudo >/dev/null; then
1596 warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")"
1600 # fakeroot - building as non-root user
1601 if [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then
1602 if ! type -p fakeroot >/dev/null; then
1603 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
1604 ret=1
1608 # gpg - package signing
1609 if [[ $SIGNPKG == 'y' || (-z "$SIGNPKG" && $(check_buildenv sign) == 'y') ]]; then
1610 if ! type -p gpg >/dev/null; then
1611 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
1612 ret=1
1616 # gpg - source verification
1617 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
1618 if ! type -p gpg >/dev/null; then
1619 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
1620 ret=1
1624 # openssl - checksum operations
1625 if (( ! SKIPCHECKSUMS )); then
1626 if ! type -p openssl >/dev/null; then
1627 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
1628 ret=1
1632 # upx - binary compression
1633 if [[ $(check_option upx) == 'y' ]]; then
1634 if ! type -p upx >/dev/null; then
1635 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
1636 ret=1
1640 # distcc - compilation with distcc
1641 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
1642 if ! type -p distcc >/dev/null; then
1643 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
1644 ret=1
1648 # ccache - compilation with ccache
1649 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
1650 if ! type -p ccache >/dev/null; then
1651 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
1652 ret=1
1656 # strip - strip symbols from binaries/libraries
1657 if [[ $(check_option strip) = "y" ]]; then
1658 if ! type -p strip >/dev/null; then
1659 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
1660 ret=1
1664 # gzip - compressig man and info pages
1665 if [[ $(check_option zipman) = "y" ]]; then
1666 if ! type -p gzip >/dev/null; then
1667 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
1668 ret=1
1672 return $ret
1675 devel_check() {
1676 newpkgver=""
1678 # Do not update pkgver if --holdver is set, when building a source package, repackaging,
1679 # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w)
1680 if (( HOLDVER || SOURCEONLY || REPKG )) ||
1681 [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = /dev/stdin ]]; then
1682 return
1685 if [[ -z $FORCE_VER ]]; then
1686 # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so.
1687 # This will only be used on the first call to makepkg; subsequent
1688 # calls to makepkg via fakeroot will explicitly pass the version
1689 # number to avoid having to determine the version number twice.
1690 # Also do a check to make sure we have the VCS tool available.
1691 oldpkgver=$pkgver
1692 if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then
1693 if ! type -p darcs >/dev/null; then
1694 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "darcs" "darcs"
1695 return 0
1697 msg "$(gettext "Determining latest %s revision...")" 'darcs'
1698 newpkgver=$(date +%Y%m%d)
1699 elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then
1700 if ! type -p cvs >/dev/null; then
1701 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "cvs" "cvs"
1702 return 0
1704 msg "$(gettext "Determining latest %s revision...")" 'cvs'
1705 newpkgver=$(date +%Y%m%d)
1706 elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then
1707 if ! type -p git >/dev/null; then
1708 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "git" "git"
1709 return 0
1711 msg "$(gettext "Determining latest %s revision...")" 'git'
1712 newpkgver=$(date +%Y%m%d)
1713 elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then
1714 if ! type -p svn >/dev/null; then
1715 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "svn" "svn"
1716 return 0
1718 msg "$(gettext "Determining latest %s revision...")" 'svn'
1719 newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p')
1720 elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then
1721 if ! type -p bzr >/dev/null; then
1722 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "bzr" "bzr"
1723 return 0
1725 msg "$(gettext "Determining latest %s revision...")" 'bzr'
1726 newpkgver=$(bzr revno ${_bzrtrunk})
1727 elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then
1728 if ! type -p hg >/dev/null; then
1729 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "hg" "hg"
1730 return 0
1732 msg "$(gettext "Determining latest %s revision...")" 'hg'
1733 if [[ -d ./src/$_hgrepo ]] ; then
1734 cd ./src/$_hgrepo
1735 local ret=0
1736 hg pull || ret=$?
1737 if (( ! ret )); then
1738 hg update
1739 elif (( ret != 1 )); then
1740 return 1
1742 else
1743 [[ ! -d ./src/ ]] && mkdir ./src/
1744 hg clone $_hgroot/$_hgrepo ./src/$_hgrepo
1745 cd ./src/$_hgrepo
1747 newpkgver=$(hg tip --template "{rev}")
1748 cd ../../
1751 if [[ -n $newpkgver ]]; then
1752 msg2 "$(gettext "Version found: %s")" "$newpkgver"
1755 else
1756 # Version number retrieved from fakeroot->makepkg argument
1757 newpkgver=$FORCE_VER
1761 devel_update() {
1762 # This is lame, but if we're wanting to use an updated pkgver for
1763 # retrieving svn/cvs/etc sources, we'll update the PKGBUILD with
1764 # the new pkgver and then re-source it. This is the most robust
1765 # method for dealing with PKGBUILDs that use, e.g.:
1767 # pkgver=23
1768 # ...
1769 # _foo=pkgver
1771 if [[ -n $newpkgver ]]; then
1772 if [[ $newpkgver != "$pkgver" ]]; then
1773 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
1774 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
1775 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
1776 source "$BUILDFILE"
1782 backup_package_variables() {
1783 local var
1784 for var in ${splitpkg_overrides[@]}; do
1785 local indirect="${var}_backup"
1786 eval "${indirect}=(\"\${$var[@]}\")"
1787 done
1790 restore_package_variables() {
1791 local var
1792 for var in ${splitpkg_overrides[@]}; do
1793 local indirect="${var}_backup"
1794 if [[ -n ${!indirect} ]]; then
1795 eval "${var}=(\"\${$indirect[@]}\")"
1796 else
1797 unset ${var}
1799 done
1802 run_split_packaging() {
1803 local pkgname_backup=${pkgname[@]}
1804 for pkgname in ${pkgname_backup[@]}; do
1805 pkgdir="$pkgdir/$pkgname"
1806 mkdir -p "$pkgdir"
1807 chmod a-s "$pkgdir"
1808 backup_package_variables
1809 run_package $pkgname
1810 tidy_install
1811 create_package $pkgname
1812 restore_package_variables
1813 pkgdir="${pkgdir%/*}"
1814 done
1815 pkgname=${pkgname_backup[@]}
1818 # Canonicalize a directory path if it exists
1819 canonicalize_path() {
1820 local path="$1";
1822 if [[ -d $path ]]; then
1824 cd "$path"
1825 pwd -P
1827 else
1828 echo "$path"
1832 m4_include(library/parse_options.sh)
1834 usage() {
1835 printf "makepkg (pacman) %s\n" "$myver"
1836 echo
1837 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
1838 echo
1839 printf -- "$(gettext "Options:")\n"
1840 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
1841 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
1842 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
1843 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
1844 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
1845 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
1846 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
1847 printf -- "$(gettext " -i, --install Install package after successful build")\n"
1848 printf -- "$(gettext " -L, --log Log package build process")\n"
1849 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
1850 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
1851 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
1852 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
1853 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
1854 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
1855 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
1856 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
1857 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
1858 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1859 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
1860 printf -- "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT"
1861 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
1862 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1863 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
1864 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
1865 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
1866 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
1867 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
1868 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
1869 echo
1870 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
1871 echo
1872 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
1873 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
1874 echo
1875 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
1876 echo
1879 version() {
1880 printf "makepkg (pacman) %s\n" "$myver"
1881 printf -- "$(gettext "\
1882 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
1883 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
1884 This is free software; see the source for copying conditions.\n\
1885 There is NO WARRANTY, to the extent permitted by law.\n")"
1888 # PROGRAM START
1890 # determine whether we have gettext; make it a no-op if we do not
1891 if ! type -p gettext >/dev/null; then
1892 gettext() {
1893 echo "$@"
1897 ARGLIST=("$@")
1899 # Parse Command Line Options.
1900 OPT_SHORT="AcdefFghiLmop:rRsSV"
1901 OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps"
1902 OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver,skippgpcheck"
1903 OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps"
1904 OPT_LONG+=",repackage,skipchecksums,skipinteg,skippgpcheck,sign,source,syncdeps"
1905 OPT_LONG+=",version,config:"
1907 # Pacman Options
1908 OPT_LONG+=",noconfirm,noprogressbar"
1909 if ! parse_options $OPT_SHORT $OPT_LONG "$@"; then
1910 echo; usage; exit 1 # E_INVALID_OPTION;
1912 set -- "${OPTRET[@]}"
1913 unset OPT_SHORT OPT_LONG OPTRET
1915 while true; do
1916 case "$1" in
1917 # Pacman Options
1918 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
1919 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
1921 # Makepkg Options
1922 --allsource) SOURCEONLY=2 ;;
1923 --asroot) ASROOT=1 ;;
1924 -A|--ignorearch) IGNOREARCH=1 ;;
1925 -c|--clean) CLEANUP=1 ;;
1926 --check) RUN_CHECK='y' ;;
1927 --config) shift; MAKEPKG_CONF=$1 ;;
1928 -d|--nodeps) NODEPS=1 ;;
1929 -e|--noextract) NOEXTRACT=1 ;;
1930 -f|--force) FORCE=1 ;;
1931 #hidden opt used by fakeroot call for svn/cvs/etc PKGBUILDs to set pkgver
1932 --forcever) shift; FORCE_VER=$1;;
1933 -F) INFAKEROOT=1 ;;
1934 -g|--geninteg) GENINTEG=1 ;;
1935 --holdver) HOLDVER=1 ;;
1936 -i|--install) INSTALL=1 ;;
1937 --key) shift; GPGKEY=$1 ;;
1938 -L|--log) LOGGING=1 ;;
1939 -m|--nocolor) USE_COLOR='n' ;;
1940 --nocheck) RUN_CHECK='n' ;;
1941 --nosign) SIGNPKG='n' ;;
1942 -o|--nobuild) NOBUILD=1 ;;
1943 -p) shift; BUILDFILE=$1 ;;
1944 --pkg) shift; PKGLIST=($1) ;;
1945 -r|--rmdeps) RMDEPS=1 ;;
1946 -R|--repackage) REPKG=1 ;;
1947 --skipchecksums) SKIPCHECKSUMS=1 ;;
1948 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
1949 --skippgpcheck) SKIPPGPCHECK=1;;
1950 --sign) SIGNPKG='y' ;;
1951 -s|--syncdeps) DEP_BIN=1 ;;
1952 -S|--source) SOURCEONLY=1 ;;
1954 -h|--help) usage; exit 0 ;; # E_OK
1955 -V|--version) version; exit 0 ;; # E_OK
1957 --) OPT_IND=0; shift; break;;
1958 *) usage; exit 1 ;; # E_INVALID_OPTION
1959 esac
1960 shift
1961 done
1963 # setup signal traps
1964 trap 'clean_up' 0
1965 for signal in TERM HUP QUIT; do
1966 trap "trap_exit \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
1967 done
1968 trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT
1969 trap 'trap_exit "$(gettext "An unknown error has occurred. Exiting...")"' ERR
1970 set -E
1972 # preserve environment variables and canonicalize path
1973 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
1974 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
1975 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
1976 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
1977 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
1978 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
1979 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
1981 # default config is makepkg.conf
1982 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
1984 # Source the config file; fail if it is not found
1985 if [[ -r $MAKEPKG_CONF ]]; then
1986 source "$MAKEPKG_CONF"
1987 else
1988 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
1989 plain "$(gettext "Aborting...")"
1990 exit 1 # $E_CONFIG_ERROR
1993 # Source user-specific makepkg.conf overrides, but only if no override config
1994 # file was specified
1995 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
1996 source ~/.makepkg.conf
1999 # set pacman command if not already defined
2000 PACMAN=${PACMAN:-pacman}
2002 # check if messages are to be printed using color
2003 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2004 if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then
2005 # prefer terminal safe colored and bold text when tput is supported
2006 if tput setaf 0 &>/dev/null; then
2007 ALL_OFF="$(tput sgr0)"
2008 BOLD="$(tput bold)"
2009 BLUE="${BOLD}$(tput setaf 4)"
2010 GREEN="${BOLD}$(tput setaf 2)"
2011 RED="${BOLD}$(tput setaf 1)"
2012 YELLOW="${BOLD}$(tput setaf 3)"
2013 else
2014 ALL_OFF="\e[1;0m"
2015 BOLD="\e[1;1m"
2016 BLUE="${BOLD}\e[1;34m"
2017 GREEN="${BOLD}\e[1;32m"
2018 RED="${BOLD}\e[1;31m"
2019 YELLOW="${BOLD}\e[1;33m"
2022 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2024 # override settings with an environment variable for batch processing
2025 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2026 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2027 if [[ ! -d $BUILDDIR ]]; then
2028 mkdir -p "$BUILDDIR" ||
2029 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2030 chmod a-s "$BUILDDIR"
2032 if [[ ! -w $BUILDDIR ]]; then
2033 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2034 plain "$(gettext "Aborting...")"
2035 exit 1
2037 srcdir="$BUILDDIR/src"
2038 pkgdir="$BUILDDIR/pkg"
2040 PKGDEST=${_PKGDEST:-$PKGDEST}
2041 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2042 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2043 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2044 plain "$(gettext "Aborting...")"
2045 exit 1
2048 SRCDEST=${_SRCDEST:-$SRCDEST}
2049 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2050 if [[ ! -w $SRCDEST ]] ; then
2051 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2052 plain "$(gettext "Aborting...")"
2053 exit 1
2056 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2057 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2058 if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then
2059 error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
2060 plain "$(gettext "Aborting...")"
2061 exit 1
2064 PKGEXT=${_PKGEXT:-$PKGEXT}
2065 SRCEXT=${_SRCEXT:-$SRCEXT}
2066 GPGKEY=${_GPGKEY:-$GPGKEY}
2068 if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then
2069 # The '\\0' is here to prevent gettext from thinking --holdver is an option
2070 error "$(gettext "\\0%s and %s cannot both be specified" )" "--holdver" "--forcever"
2071 exit 1
2074 if (( ! INFAKEROOT )); then
2075 if (( EUID == 0 && ! ASROOT )); then
2076 # Warn those who like to live dangerously.
2077 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2078 catastrophic damage to your system. If you wish to run as root, please\n\
2079 use the %s option.")" "makepkg" "--asroot"
2080 exit 1 # $E_USER_ABORT
2081 elif (( EUID > 0 && ASROOT )); then
2082 # Warn those who try to use the --asroot option when they are not root
2083 error "$(gettext "The %s option is meant for the root user only. Please\n\
2084 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2085 exit 1 # $E_USER_ABORT
2086 elif (( EUID > 0 )) && [[ $(check_buildenv fakeroot) != "y" ]]; then
2087 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2088 ownership of the packaged files. Try using the %s environment by\n\
2089 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2090 sleep 1
2092 else
2093 if [[ -z $FAKEROOTKEY ]]; then
2094 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2095 exit 1 # TODO: error code
2099 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2100 unset md5sums replaces depends conflicts backup source install changelog build
2101 unset makedepends optdepends options noextract
2103 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2104 if [[ ! -f $BUILDFILE ]]; then
2105 if [[ -t 0 ]]; then
2106 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2107 exit 1
2108 else
2109 # PKGBUILD passed through a pipe
2110 BUILDFILE=/dev/stdin
2111 shopt -u extglob
2112 source "$BUILDFILE"
2113 shopt -s extglob
2115 else
2116 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2117 if [[ -n $crlftest ]]; then
2118 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2119 exit 1
2122 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2123 BUILDFILE="$startdir/$BUILDFILE"
2125 shopt -u extglob
2126 source "$BUILDFILE"
2127 shopt -s extglob
2130 # set defaults if they weren't specified in buildfile
2131 pkgbase=${pkgbase:-${pkgname[0]}}
2132 epoch=${epoch:-0}
2134 if (( GENINTEG )); then
2135 mkdir -p "$srcdir"
2136 chmod a-s "$srcdir"
2137 cd "$srcdir"
2138 download_sources
2139 generate_checksums
2140 exit 0 # $E_OK
2143 # check the PKGBUILD for some basic requirements
2144 check_sanity || exit 1
2146 # check we have the software required to process the PKGBUILD
2147 check_software || exit 1
2149 # We need to run devel_update regardless of whether we are in the fakeroot
2150 # build process so that if the user runs makepkg --forcever manually, we
2151 # 1) output the correct pkgver, and 2) use the correct filename when
2152 # checking if the package file already exists - fixes FS #9194
2153 devel_check
2154 devel_update
2156 if (( ${#pkgname[@]} > 1 )); then
2157 SPLITPKG=1
2160 # test for available PKGBUILD functions
2161 if declare -f build >/dev/null; then
2162 BUILDFUNC=1
2164 if declare -f check >/dev/null; then
2165 # "Hide" check() function if not going to be run
2166 if [[ $RUN_CHECK = 'y' || (! $(check_buildenv check) = "n" && ! $RUN_CHECK = "n") ]]; then
2167 CHECKFUNC=1
2170 if declare -f package >/dev/null; then
2171 PKGFUNC=1
2172 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2173 SPLITPKG=1
2176 if [[ -n "${PKGLIST[@]}" ]]; then
2177 unset pkgname
2178 pkgname=("${PKGLIST[@]}")
2181 # check if gpg signature is to be created and if signing key is valid
2182 [[ -z $SIGNPKG ]] && SIGNPKG=$(check_buildenv sign)
2183 if [[ $SIGNPKG == 'y' ]]; then
2184 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2185 if [[ ! -z $GPGKEY ]]; then
2186 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2187 else
2188 error "$(gettext "There is no key in your keyring.")"
2190 exit 1
2195 if (( ! SPLITPKG )); then
2196 fullver=$(get_full_version)
2197 if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \
2198 || -f $PKGDEST/${pkgname}-${fullver}-any${PKGEXT} ]] \
2199 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2200 if (( INSTALL )); then
2201 warning "$(gettext "A package has already been built, installing existing package...")"
2202 install_package
2203 exit $?
2204 else
2205 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2206 exit 1
2209 else
2210 allpkgbuilt=1
2211 somepkgbuilt=0
2212 for pkg in ${pkgname[@]}; do
2213 fullver=$(get_full_version $pkg)
2214 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} \
2215 || -f $PKGDEST/${pkg}-${fullver}-any${PKGEXT} ]]; then
2216 somepkgbuilt=1
2217 else
2218 allpkgbuilt=0
2220 done
2221 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2222 if (( allpkgbuilt )); then
2223 if (( INSTALL )); then
2224 warning "$(gettext "The package group has already been built, installing existing packages...")"
2225 install_package
2226 exit $?
2227 else
2228 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2229 exit 1
2232 if (( somepkgbuilt )); then
2233 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2234 exit 1
2237 unset allpkgbuilt somepkgbuilt
2240 # Run the bare minimum in fakeroot
2241 if (( INFAKEROOT )); then
2242 if (( SOURCEONLY )); then
2243 create_srcpackage
2244 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2245 exit 0 # $E_OK
2248 if (( ! SPLITPKG )); then
2249 if (( ! PKGFUNC )); then
2250 if (( ! REPKG )); then
2251 if (( BUILDFUNC )); then
2252 run_build
2253 (( CHECKFUNC )) && run_check
2254 tidy_install
2256 else
2257 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2258 plain "$(gettext "File permissions may not be preserved.")"
2260 else
2261 run_package
2262 tidy_install
2264 create_package
2265 else
2266 run_split_packaging
2269 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2270 exit 0 # $E_OK
2273 fullver=$(get_full_version)
2274 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2276 # if we are creating a source-only package, go no further
2277 if (( SOURCEONLY )); then
2278 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2279 && (( ! FORCE )); then
2280 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2281 exit 1
2284 # Get back to our src directory so we can begin with sources.
2285 mkdir -p "$srcdir"
2286 chmod a-s "$srcdir"
2287 cd "$srcdir"
2288 if ( (( ! SKIPCHECKSUMS )) || \
2289 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \
2290 (( SOURCEONLY == 2 )); then
2291 download_sources
2293 check_source_integrity
2294 cd "$startdir"
2296 # if we are root or if fakeroot is not enabled, then we don't use it
2297 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2298 create_srcpackage
2299 else
2300 enter_fakeroot
2303 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2304 exit 0
2307 if (( NODEPS || ( (NOBUILD || REPKG) && !DEP_BIN ) )); then
2308 # no warning message needed for nobuild, repkg
2309 if (( NODEPS || ( REPKG && PKGFUNC ) )); then
2310 warning "$(gettext "Skipping dependency checks.")"
2312 elif type -p "${PACMAN%% *}" >/dev/null; then
2313 if (( RMDEPS && ! INSTALL )); then
2314 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2316 deperr=0
2318 msg "$(gettext "Checking runtime dependencies...")"
2319 resolve_deps ${depends[@]} || deperr=1
2321 if (( RMDEPS && INSTALL )); then
2322 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2325 msg "$(gettext "Checking buildtime dependencies...")"
2326 resolve_deps ${makedepends[@]} || deperr=1
2328 if (( CHECKFUNC )); then
2329 resolve_deps ${checkdepends[@]} || deperr=1
2332 if (( RMDEPS )); then
2333 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2336 if (( deperr )); then
2337 error "$(gettext "Could not resolve all dependencies.")"
2338 exit 1
2340 else
2341 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2344 # ensure we have a sane umask set
2345 umask 0022
2347 # get back to our src directory so we can begin with sources
2348 mkdir -p "$srcdir"
2349 chmod a-s "$srcdir"
2350 cd "$srcdir"
2352 if (( NOEXTRACT )); then
2353 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2354 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2355 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2357 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2358 error "$(gettext "The source directory is empty, there is nothing to build!")"
2359 plain "$(gettext "Aborting...")"
2360 exit 1
2362 elif (( REPKG )); then
2363 if (( ! PKGFUNC && ! SPLITPKG )) \
2364 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2365 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2366 plain "$(gettext "Aborting...")"
2367 exit 1
2369 else
2370 download_sources
2371 check_source_integrity
2372 extract_sources
2375 if (( NOBUILD )); then
2376 msg "$(gettext "Sources are ready.")"
2377 exit 0 #E_OK
2378 else
2379 # check for existing pkg directory; don't remove if we are repackaging
2380 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2381 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2382 rm -rf "$pkgdir"
2384 mkdir -p "$pkgdir"
2385 chmod a-s "$pkgdir"
2386 cd "$startdir"
2388 # if we are root or if fakeroot is not enabled, then we don't use it
2389 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2390 if (( ! REPKG )); then
2391 devel_update
2392 (( BUILDFUNC )) && run_build
2393 (( CHECKFUNC )) && run_check
2395 if (( ! SPLITPKG )); then
2396 if (( PKGFUNC )); then
2397 run_package
2398 tidy_install
2399 else
2400 if (( ! REPKG )); then
2401 tidy_install
2402 else
2403 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2404 plain "$(gettext "File permissions may not be preserved.")"
2407 create_package
2408 else
2409 run_split_packaging
2411 else
2412 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2413 devel_update
2414 (( BUILDFUNC )) && run_build
2415 (( CHECKFUNC )) && run_check
2416 cd "$startdir"
2419 enter_fakeroot
2423 fullver=$(get_full_version)
2424 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2426 install_package
2428 exit 0 #E_OK
2430 # vim: set ts=2 sw=2 noet: