scripts/library: introduce parseopts
[pacman-ng.git] / scripts / makepkg.sh.in
blob46191ee4b8209524cd430210ea7913fe6ea475ad
1 #!/bin/bash
3 # makepkg - make packages compatible for use with pacman
4 # @configure_input@
6 # Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
7 # Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
8 # Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
9 # Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org>
10 # Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
11 # Copyright (c) 2006 by Alex Smith <alex@alex-smith.me.uk>
12 # Copyright (c) 2006 by Andras Voroskoi <voroskoi@frugalware.org>
14 # This program is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
28 # makepkg uses quite a few external programs during its execution. You
29 # need to have at least the following installed for makepkg to function:
30 # awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils),
31 # gettext, gpg, grep, gzip, openssl, sed, tput (ncurses), xz
33 # gettext initialization
34 export TEXTDOMAIN='pacman-scripts'
35 export TEXTDOMAINDIR='@localedir@'
37 # file -i does not work on Mac OSX unless legacy mode is set
38 export COMMAND_MODE='legacy'
39 # Ensure CDPATH doesn't screw with our cd calls
40 unset CDPATH
42 declare -r myver='@PACKAGE_VERSION@'
43 declare -r confdir='@sysconfdir@'
44 declare -r BUILDSCRIPT='@BUILDSCRIPT@'
45 declare -r startdir="$PWD"
47 packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge' 'upx')
48 other_options=('ccache' 'distcc' 'buildflags' 'makeflags')
49 splitpkg_overrides=('pkgver' 'pkgrel' 'epoch' 'pkgdesc' 'arch' 'license' \
50 'groups' 'depends' 'optdepends' 'provides' 'conflicts' \
51 'replaces' 'backup' 'options' 'install' 'changelog')
52 readonly -a packaging_options other_options splitpkg_overrides
54 # Options
55 ASROOT=0
56 CLEANUP=0
57 DEP_BIN=0
58 FORCE=0
59 INFAKEROOT=0
60 GENINTEG=0
61 SKIPCHECKSUMS=0
62 SKIPPGPCHECK=0
63 INSTALL=0
64 NOBUILD=0
65 NODEPS=0
66 NOEXTRACT=0
67 RMDEPS=0
68 REPKG=0
69 LOGGING=0
70 SOURCEONLY=0
71 IGNOREARCH=0
72 HOLDVER=0
73 BUILDFUNC=0
74 CHECKFUNC=0
75 PKGFUNC=0
76 SPLITPKG=0
77 PKGLIST=()
78 SIGNPKG=''
80 # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call
81 # when dealing with svn/cvs/etc PKGBUILDs.
82 FORCE_VER=""
84 PACMAN_OPTS=
86 shopt -s extglob
88 ### SUBROUTINES ###
90 plain() {
91 local mesg=$1; shift
92 printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
95 msg() {
96 local mesg=$1; shift
97 printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
100 msg2() {
101 local mesg=$1; shift
102 printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
105 warning() {
106 local mesg=$1; shift
107 printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
110 error() {
111 local mesg=$1; shift
112 printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
117 # Special exit call for traps, Don't print any error messages when inside,
118 # the fakeroot call, the error message will be printed by the main call.
120 trap_exit() {
121 local signal=$1; shift
123 if (( ! INFAKEROOT )); then
124 echo
125 error "$@"
127 [[ -n $srclinks ]] && rm -rf "$srclinks"
129 # unset the trap for this signal, and then call the default handler
130 trap -- "$signal"
131 kill "-$signal" "$$"
136 # Clean up function. Called automatically when the script exits.
138 clean_up() {
139 local EXIT_CODE=$?
141 if (( INFAKEROOT )); then
142 # Don't clean up when leaving fakeroot, we're not done yet.
143 return
146 if (( ! EXIT_CODE && CLEANUP )); then
147 local pkg file
149 # If it's a clean exit and -c/--clean has been passed...
150 msg "$(gettext "Cleaning up...")"
151 rm -rf "$pkgdir" "$srcdir"
152 if [[ -n $pkgbase ]]; then
153 local fullver=$(get_full_version)
154 # Can't do this unless the BUILDSCRIPT has been sourced.
155 if (( BUILDFUNC )); then
156 rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"*
158 if (( CHECKFUNC )); then
159 rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
161 if (( PKGFUNC )); then
162 rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
163 elif (( SPLITPKG )); then
164 for pkg in ${pkgname[@]}; do
165 rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"*
166 done
169 # clean up dangling symlinks to packages
170 for pkg in ${pkgname[@]}; do
171 for file in ${pkg}-*-*-${CARCH}{${PKGEXT},${SRCEXT}}; do
172 if [[ -h $file && ! -e $file ]]; then
173 rm -f "$file"
175 done
176 done
180 remove_deps
184 enter_fakeroot() {
185 msg "$(gettext "Entering %s environment...")" "fakeroot"
187 if [[ -n $newpkgver ]]; then
188 fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $?
189 else
190 fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
195 # a source entry can have two forms :
196 # 1) "filename::http://path/to/file"
197 # 2) "http://path/to/file"
199 # Return the absolute filename of a source entry
201 # This function accepts a source entry or the already extracted filename of a
202 # source entry as input
203 get_filepath() {
204 local file="$(get_filename "$1")"
206 if [[ -f "$startdir/$file" ]]; then
207 file="$startdir/$file"
208 elif [[ -f "$SRCDEST/$file" ]]; then
209 file="$SRCDEST/$file"
210 else
211 return 1
214 printf "%s\n" "$file"
217 # Print 'source not found' error message and exit makepkg
218 missing_source_file() {
219 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
220 plain "$(gettext "Aborting...")"
221 exit 1 # $E_MISSING_FILE
224 # extract the filename from a source entry
225 get_filename() {
226 # if a filename is specified, use it
227 local filename="${1%%::*}"
228 # if it is just an URL, we only keep the last component
229 printf "%s\n" "${filename##*/}"
232 # extract the URL from a source entry
233 get_url() {
234 # strip an eventual filename
235 printf "%s\n" "${1#*::}"
239 # usage : get_full_version( [$pkgname] )
240 # return : full version spec, including epoch (if necessary), pkgver, pkgrel
242 get_full_version() {
243 if [[ -z $1 ]]; then
244 if [[ $epoch ]] && (( ! $epoch )); then
245 printf "%s\n" "$pkgver-$pkgrel"
246 else
247 printf "%s\n" "$epoch:$pkgver-$pkgrel"
249 else
250 for i in pkgver pkgrel epoch; do
251 local indirect="${i}_override"
252 eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
253 [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
254 done
255 if (( ! $epoch_override )); then
256 printf "%s\n" "$pkgver_override-$pkgrel_override"
257 else
258 printf "%s\n" "$epoch_override:$pkgver_override-$pkgrel_override"
264 # Checks to see if options are present in makepkg.conf or PKGBUILD;
265 # PKGBUILD options always take precedence.
267 # usage : check_option( $option )
268 # return : y - enabled
269 # n - disabled
270 # ? - not found
272 check_option() {
273 local ret=$(in_opt_array "$1" ${options[@]})
274 if [[ $ret != '?' ]]; then
275 printf "%s\n" "$ret"
276 return
279 # fall back to makepkg.conf options
280 ret=$(in_opt_array "$1" ${OPTIONS[@]})
281 if [[ $ret != '?' ]]; then
282 printf "%s\n" "$ret"
283 return
286 echo '?' # Not Found
291 # Check if option is present in BUILDENV
293 # usage : check_buildenv( $option )
294 # return : y - enabled
295 # n - disabled
296 # ? - not found
298 check_buildenv() {
299 in_opt_array "$1" ${BUILDENV[@]}
304 # usage : in_opt_array( $needle, $haystack )
305 # return : y - enabled
306 # n - disabled
307 # ? - not found
309 in_opt_array() {
310 local needle=$1; shift
312 local opt
313 for opt in "$@"; do
314 if [[ $opt = "$needle" ]]; then
315 echo 'y' # Enabled
316 return
317 elif [[ $opt = "!$needle" ]]; then
318 echo 'n' # Disabled
319 return
321 done
323 echo '?' # Not Found
328 # usage : in_array( $needle, $haystack )
329 # return : 0 - found
330 # 1 - not found
332 in_array() {
333 local needle=$1; shift
334 local item
335 for item in "$@"; do
336 [[ $item = "$needle" ]] && return 0 # Found
337 done
338 return 1 # Not Found
341 source_has_signatures() {
342 local file
343 for file in "${source[@]}"; do
344 if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
345 return 0
347 done
348 return 1
351 get_downloadclient() {
352 # $1 = URL with valid protocol prefix
353 local url=$1
354 local proto="${url%%://*}"
356 # loop through DOWNLOAD_AGENTS variable looking for protocol
357 local i
358 for i in "${DLAGENTS[@]}"; do
359 local handler="${i%%::*}"
360 if [[ $proto = "$handler" ]]; then
361 local agent="${i##*::}"
362 break
364 done
366 # if we didn't find an agent, return an error
367 if [[ -z $agent ]]; then
368 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
369 plain "$(gettext "Aborting...")"
370 exit 1 # $E_CONFIG_ERROR
373 # ensure specified program is installed
374 local program="${agent%% *}"
375 if [[ ! -x $program ]]; then
376 local baseprog="${program##*/}"
377 error "$(gettext "The download program %s is not installed.")" "$baseprog"
378 plain "$(gettext "Aborting...")"
379 exit 1 # $E_MISSING_PROGRAM
382 printf "%s\n" "$agent"
385 download_file() {
386 # download command
387 local dlcmd=$1
388 # URL of the file
389 local url=$2
390 # destination file
391 local file=$3
392 # temporary download file, default to last component of the URL
393 local dlfile="${url##*/}"
395 # replace %o by the temporary dlfile if it exists
396 if [[ $dlcmd = *%o* ]]; then
397 dlcmd=${dlcmd//\%o/\"$file.part\"}
398 dlfile="$file.part"
400 # add the URL, either in place of %u or at the end
401 if [[ $dlcmd = *%u* ]]; then
402 dlcmd=${dlcmd//\%u/\"$url\"}
403 else
404 dlcmd="$dlcmd \"$url\""
407 local ret=0
408 eval "$dlcmd || ret=\$?"
409 if (( ret )); then
410 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
411 return $ret
414 # rename the temporary download file to the final destination
415 if [[ $dlfile != "$file" ]]; then
416 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$file"
420 run_pacman() {
421 local cmd
422 if [[ ! $1 = -@(T|Qq) ]]; then
423 cmd=("$PACMAN" $PACMAN_OPTS "$@")
424 else
425 cmd=("$PACMAN" "$@")
427 if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then
428 if type -p sudo >/dev/null; then
429 cmd=(sudo "${cmd[@]}")
430 else
431 cmd=(su root -c "$(printf '%q ' "${cmd[@]}")")
434 "${cmd[@]}"
437 check_deps() {
438 (( $# > 0 )) || return 0
440 local ret=0
441 local pmout
442 pmout=$(run_pacman -T "$@")
443 ret=$?
445 if (( ret == 127 )); then #unresolved deps
446 printf "%s\n" "$pmout"
447 elif (( ret )); then
448 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
449 return "$ret"
453 handle_deps() {
454 local R_DEPS_SATISFIED=0
455 local R_DEPS_MISSING=1
457 (( $# == 0 )) && return $R_DEPS_SATISFIED
459 local deplist="$*"
461 if (( ! DEP_BIN )); then
462 return $R_DEPS_MISSING
465 if (( DEP_BIN )); then
466 # install missing deps from binary packages (using pacman -S)
467 msg "$(gettext "Installing missing dependencies...")"
469 if ! run_pacman -S --asdeps $deplist; then
470 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
471 exit 1 # TODO: error code
475 # we might need the new system environment
476 # save our shell options and turn off extglob
477 local shellopts=$(shopt -p)
478 shopt -u extglob
479 source /etc/profile &>/dev/null
480 eval "$shellopts"
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 printf "%s\n" "${integlist[@]}"
593 else
594 printf "%s\n" "${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 printf "%s" "${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 )) && printf "%s" "$indent"
640 printf "%s" "'$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 printf "%s" " $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 cd_safe() {
873 if ! cd "$1"; then
874 error "$(gettext "Failed to change to directory %s")" "$1"
875 plain "$(gettext "Aborting...")"
876 exit 1
880 source_safe() {
881 shopt -u extglob
882 if ! source "$@"; then
883 error "$(gettext "Failed to source %s")" "$1"
884 exit 1
886 shopt -s extglob
889 run_function_safe() {
890 local restoretrap
892 set -e
893 set -E
895 restoretrap=$(trap -p ERR)
896 trap 'error_function $pkgfunc' ERR
898 run_function "$1"
900 eval $restoretrap
902 set +E
903 set +e
906 run_function() {
907 if [[ -z $1 ]]; then
908 return 1
910 local pkgfunc="$1"
912 # clear user-specified buildflags if requested
913 if [[ $(check_option buildflags) = "n" ]]; then
914 unset CFLAGS CXXFLAGS LDFLAGS
917 # clear user-specified makeflags if requested
918 if [[ $(check_option makeflags) = "n" ]]; then
919 unset MAKEFLAGS
922 msg "$(gettext "Starting %s()...")" "$pkgfunc"
923 cd_safe "$srcdir"
925 # ensure all necessary build variables are exported
926 export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
927 # save our shell options so pkgfunc() can't override what we need
928 local shellopts=$(shopt -p)
930 local ret=0
931 if (( LOGGING )); then
932 local fullver=$(get_full_version)
933 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
934 if [[ -f $BUILDLOG ]]; then
935 local i=1
936 while true; do
937 if [[ -f $BUILDLOG.$i ]]; then
938 i=$(($i +1))
939 else
940 break
942 done
943 mv "$BUILDLOG" "$BUILDLOG.$i"
946 # ensure overridden package variables survive tee with split packages
947 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
948 mkfifo "$logpipe"
949 tee "$BUILDLOG" < "$logpipe" &
950 local teepid=$!
952 $pkgfunc &>"$logpipe"
954 wait $teepid
955 rm "$logpipe"
956 else
957 $pkgfunc 2>&1
959 # reset our shell options
960 eval "$shellopts"
963 run_build() {
964 # use distcc if it is requested (check buildenv and PKGBUILD opts)
965 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
966 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
967 export DISTCC_HOSTS
970 # use ccache if it is requested (check buildenv and PKGBUILD opts)
971 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
972 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
975 run_function_safe "build"
978 run_check() {
979 run_function_safe "check"
982 run_package() {
983 local pkgfunc
984 if [[ -z $1 ]]; then
985 pkgfunc="package"
986 else
987 pkgfunc="package_$1"
990 run_function_safe "$pkgfunc"
993 tidy_install() {
994 cd_safe "$pkgdir"
995 msg "$(gettext "Tidying install...")"
997 if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then
998 msg2 "$(gettext "Removing doc files...")"
999 rm -rf -- ${DOC_DIRS[@]}
1002 if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then
1003 msg2 "$(gettext "Purging unwanted files...")"
1004 local pt
1005 for pt in "${PURGE_TARGETS[@]}"; do
1006 if [[ ${pt} = "${pt//\/}" ]]; then
1007 find . -type f -name "${pt}" -exec rm -f -- '{}' \;
1008 else
1009 rm -f ${pt}
1011 done
1014 if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then
1015 msg2 "$(gettext "Compressing man and info pages...")"
1016 local manpage ext file link hardlinks hl
1017 find ${MAN_DIRS[@]} -type f 2>/dev/null |
1018 while read manpage ; do
1019 ext="${manpage##*.}"
1020 file="${manpage##*/}"
1021 if [[ $ext != gz && $ext != bz2 ]]; then
1022 # update symlinks to this manpage
1023 find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null |
1024 while read link ; do
1025 rm -f "$link" "${link}.gz"
1026 ln -s -- "${file}.gz" "${link}.gz"
1027 done
1029 # check file still exists (potentially already compressed due to hardlink)
1030 if [[ -f ${manpage} ]]; then
1031 # find hard links and remove them
1032 # the '|| true' part keeps the script from bailing on the EOF returned
1033 # by read at the end of the find output
1034 IFS=$'\n' read -rd '' -a hardlinks < \
1035 <(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" \
1036 2>/dev/null || true) || true
1037 rm -f "${hardlinks[@]}"
1038 # compress the original
1039 gzip -9 "$manpage"
1040 # recreate hard links removed earlier
1041 for hl in "${hardlinks[@]}"; do
1042 ln "${manpage}.gz" "${hl}.gz"
1043 chmod 644 ${hl}.gz
1044 done
1047 done
1050 if [[ $(check_option strip) = "y" ]]; then
1051 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1052 # make sure library stripping variables are defined to prevent excess stripping
1053 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1054 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1055 local binary
1056 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1057 case "$(file -bi "$binary")" in
1058 *application/x-sharedlib*) # Libraries (.so)
1059 strip $STRIP_SHARED "$binary";;
1060 *application/x-archive*) # Libraries (.a)
1061 strip $STRIP_STATIC "$binary";;
1062 *application/x-executable*) # Binaries
1063 strip $STRIP_BINARIES "$binary";;
1064 esac
1065 done
1068 if [[ $(check_option libtool) = "n" ]]; then
1069 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1070 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1073 if [[ $(check_option emptydirs) = "n" ]]; then
1074 msg2 "$(gettext "Removing empty directories...")"
1075 find . -depth -type d -empty -delete
1078 if [[ $(check_option upx) = "y" ]]; then
1079 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1080 local binary
1081 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1082 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1083 upx $UPXFLAGS "$binary" &>/dev/null ||
1084 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1086 done
1090 find_libdepends() {
1091 local libdepends
1092 find "$pkgdir" -type f -perm -u+x | while read filename
1094 # get architecture of the file; if soarch is empty it's not an ELF binary
1095 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1096 [ -n "$soarch" ] || continue
1097 # process all libraries needed by the binary
1098 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1100 # extract the library name: libfoo.so
1101 soname="${sofile%.so?(+(.+([0-9])))}".so
1102 # extract the major version: 1
1103 soversion="${sofile##*\.so\.}"
1104 if in_array "${soname}" ${depends[@]}; then
1105 if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then
1106 # libfoo.so=1-64
1107 printf "%s" "${soname}=${soversion}-${soarch}"
1108 libdepends+=("${soname}=${soversion}-${soarch}")
1111 done
1112 done
1115 find_libprovides() {
1116 local libprovides missing
1117 for p in "${provides[@]}"; do
1118 missing=0
1119 case "$p" in
1120 *.so)
1121 IFS=$'\n' read -rd '' -a filename < <(find "$pkgdir" -type f -name $p\*)
1122 if [[ $filename ]]; then
1123 # packages may provide multiple versions of the same library
1124 for fn in "${filename[@]}"; do
1125 # check if we really have a shared object
1126 if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1127 # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1)
1128 local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1129 if [[ -z "$sofile" ]]; then
1130 warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p"
1131 libprovides+=("$p")
1132 continue
1135 # get the library architecture (32 or 64 bit)
1136 local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1138 # extract the library major version
1139 local soversion="${sofile##*\.so\.}"
1141 libprovides+=("${p}=${soversion}-${soarch}")
1142 else
1143 warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p"
1144 libprovides+=("$p")
1146 done
1147 else
1148 libprovides+=("$p")
1149 missing=1
1153 libprovides+=("$p")
1155 esac
1157 if (( missing )); then
1158 warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p"
1160 done
1162 printf '%s\n' "${libprovides[@]}"
1165 check_license() {
1166 # TODO maybe remove this at some point
1167 # warn if license array is not present or empty
1168 if [[ -z $license ]]; then
1169 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1170 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1174 write_pkginfo() {
1175 local builddate=$(date -u "+%s")
1176 if [[ -n $PACKAGER ]]; then
1177 local packager="$PACKAGER"
1178 else
1179 local packager="Unknown Packager"
1182 # btrfs's delayed allocation causes the stat buffers from the kernel to "lie"
1183 # to us momentarily and report 0 blocks allocated (which is how du calculates
1184 # size). Sleeping for a second here is about the dirtiest thing possible,
1185 # but avoids reporting entirely bogus install sizes.
1186 sleep 1
1187 local size="$(@DUPATH@ -sk)"
1188 size="$(( ${size%%[^0-9]*} * 1024 ))"
1190 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1191 echo "# Generated by makepkg $myver"
1192 if (( INFAKEROOT )); then
1193 echo "# using $(fakeroot -v)"
1195 echo "# $(LC_ALL=C date -u)"
1196 printf "pkgname = %s\n" "$1"
1197 (( SPLITPKG )) && echo pkgbase = $pkgbase
1198 echo "pkgver = $(get_full_version)"
1199 printf "pkgdesc = %s\n" "$pkgdesc"
1200 printf "url = %s\n" "$url"
1201 printf "builddate = %s\n" "$builddate"
1202 printf "packager = %s\n" "$packager"
1203 printf "size = %s\n" "$size"
1204 printf "arch = %s\n" "$PKGARCH"
1206 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1207 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1208 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1209 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1210 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1212 IFS=$'\n' read -rd '' -a provides < <(find_libprovides)
1213 [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
1215 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1218 local it
1219 IFS=$'\n' read -rd '' -a libdepends < <(find_libdepends)
1220 depends+=("${libdepends[@]}")
1222 for it in "${depends[@]}"; do
1223 if [[ $it = *.so ]]; then
1224 # check if the entry has been found by find_libdepends
1225 # if not, it's unneeded; tell the user so he can remove it
1226 printf -v re '(^|\s)%s=.*' "$it"
1227 if [[ ! $libdepends =~ $re ]]; then
1228 error "$(gettext "Cannot find library listed in %s: %s")" "'depends'" "$it"
1229 return 1
1231 else
1232 printf "depend = %s\n" "$it"
1234 done
1236 for it in "${packaging_options[@]}"; do
1237 local ret="$(check_option $it)"
1238 if [[ $ret != "?" ]]; then
1239 if [[ $ret = "y" ]]; then
1240 printf "makepkgopt = %s\n" "$it"
1241 else
1242 printf "makepkgopt = %s\n" "!$it"
1245 done
1247 check_license
1250 check_package() {
1251 cd_safe "$pkgdir"
1253 # check existence of backup files
1254 local file
1255 for file in "${backup[@]}"; do
1256 if [[ ! -f $file ]]; then
1257 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1259 done
1261 # check for references to the build and package directory
1262 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1263 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1265 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1266 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1271 create_package() {
1272 if [[ ! -d $pkgdir ]]; then
1273 error "$(gettext "Missing %s directory.")" "pkg/"
1274 plain "$(gettext "Aborting...")"
1275 exit 1 # $E_MISSING_PKGDIR
1278 check_package
1280 cd_safe "$pkgdir"
1281 msg "$(gettext "Creating package...")"
1283 local nameofpkg
1284 if [[ -z $1 ]]; then
1285 nameofpkg="$pkgname"
1286 else
1287 nameofpkg="$1"
1290 if [[ $arch = "any" ]]; then
1291 PKGARCH="any"
1292 else
1293 PKGARCH=$CARCH
1296 write_pkginfo $nameofpkg > .PKGINFO
1298 local comp_files=('.PKGINFO')
1300 # check for changelog/install files
1301 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1302 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1304 if [[ -n ${!orig} ]]; then
1305 msg2 "$(gettext "Adding %s file...")" "$orig"
1306 cp "$startdir/${!orig}" "$dest"
1307 chmod 644 "$dest"
1308 comp_files+=("$dest")
1310 done
1312 # tar it up
1313 msg2 "$(gettext "Compressing package...")"
1315 local fullver=$(get_full_version)
1316 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}"
1317 local ret=0
1319 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1320 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1322 # when fileglobbing, we want * in an empty directory to expand to
1323 # the null string rather than itself
1324 shopt -s nullglob
1325 # TODO: Maybe this can be set globally for robustness
1326 shopt -s -o pipefail
1327 # bsdtar's gzip compression always saves the time stamp, making one
1328 # archive created using the same command line distinct from another.
1329 # Disable bsdtar compression and use gzip -n for now.
1330 bsdtar -cf - "${comp_files[@]}" * |
1331 case "$PKGEXT" in
1332 *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;;
1333 *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;;
1334 *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;;
1335 *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;;
1336 *tar) cat ;;
1337 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1338 "$PKGEXT"; cat ;;
1339 esac > "${pkg_file}" || ret=$?
1341 shopt -u nullglob
1342 shopt -u -o pipefail
1344 if (( ret )); then
1345 error "$(gettext "Failed to create package file.")"
1346 exit 1 # TODO: error code
1349 create_signature "$pkg_file"
1351 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1352 rm -f "${pkg_file/$PKGDEST/$startdir}"
1353 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1354 ret=$?
1355 if [[ -f $pkg_file.sig ]]; then
1356 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1357 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1361 if (( ret )); then
1362 warning "$(gettext "Failed to create symlink to package file.")"
1366 create_signature() {
1367 if [[ $SIGNPKG != 'y' ]]; then
1368 return
1370 local ret=0
1371 local filename="$1"
1372 msg "$(gettext "Signing package...")"
1374 local SIGNWITHKEY=""
1375 if [[ -n $GPGKEY ]]; then
1376 SIGNWITHKEY="-u ${GPGKEY}"
1378 # The signature will be generated directly in ascii-friendly format
1379 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1382 if (( ! ret )); then
1383 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1384 else
1385 warning "$(gettext "Failed to sign package file.")"
1389 create_srcpackage() {
1390 local ret=0
1391 msg "$(gettext "Creating source package...")"
1392 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1393 mkdir "${srclinks}"/${pkgbase}
1395 check_license
1397 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1398 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1400 local file
1401 for file in "${source[@]}"; do
1402 if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then
1403 local absfile
1404 absfile=$(get_filepath "$file") || missing_source_file "$file"
1405 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1406 ln -s "$absfile" "$srclinks/$pkgbase"
1408 done
1410 local i
1411 for i in 'changelog' 'install'; do
1412 local file
1413 while read -r file; do
1414 # evaluate any bash variables used
1415 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1416 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1417 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1418 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1420 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1421 done
1423 local TAR_OPT
1424 case "$SRCEXT" in
1425 *tar.gz) TAR_OPT="z" ;;
1426 *tar.bz2) TAR_OPT="j" ;;
1427 *tar.xz) TAR_OPT="J" ;;
1428 *tar.Z) TAR_OPT="Z" ;;
1429 *tar) TAR_OPT="" ;;
1430 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1431 "$SRCEXT" ;;
1432 esac
1434 local fullver=$(get_full_version)
1435 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1437 # tar it up
1438 msg2 "$(gettext "Compressing source package...")"
1439 cd_safe "${srclinks}"
1440 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1441 error "$(gettext "Failed to create source package file.")"
1442 exit 1 # TODO: error code
1445 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1446 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1447 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1448 ret=$?
1451 if (( ret )); then
1452 warning "$(gettext "Failed to create symlink to source package file.")"
1455 cd_safe "${startdir}"
1456 rm -rf "${srclinks}"
1459 install_package() {
1460 (( ! INSTALL )) && return
1462 if (( ! SPLITPKG )); then
1463 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1464 else
1465 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1468 local fullver pkg pkglist
1469 for pkg in ${pkgname[@]}; do
1470 fullver=$(get_full_version $pkg)
1471 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} ]]; then
1472 pkglist+=" $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT}"
1473 else
1474 pkglist+=" $PKGDEST/${pkg}-${fullver}-any${PKGEXT}"
1476 done
1478 if ! run_pacman -U $pkglist; then
1479 warning "$(gettext "Failed to install built package(s).")"
1480 return 0
1484 check_sanity() {
1485 # check for no-no's in the build script
1486 local i
1487 local ret=0
1488 for i in 'pkgname' 'pkgrel' 'pkgver'; do
1489 if [[ -z ${!i} ]]; then
1490 error "$(gettext "%s is not allowed to be empty.")" "$i"
1491 ret=1
1493 done
1495 for i in "${pkgname[@]}"; do
1496 if [[ ${i:0:1} = "-" ]]; then
1497 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1498 ret=1
1500 done
1502 if [[ ${pkgbase:0:1} = "-" ]]; then
1503 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1504 ret=1
1507 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1508 while IFS='=' read -r _ i; do
1509 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1510 if [[ $i = *[[:space:]:-]* ]]; then
1511 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
1512 return 1
1514 done || ret=1
1516 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1517 while IFS='=' read -r _ i; do
1518 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1519 if [[ $i != +([0-9])?(.+([0-9])) ]]; then
1520 error "$(gettext "%s must be a decimal.")" "pkgrel"
1521 return 1
1523 done || ret=1
1525 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1526 while IFS='=' read -r _ i; do
1527 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1528 if [[ $i != *([[:digit:]]) ]]; then
1529 error "$(gettext "%s must be an integer.")" "epoch"
1530 return 1
1532 done || ret=1
1534 if [[ $arch != 'any' ]]; then
1535 if ! in_array $CARCH ${arch[@]}; then
1536 if (( ! IGNOREARCH )); then
1537 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1538 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1539 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1540 ret=1
1545 if (( ${#pkgname[@]} > 1 )); then
1546 for i in ${pkgname[@]}; do
1547 local arch_list=""
1548 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1549 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1550 if ! in_array $CARCH ${arch_list[@]}; then
1551 if (( ! IGNOREARCH )); then
1552 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1553 ret=1
1557 done
1560 local provides_list=()
1561 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1562 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1563 for i in ${provides_list[@]}; do
1564 if [[ $i == *['<>']* ]]; then
1565 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1566 ret=1
1568 done
1570 local backup_list=()
1571 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1572 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1573 for i in "${backup_list[@]}"; do
1574 if [[ ${i:0:1} = "/" ]]; then
1575 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1576 ret=1
1578 done
1580 local optdepends_list=()
1581 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1582 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1583 for i in "${optdepends_list[@]}"; do
1584 local pkg=${i%%:[[:space:]]*}
1585 # the '-' character _must_ be first or last in the character range
1586 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1587 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1588 ret=1
1590 done
1592 for i in 'changelog' 'install'; do
1593 local file
1594 while read -r file; do
1595 # evaluate any bash variables used
1596 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1597 if [[ $file && ! -f $file ]]; then
1598 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1599 ret=1
1601 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1602 done
1604 local valid_options=1
1605 local known kopt options_list
1606 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1607 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1608 for i in ${options_list[@]}; do
1609 known=0
1610 # check if option matches a known option or its inverse
1611 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1612 if [[ ${i} = "${kopt}" || ${i} = "!${kopt}" ]]; then
1613 known=1
1615 done
1616 if (( ! known )); then
1617 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1618 valid_options=0
1620 done
1621 if (( ! valid_options )); then
1622 ret=1
1625 if (( ${#pkgname[@]} > 1 )); then
1626 for i in ${pkgname[@]}; do
1627 if ! declare -f package_${i} >/dev/null; then
1628 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1629 ret=1
1631 done
1634 for i in ${PKGLIST[@]}; do
1635 if ! in_array $i ${pkgname[@]}; then
1636 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1637 ret=1
1639 done
1641 return $ret
1644 check_software() {
1645 # check for needed software
1646 local ret=0
1648 # check for sudo if we will need it during makepkg execution
1649 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1650 if ! type -p sudo >/dev/null; then
1651 warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")"
1655 # fakeroot - building as non-root user
1656 if [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then
1657 if ! type -p fakeroot >/dev/null; then
1658 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
1659 ret=1
1663 # gpg - package signing
1664 if [[ $SIGNPKG == 'y' || (-z "$SIGNPKG" && $(check_buildenv sign) == 'y') ]]; then
1665 if ! type -p gpg >/dev/null; then
1666 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
1667 ret=1
1671 # gpg - source verification
1672 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
1673 if ! type -p gpg >/dev/null; then
1674 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
1675 ret=1
1679 # openssl - checksum operations
1680 if (( ! SKIPCHECKSUMS )); then
1681 if ! type -p openssl >/dev/null; then
1682 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
1683 ret=1
1687 # upx - binary compression
1688 if [[ $(check_option upx) == 'y' ]]; then
1689 if ! type -p upx >/dev/null; then
1690 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
1691 ret=1
1695 # distcc - compilation with distcc
1696 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
1697 if ! type -p distcc >/dev/null; then
1698 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
1699 ret=1
1703 # ccache - compilation with ccache
1704 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
1705 if ! type -p ccache >/dev/null; then
1706 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
1707 ret=1
1711 # strip - strip symbols from binaries/libraries
1712 if [[ $(check_option strip) = "y" ]]; then
1713 if ! type -p strip >/dev/null; then
1714 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
1715 ret=1
1719 # gzip - compressig man and info pages
1720 if [[ $(check_option zipman) = "y" ]]; then
1721 if ! type -p gzip >/dev/null; then
1722 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
1723 ret=1
1727 return $ret
1730 devel_check() {
1731 newpkgver=""
1733 # Do not update pkgver if --holdver is set, when building a source package, repackaging,
1734 # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w)
1735 if (( HOLDVER || SOURCEONLY || REPKG )) ||
1736 [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = "/dev/stdin" ]]; then
1737 return
1740 if [[ -z $FORCE_VER ]]; then
1741 # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so.
1742 # This will only be used on the first call to makepkg; subsequent
1743 # calls to makepkg via fakeroot will explicitly pass the version
1744 # number to avoid having to determine the version number twice.
1745 # Also do a check to make sure we have the VCS tool available.
1746 local vcs=()
1748 [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] && vcs+=("darcs")
1749 [[ -n ${_cvsroot} && -n ${_cvsmod} ]] && vcs+=("cvs")
1750 [[ -n ${_gitroot} && -n ${_gitname} ]] && vcs+=("git")
1751 [[ -n ${_svntrunk} && -n ${_svnmod} ]] && vcs+=("svn")
1752 [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] && vcs+=("bzr")
1753 [[ -n ${_hgroot} && -n ${_hgrepo} ]] && vcs+=("hg")
1755 if (( ${#vcs[@]} == 0 )); then
1756 return
1757 elif (( ${#vcs[@]} > 1 )); then
1758 warning "$(gettext "Ambiguous VCS package. Cannot pick from: %s.")" "${vcs[*]}"
1759 return 0
1762 if ! type -p "$vcs" >/dev/null; then
1763 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "$vcs" "$vcs"
1764 return 0
1767 msg "$(gettext "Determining latest %s revision...")" "$vcs"
1769 case "$vcs" in
1770 darcs)
1771 newpkgver=$(date +%Y%m%d)
1773 cvs)
1774 newpkgver=$(date +%Y%m%d)
1776 git)
1777 newpkgver=$(date +%Y%m%d)
1779 svn)
1780 newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p')
1782 bzr)
1783 newpkgver=$(bzr revno ${_bzrtrunk})
1786 if pushd "./src/$_hgrepo" > /dev/null; then
1787 local ret=0
1788 hg pull || ret=$?
1789 if (( ! ret )); then
1790 hg update
1791 elif (( ret != 1 )); then
1792 return 1
1794 else
1795 [[ ! -d ./src/ ]] && mkdir ./src/
1796 hg clone "$_hgroot/$_hgrepo" "./src/$_hgrepo"
1797 if ! pushd "./src/$_hgrepo" > /dev/null; then
1798 warning "$(gettext "An error occured while determining the hg version number.")"
1799 return 0
1802 newpkgver=$(hg tip --template "{rev}")
1803 popd > /dev/null
1805 esac
1807 if [[ -n $newpkgver ]]; then
1808 msg2 "$(gettext "Version found: %s")" "$newpkgver"
1811 else
1812 # Version number retrieved from fakeroot->makepkg argument
1813 newpkgver=$FORCE_VER
1817 devel_update() {
1818 # This is lame, but if we're wanting to use an updated pkgver for
1819 # retrieving svn/cvs/etc sources, we'll update the PKGBUILD with
1820 # the new pkgver and then re-source it. This is the most robust
1821 # method for dealing with PKGBUILDs that use, e.g.:
1823 # pkgver=23
1824 # ...
1825 # _foo=pkgver
1827 if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then
1828 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
1829 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
1830 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
1831 source "$BUILDFILE"
1832 else
1833 warning "$(gettext "%s is not writeable -- pkgver will not be updated")" "$BUILDFILE"
1838 backup_package_variables() {
1839 local var
1840 for var in ${splitpkg_overrides[@]}; do
1841 local indirect="${var}_backup"
1842 eval "${indirect}=(\"\${$var[@]}\")"
1843 done
1846 restore_package_variables() {
1847 local var
1848 for var in ${splitpkg_overrides[@]}; do
1849 local indirect="${var}_backup"
1850 if [[ -n ${!indirect} ]]; then
1851 eval "${var}=(\"\${$indirect[@]}\")"
1852 else
1853 unset ${var}
1855 done
1858 run_split_packaging() {
1859 local pkgname_backup=${pkgname[@]}
1860 for pkgname in ${pkgname_backup[@]}; do
1861 pkgdir="$pkgdir/$pkgname"
1862 mkdir -p "$pkgdir"
1863 chmod a-s "$pkgdir"
1864 backup_package_variables
1865 run_package $pkgname
1866 tidy_install
1867 create_package $pkgname
1868 restore_package_variables
1869 pkgdir="${pkgdir%/*}"
1870 done
1871 pkgname=${pkgname_backup[@]}
1874 # Canonicalize a directory path if it exists
1875 canonicalize_path() {
1876 local path="$1";
1878 if [[ -d $path ]]; then
1880 cd_safe "$path"
1881 pwd -P
1883 else
1884 printf "%s\n" "$path"
1888 m4_include(library/parse_options.sh)
1890 usage() {
1891 printf "makepkg (pacman) %s\n" "$myver"
1892 echo
1893 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
1894 echo
1895 printf -- "$(gettext "Options:")\n"
1896 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
1897 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
1898 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
1899 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
1900 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
1901 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
1902 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
1903 printf -- "$(gettext " -i, --install Install package after successful build")\n"
1904 printf -- "$(gettext " -L, --log Log package build process")\n"
1905 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
1906 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
1907 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
1908 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
1909 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
1910 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
1911 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
1912 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
1913 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
1914 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1915 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
1916 printf -- "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT"
1917 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
1918 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1919 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
1920 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
1921 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
1922 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
1923 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
1924 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
1925 echo
1926 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
1927 echo
1928 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
1929 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
1930 echo
1931 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
1932 echo
1935 version() {
1936 printf "makepkg (pacman) %s\n" "$myver"
1937 printf -- "$(gettext "\
1938 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
1939 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
1940 This is free software; see the source for copying conditions.\n\
1941 There is NO WARRANTY, to the extent permitted by law.\n")"
1944 # PROGRAM START
1946 # determine whether we have gettext; make it a no-op if we do not
1947 if ! type -p gettext >/dev/null; then
1948 gettext() {
1949 printf "%s\n" "$@"
1953 ARGLIST=("$@")
1955 # Parse Command Line Options.
1956 OPT_SHORT="AcdefFghiLmop:rRsSV"
1957 OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps"
1958 OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver,skippgpcheck"
1959 OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps"
1960 OPT_LONG+=",repackage,skipchecksums,skipinteg,skippgpcheck,sign,source,syncdeps"
1961 OPT_LONG+=",version,config:"
1963 # Pacman Options
1964 OPT_LONG+=",noconfirm,noprogressbar"
1965 if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then
1966 echo; usage; exit 1 # E_INVALID_OPTION;
1968 eval set -- "$OPT_TEMP"
1969 unset OPT_SHORT OPT_LONG OPT_TEMP
1971 while true; do
1972 case "$1" in
1973 # Pacman Options
1974 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
1975 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
1977 # Makepkg Options
1978 --allsource) SOURCEONLY=2 ;;
1979 --asroot) ASROOT=1 ;;
1980 -A|--ignorearch) IGNOREARCH=1 ;;
1981 -c|--clean) CLEANUP=1 ;;
1982 --check) RUN_CHECK='y' ;;
1983 --config) shift; MAKEPKG_CONF=$1 ;;
1984 -d|--nodeps) NODEPS=1 ;;
1985 -e|--noextract) NOEXTRACT=1 ;;
1986 -f|--force) FORCE=1 ;;
1987 #hidden opt used by fakeroot call for svn/cvs/etc PKGBUILDs to set pkgver
1988 --forcever) shift; FORCE_VER=$1;;
1989 -F) INFAKEROOT=1 ;;
1990 -g|--geninteg) GENINTEG=1 ;;
1991 --holdver) HOLDVER=1 ;;
1992 -i|--install) INSTALL=1 ;;
1993 --key) shift; GPGKEY=$1 ;;
1994 -L|--log) LOGGING=1 ;;
1995 -m|--nocolor) USE_COLOR='n' ;;
1996 --nocheck) RUN_CHECK='n' ;;
1997 --nosign) SIGNPKG='n' ;;
1998 -o|--nobuild) NOBUILD=1 ;;
1999 -p) shift; BUILDFILE=$1 ;;
2000 --pkg) shift; PKGLIST=($1) ;;
2001 -r|--rmdeps) RMDEPS=1 ;;
2002 -R|--repackage) REPKG=1 ;;
2003 --skipchecksums) SKIPCHECKSUMS=1 ;;
2004 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
2005 --skippgpcheck) SKIPPGPCHECK=1;;
2006 --sign) SIGNPKG='y' ;;
2007 -s|--syncdeps) DEP_BIN=1 ;;
2008 -S|--source) SOURCEONLY=1 ;;
2010 -h|--help) usage; exit 0 ;; # E_OK
2011 -V|--version) version; exit 0 ;; # E_OK
2013 --) OPT_IND=0; shift; break;;
2014 *) usage; exit 1 ;; # E_INVALID_OPTION
2015 esac
2016 shift
2017 done
2019 # setup signal traps
2020 trap 'clean_up' 0
2021 for signal in TERM HUP QUIT; do
2022 trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
2023 done
2024 trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT
2025 trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR
2027 # preserve environment variables and canonicalize path
2028 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
2029 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
2030 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
2031 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
2032 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
2033 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
2034 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
2035 [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
2037 # default config is makepkg.conf
2038 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
2040 # Source the config file; fail if it is not found
2041 if [[ -r $MAKEPKG_CONF ]]; then
2042 source_safe "$MAKEPKG_CONF"
2043 else
2044 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
2045 plain "$(gettext "Aborting...")"
2046 exit 1 # $E_CONFIG_ERROR
2049 # Source user-specific makepkg.conf overrides, but only if no override config
2050 # file was specified
2051 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
2052 source_safe ~/.makepkg.conf
2055 # set pacman command if not already defined
2056 PACMAN=${PACMAN:-pacman}
2058 # check if messages are to be printed using color
2059 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2060 if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then
2061 # prefer terminal safe colored and bold text when tput is supported
2062 if tput setaf 0 &>/dev/null; then
2063 ALL_OFF="$(tput sgr0)"
2064 BOLD="$(tput bold)"
2065 BLUE="${BOLD}$(tput setaf 4)"
2066 GREEN="${BOLD}$(tput setaf 2)"
2067 RED="${BOLD}$(tput setaf 1)"
2068 YELLOW="${BOLD}$(tput setaf 3)"
2069 else
2070 ALL_OFF="\e[1;0m"
2071 BOLD="\e[1;1m"
2072 BLUE="${BOLD}\e[1;34m"
2073 GREEN="${BOLD}\e[1;32m"
2074 RED="${BOLD}\e[1;31m"
2075 YELLOW="${BOLD}\e[1;33m"
2078 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2080 # override settings with an environment variable for batch processing
2081 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2082 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2083 if [[ ! -d $BUILDDIR ]]; then
2084 if ! mkdir -p "$BUILDDIR"; then
2085 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2086 plain "$(gettext "Aborting...")"
2087 exit 1
2089 chmod a-s "$BUILDDIR"
2091 if [[ ! -w $BUILDDIR ]]; then
2092 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2093 plain "$(gettext "Aborting...")"
2094 exit 1
2097 PKGDEST=${_PKGDEST:-$PKGDEST}
2098 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2099 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2100 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2101 plain "$(gettext "Aborting...")"
2102 exit 1
2105 SRCDEST=${_SRCDEST:-$SRCDEST}
2106 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2107 if [[ ! -w $SRCDEST ]] ; then
2108 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2109 plain "$(gettext "Aborting...")"
2110 exit 1
2113 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2114 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2115 if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then
2116 error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
2117 plain "$(gettext "Aborting...")"
2118 exit 1
2121 PKGEXT=${_PKGEXT:-$PKGEXT}
2122 SRCEXT=${_SRCEXT:-$SRCEXT}
2123 GPGKEY=${_GPGKEY:-$GPGKEY}
2124 PACKAGER=${_PACKAGER:-$PACKAGER}
2126 if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then
2127 # The '\\0' is here to prevent gettext from thinking --holdver is an option
2128 error "$(gettext "\\0%s and %s cannot both be specified" )" "--holdver" "--forcever"
2129 exit 1
2132 if (( ! INFAKEROOT )); then
2133 if (( EUID == 0 && ! ASROOT )); then
2134 # Warn those who like to live dangerously.
2135 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2136 catastrophic damage to your system. If you wish to run as root, please\n\
2137 use the %s option.")" "makepkg" "--asroot"
2138 exit 1 # $E_USER_ABORT
2139 elif (( EUID > 0 && ASROOT )); then
2140 # Warn those who try to use the --asroot option when they are not root
2141 error "$(gettext "The %s option is meant for the root user only. Please\n\
2142 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2143 exit 1 # $E_USER_ABORT
2144 elif (( EUID > 0 )) && [[ $(check_buildenv fakeroot) != "y" ]]; then
2145 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2146 ownership of the packaged files. Try using the %s environment by\n\
2147 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2148 sleep 1
2150 else
2151 if [[ -z $FAKEROOTKEY ]]; then
2152 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2153 exit 1 # TODO: error code
2157 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2158 unset md5sums replaces depends conflicts backup source install changelog build
2159 unset makedepends optdepends options noextract
2161 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2162 if [[ ! -f $BUILDFILE ]]; then
2163 if [[ -t 0 ]]; then
2164 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2165 exit 1
2166 else
2167 # PKGBUILD passed through a pipe
2168 BUILDFILE=/dev/stdin
2169 source_safe "$BUILDFILE"
2171 else
2172 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2173 if [[ -n $crlftest ]]; then
2174 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2175 exit 1
2178 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2179 BUILDFILE="$startdir/$BUILDFILE"
2181 source_safe "$BUILDFILE"
2184 # set defaults if they weren't specified in buildfile
2185 pkgbase=${pkgbase:-${pkgname[0]}}
2186 epoch=${epoch:-0}
2188 if [[ $BUILDDIR = "$startdir" ]]; then
2189 srcdir="$BUILDDIR/src"
2190 pkgdir="$BUILDDIR/pkg"
2191 else
2192 srcdir="$BUILDDIR/$pkgbase/src"
2193 pkgdir="$BUILDDIR/$pkgbase/pkg"
2196 if (( GENINTEG )); then
2197 mkdir -p "$srcdir"
2198 chmod a-s "$srcdir"
2199 cd_safe "$srcdir"
2200 download_sources
2201 generate_checksums
2202 exit 0 # $E_OK
2205 # check the PKGBUILD for some basic requirements
2206 check_sanity || exit 1
2208 # check we have the software required to process the PKGBUILD
2209 check_software || exit 1
2211 # We need to run devel_update regardless of whether we are in the fakeroot
2212 # build process so that if the user runs makepkg --forcever manually, we
2213 # 1) output the correct pkgver, and 2) use the correct filename when
2214 # checking if the package file already exists - fixes FS #9194
2215 devel_check
2216 devel_update
2218 if (( ${#pkgname[@]} > 1 )); then
2219 SPLITPKG=1
2222 # test for available PKGBUILD functions
2223 if declare -f build >/dev/null; then
2224 BUILDFUNC=1
2226 if declare -f check >/dev/null; then
2227 # "Hide" check() function if not going to be run
2228 if [[ $RUN_CHECK = 'y' || (! $(check_buildenv check) = "n" && ! $RUN_CHECK = "n") ]]; then
2229 CHECKFUNC=1
2232 if declare -f package >/dev/null; then
2233 PKGFUNC=1
2234 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2235 SPLITPKG=1
2238 if [[ -n "${PKGLIST[@]}" ]]; then
2239 unset pkgname
2240 pkgname=("${PKGLIST[@]}")
2243 # check if gpg signature is to be created and if signing key is valid
2244 [[ -z $SIGNPKG ]] && SIGNPKG=$(check_buildenv sign)
2245 if [[ $SIGNPKG == 'y' ]]; then
2246 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2247 if [[ ! -z $GPGKEY ]]; then
2248 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2249 else
2250 error "$(gettext "There is no key in your keyring.")"
2252 exit 1
2257 if (( ! SPLITPKG )); then
2258 fullver=$(get_full_version)
2259 if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \
2260 || -f $PKGDEST/${pkgname}-${fullver}-any${PKGEXT} ]] \
2261 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2262 if (( INSTALL )); then
2263 warning "$(gettext "A package has already been built, installing existing package...")"
2264 install_package
2265 exit $?
2266 else
2267 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2268 exit 1
2271 else
2272 allpkgbuilt=1
2273 somepkgbuilt=0
2274 for pkg in ${pkgname[@]}; do
2275 fullver=$(get_full_version $pkg)
2276 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} \
2277 || -f $PKGDEST/${pkg}-${fullver}-any${PKGEXT} ]]; then
2278 somepkgbuilt=1
2279 else
2280 allpkgbuilt=0
2282 done
2283 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2284 if (( allpkgbuilt )); then
2285 if (( INSTALL )); then
2286 warning "$(gettext "The package group has already been built, installing existing packages...")"
2287 install_package
2288 exit $?
2289 else
2290 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2291 exit 1
2294 if (( somepkgbuilt )); then
2295 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2296 exit 1
2299 unset allpkgbuilt somepkgbuilt
2302 # Run the bare minimum in fakeroot
2303 if (( INFAKEROOT )); then
2304 if (( SOURCEONLY )); then
2305 create_srcpackage
2306 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2307 exit 0 # $E_OK
2310 if (( ! SPLITPKG )); then
2311 if (( ! PKGFUNC )); then
2312 if (( ! REPKG )); then
2313 if (( BUILDFUNC )); then
2314 run_build
2315 (( CHECKFUNC )) && run_check
2316 tidy_install
2318 else
2319 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2320 plain "$(gettext "File permissions may not be preserved.")"
2322 else
2323 run_package
2324 tidy_install
2326 create_package
2327 else
2328 run_split_packaging
2331 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2332 exit 0 # $E_OK
2335 fullver=$(get_full_version)
2336 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2338 # if we are creating a source-only package, go no further
2339 if (( SOURCEONLY )); then
2340 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2341 && (( ! FORCE )); then
2342 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2343 exit 1
2346 # Get back to our src directory so we can begin with sources.
2347 mkdir -p "$srcdir"
2348 chmod a-s "$srcdir"
2349 cd_safe "$srcdir"
2350 if ( (( ! SKIPCHECKSUMS )) || \
2351 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \
2352 (( SOURCEONLY == 2 )); then
2353 download_sources
2355 check_source_integrity
2356 cd_safe "$startdir"
2358 # if we are root or if fakeroot is not enabled, then we don't use it
2359 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2360 create_srcpackage
2361 else
2362 enter_fakeroot
2365 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2366 exit 0
2369 if (( NODEPS || ( (NOBUILD || REPKG) && !DEP_BIN ) )); then
2370 # no warning message needed for nobuild, repkg
2371 if (( NODEPS || ( REPKG && PKGFUNC ) )); then
2372 warning "$(gettext "Skipping dependency checks.")"
2374 elif type -p "${PACMAN%% *}" >/dev/null; then
2375 if (( RMDEPS && ! INSTALL )); then
2376 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2378 deperr=0
2380 msg "$(gettext "Checking runtime dependencies...")"
2381 resolve_deps ${depends[@]} || deperr=1
2383 if (( RMDEPS && INSTALL )); then
2384 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2387 msg "$(gettext "Checking buildtime dependencies...")"
2388 resolve_deps ${makedepends[@]} || deperr=1
2390 if (( CHECKFUNC )); then
2391 resolve_deps ${checkdepends[@]} || deperr=1
2394 if (( RMDEPS )); then
2395 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2398 if (( deperr )); then
2399 error "$(gettext "Could not resolve all dependencies.")"
2400 exit 1
2402 else
2403 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2406 # ensure we have a sane umask set
2407 umask 0022
2409 # get back to our src directory so we can begin with sources
2410 mkdir -p "$srcdir"
2411 chmod a-s "$srcdir"
2412 cd_safe "$srcdir"
2414 if (( NOEXTRACT )); then
2415 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2416 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2417 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2419 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2420 error "$(gettext "The source directory is empty, there is nothing to build!")"
2421 plain "$(gettext "Aborting...")"
2422 exit 1
2424 elif (( REPKG )); then
2425 if (( ! PKGFUNC && ! SPLITPKG )) \
2426 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2427 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2428 plain "$(gettext "Aborting...")"
2429 exit 1
2431 else
2432 download_sources
2433 check_source_integrity
2434 extract_sources
2437 if (( NOBUILD )); then
2438 msg "$(gettext "Sources are ready.")"
2439 exit 0 #E_OK
2440 else
2441 # check for existing pkg directory; don't remove if we are repackaging
2442 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2443 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2444 rm -rf "$pkgdir"
2446 mkdir -p "$pkgdir"
2447 chmod a-s "$pkgdir"
2448 cd_safe "$startdir"
2450 # if we are root or if fakeroot is not enabled, then we don't use it
2451 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2452 if (( ! REPKG )); then
2453 devel_update
2454 (( BUILDFUNC )) && run_build
2455 (( CHECKFUNC )) && run_check
2457 if (( ! SPLITPKG )); then
2458 if (( PKGFUNC )); then
2459 run_package
2460 tidy_install
2461 else
2462 if (( ! REPKG )); then
2463 tidy_install
2464 else
2465 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2466 plain "$(gettext "File permissions may not be preserved.")"
2469 create_package
2470 else
2471 run_split_packaging
2473 else
2474 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2475 devel_update
2476 (( BUILDFUNC )) && run_build
2477 (( CHECKFUNC )) && run_check
2478 cd_safe "$startdir"
2481 enter_fakeroot
2485 fullver=$(get_full_version)
2486 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2488 install_package
2490 exit 0 #E_OK
2492 # vim: set ts=2 sw=2 noet: