pkgdelta: implement requirments for delta generation
[pacman-ng.git] / scripts / makepkg.sh.in
blobeeb7ede1cf3a1be2d965630b6aefbb766d70f711
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 local signal=$1; shift
123 if (( ! INFAKEROOT )); then
124 echo
125 error "$@"
127 [[ -n $srclinks ]] && rm -rf "$srclinks"
129 # unset the trap for this signal, and then call the default handler
130 trap -- "$signal"
131 kill "-$signal" "$$"
136 # Clean up function. Called automatically when the script exits.
138 clean_up() {
139 local EXIT_CODE=$?
141 if (( INFAKEROOT )); then
142 # Don't clean up when leaving fakeroot, we're not done yet.
143 return
146 if (( ! EXIT_CODE && CLEANUP )); then
147 local pkg file
149 # If it's a clean exit and -c/--clean has been passed...
150 msg "$(gettext "Cleaning up...")"
151 rm -rf "$pkgdir" "$srcdir"
152 if [[ -n $pkgbase ]]; then
153 local fullver=$(get_full_version)
154 # Can't do this unless the BUILDSCRIPT has been sourced.
155 if (( BUILDFUNC )); then
156 rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"*
158 if (( CHECKFUNC )); then
159 rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
161 if (( PKGFUNC )); then
162 rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
163 elif (( SPLITPKG )); then
164 for pkg in ${pkgname[@]}; do
165 rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"*
166 done
169 # clean up dangling symlinks to packages
170 for pkg in ${pkgname[@]}; do
171 for file in ${pkg}-*-*-${CARCH}{${PKGEXT},${SRCEXT}}; do
172 if [[ -h $file && ! -e $file ]]; then
173 rm -f "$file"
175 done
176 done
180 remove_deps
184 enter_fakeroot() {
185 msg "$(gettext "Entering %s environment...")" "fakeroot"
187 if [[ -n $newpkgver ]]; then
188 fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $?
189 else
190 fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
195 # a source entry can have two forms :
196 # 1) "filename::http://path/to/file"
197 # 2) "http://path/to/file"
199 # Return the absolute filename of a source entry
201 # This function accepts a source entry or the already extracted filename of a
202 # source entry as input
203 get_filepath() {
204 local file="$(get_filename "$1")"
206 if [[ -f "$startdir/$file" ]]; then
207 file="$startdir/$file"
208 elif [[ -f "$SRCDEST/$file" ]]; then
209 file="$SRCDEST/$file"
210 else
211 return 1
214 echo "$file"
217 # Print 'source not found' error message and exit makepkg
218 missing_source_file() {
219 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
220 plain "$(gettext "Aborting...")"
221 exit 1 # $E_MISSING_FILE
224 # extract the filename from a source entry
225 get_filename() {
226 # if a filename is specified, use it
227 local filename="${1%%::*}"
228 # if it is just an URL, we only keep the last component
229 echo "${filename##*/}"
232 # extract the URL from a source entry
233 get_url() {
234 # strip an eventual filename
235 echo "${1#*::}"
239 # usage : get_full_version( [$pkgname] )
240 # return : full version spec, including epoch (if necessary), pkgver, pkgrel
242 get_full_version() {
243 if [[ -z $1 ]]; then
244 if [[ $epoch ]] && (( ! $epoch )); then
245 echo $pkgver-$pkgrel
246 else
247 echo $epoch:$pkgver-$pkgrel
249 else
250 for i in pkgver pkgrel epoch; do
251 local indirect="${i}_override"
252 eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
253 [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
254 done
255 if (( ! $epoch_override )); then
256 echo $pkgver_override-$pkgrel_override
257 else
258 echo $epoch_override:$pkgver_override-$pkgrel_override
264 # Checks to see if options are present in makepkg.conf or PKGBUILD;
265 # PKGBUILD options always take precedence.
267 # usage : check_option( $option )
268 # return : y - enabled
269 # n - disabled
270 # ? - not found
272 check_option() {
273 local ret=$(in_opt_array "$1" ${options[@]})
274 if [[ $ret != '?' ]]; then
275 echo $ret
276 return
279 # fall back to makepkg.conf options
280 ret=$(in_opt_array "$1" ${OPTIONS[@]})
281 if [[ $ret != '?' ]]; then
282 echo $ret
283 return
286 echo '?' # Not Found
291 # Check if option is present in BUILDENV
293 # usage : check_buildenv( $option )
294 # return : y - enabled
295 # n - disabled
296 # ? - not found
298 check_buildenv() {
299 in_opt_array "$1" ${BUILDENV[@]}
304 # usage : in_opt_array( $needle, $haystack )
305 # return : y - enabled
306 # n - disabled
307 # ? - not found
309 in_opt_array() {
310 local needle=$1; shift
312 local opt
313 for opt in "$@"; do
314 if [[ $opt = $needle ]]; then
315 echo 'y' # Enabled
316 return
317 elif [[ $opt = "!$needle" ]]; then
318 echo 'n' # Disabled
319 return
321 done
323 echo '?' # Not Found
328 # usage : in_array( $needle, $haystack )
329 # return : 0 - found
330 # 1 - not found
332 in_array() {
333 local needle=$1; shift
334 local item
335 for item in "$@"; do
336 [[ $item = $needle ]] && return 0 # Found
337 done
338 return 1 # Not Found
341 source_has_signatures(){
342 local file
343 for file in "${source[@]}"; do
344 if [[ $file = *.@(sig?(n)|asc) ]]; then
345 return 0
347 done
348 return 1
351 get_downloadclient() {
352 # $1 = URL with valid protocol prefix
353 local url=$1
354 local proto="${url%%://*}"
356 # loop through DOWNLOAD_AGENTS variable looking for protocol
357 local i
358 for i in "${DLAGENTS[@]}"; do
359 local handler="${i%%::*}"
360 if [[ $proto = $handler ]]; then
361 local agent="${i##*::}"
362 break
364 done
366 # if we didn't find an agent, return an error
367 if [[ -z $agent ]]; then
368 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
369 plain "$(gettext "Aborting...")"
370 exit 1 # $E_CONFIG_ERROR
373 # ensure specified program is installed
374 local program="${agent%% *}"
375 if [[ ! -x $program ]]; then
376 local baseprog="${program##*/}"
377 error "$(gettext "The download program %s is not installed.")" "$baseprog"
378 plain "$(gettext "Aborting...")"
379 exit 1 # $E_MISSING_PROGRAM
382 echo "$agent"
385 download_file() {
386 # download command
387 local dlcmd=$1
388 # URL of the file
389 local url=$2
390 # destination file
391 local file=$3
392 # temporary download file, default to last component of the URL
393 local dlfile="${url##*/}"
395 # replace %o by the temporary dlfile if it exists
396 if [[ $dlcmd = *%o* ]]; then
397 dlcmd=${dlcmd//\%o/\"$file.part\"}
398 dlfile="$file.part"
400 # add the URL, either in place of %u or at the end
401 if [[ $dlcmd = *%u* ]]; then
402 dlcmd=${dlcmd//\%u/\"$url\"}
403 else
404 dlcmd="$dlcmd \"$url\""
407 local ret=0
408 eval "$dlcmd || ret=\$?"
409 if (( ret )); then
410 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
411 return $ret
414 # rename the temporary download file to the final destination
415 if [[ $dlfile != "$file" ]]; then
416 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$file"
420 run_pacman() {
421 local cmd
422 if [[ ! $1 = -@(T|Qq) ]]; then
423 printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@"
424 else
425 printf -v cmd "%q " "$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 '$cmd'"
434 eval "$cmd"
437 check_deps() {
438 (( $# > 0 )) || return 0
440 # Disable error trap in pacman subshell call as this breaks bash-3.2 compatibility
441 # Also, a non-zero return value is not unexpected and we are manually dealing them
442 set +E
443 local ret=0
444 local pmout
445 pmout=$(run_pacman -T "$@") || ret=$?
446 set -E
448 if (( ret == 127 )); then #unresolved deps
449 echo "$pmout"
450 elif (( ret )); then
451 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
452 return "$ret"
456 handle_deps() {
457 local R_DEPS_SATISFIED=0
458 local R_DEPS_MISSING=1
460 (( $# == 0 )) && return $R_DEPS_SATISFIED
462 local deplist="$*"
464 if (( ! DEP_BIN )); then
465 return $R_DEPS_MISSING
468 if (( DEP_BIN )); then
469 # install missing deps from binary packages (using pacman -S)
470 msg "$(gettext "Installing missing dependencies...")"
472 if ! run_pacman -S --asdeps $deplist; then
473 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
474 exit 1 # TODO: error code
478 # we might need the new system environment
479 # avoid triggering the ERR trap and exiting
480 set +e
481 local restoretrap=$(trap -p ERR)
482 trap - ERR
483 source /etc/profile &>/dev/null
484 eval $restoretrap
485 set -e
487 return $R_DEPS_SATISFIED
490 resolve_deps() {
491 local R_DEPS_SATISFIED=0
492 local R_DEPS_MISSING=1
494 # deplist cannot be declared like this: local deplist=$(foo)
495 # Otherwise, the return value will depend on the assignment.
496 local deplist
497 deplist="$(set +E; check_deps $*)" || exit 1
498 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
500 if handle_deps $deplist; then
501 # check deps again to make sure they were resolved
502 deplist="$(set +E; check_deps $*)" || exit 1
503 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
506 msg "$(gettext "Missing Dependencies:")"
507 local dep
508 for dep in $deplist; do
509 msg2 "$dep"
510 done
512 return $R_DEPS_MISSING
515 remove_deps() {
516 (( ! RMDEPS )) && return
518 # check for packages removed during dependency install (e.g. due to conflicts)
519 # removing all installed packages is risky in this case
520 if [[ -n $(grep -xvFf <(printf '%s\n' "${current_packagelist[@]}") \
521 <(printf '%s\n' "${original_packagelist[@]}") || true) ]]; then
522 warning "$(gettext "Failed to remove installed dependencies.")"
523 return 0
526 local deplist
527 deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \
528 <(printf "%s\n" "${current_pkglist[@]}") || true))
529 if [[ -z $deplist ]]; then
530 return
533 msg "Removing installed dependencies..."
534 # exit cleanly on failure to remove deps as package has been built successfully
535 if ! run_pacman -Rn ${deplist[@]}; then
536 warning "$(gettext "Failed to remove installed dependencies.")"
537 return 0
541 download_sources() {
542 msg "$(gettext "Retrieving Sources...")"
544 pushd "$SRCDEST" &>/dev/null
546 local netfile
547 for netfile in "${source[@]}"; do
548 local file=$(get_filepath "$netfile" || true)
549 if [[ -n "$file" ]]; then
550 msg2 "$(gettext "Found %s")" "${file##*/}"
551 rm -f "$srcdir/${file##*/}"
552 ln -s "$file" "$srcdir/"
553 continue
556 file=$(get_filename "$netfile")
557 local url=$(get_url "$netfile")
559 # if we get here, check to make sure it was a URL, else fail
560 if [[ $file = $url ]]; then
561 error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file"
562 exit 1 # $E_MISSING_FILE
565 # find the client we should use for this URL
566 local dlclient
567 dlclient=$(get_downloadclient "$url") || exit $?
569 msg2 "$(gettext "Downloading %s...")" "$file"
570 # fix flyspray bug #3289
571 local ret=0
572 download_file "$dlclient" "$url" "$file" || ret=$?
573 if (( ret )); then
574 error "$(gettext "Failure while downloading %s")" "$file"
575 plain "$(gettext "Aborting...")"
576 exit 1
578 rm -f "$srcdir/$file"
579 ln -s "$SRCDEST/$file" "$srcdir/"
580 done
582 popd &>/dev/null
585 get_integlist() {
586 local integ
587 local integlist=()
589 for integ in md5 sha1 sha256 sha384 sha512; do
590 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
591 if [[ -n "$integrity_sums" ]]; then
592 integlist=(${integlist[@]} $integ)
594 done
596 if (( ${#integlist[@]} > 0 )); then
597 echo ${integlist[@]}
598 else
599 echo ${INTEGRITY_CHECK[@]}
603 generate_checksums() {
604 msg "$(gettext "Generating checksums for source files...")"
605 plain ""
607 if ! type -p openssl >/dev/null; then
608 error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
609 exit 1 # $E_MISSING_PROGRAM
612 local integlist
613 if (( $# == 0 )); then
614 integlist=$(get_integlist)
615 else
616 integlist=$@
619 local integ
620 for integ in ${integlist[@]}; do
621 case "$integ" in
622 md5|sha1|sha256|sha384|sha512) : ;;
624 error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
625 exit 1;; # $E_CONFIG_ERROR
626 esac
628 local ct=0
629 local numsrc=${#source[@]}
630 echo -n "${integ}sums=("
632 local i
633 local indent=''
634 for (( i = 0; i < ${#integ} + 6; i++ )); do
635 indent="$indent "
636 done
638 local netfile
639 for netfile in "${source[@]}"; do
640 local file
641 file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
642 local sum="$(openssl dgst -${integ} "$file")"
643 sum=${sum##* }
644 (( ct )) && echo -n "$indent"
645 echo -n "'$sum'"
646 ct=$(($ct+1))
647 (( $ct < $numsrc )) && echo
648 done
650 echo ")"
651 done
654 check_checksums() {
655 (( SKIPCHECKSUMS )) && return 0
656 (( ! ${#source[@]} )) && return 0
658 local correlation=0
659 local integ required
660 for integ in md5 sha1 sha256 sha384 sha512; do
661 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
662 if (( ${#integrity_sums[@]} == ${#source[@]} )); then
663 msg "$(gettext "Validating source files with %s...")" "${integ}sums"
664 correlation=1
665 local errors=0
666 local idx=0
667 local file
668 for file in "${source[@]}"; do
669 local found=1
670 file="$(get_filename "$file")"
671 echo -n " $file ... " >&2
673 if ! file="$(get_filepath "$file")"; then
674 printf -- "$(gettext "NOT FOUND")\n" >&2
675 errors=1
676 found=0
679 if (( $found )) ; then
680 local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}")
681 local realsum="$(openssl dgst -${integ} "$file")"
682 realsum="${realsum##* }"
683 if [[ $expectedsum = $realsum ]]; then
684 printf -- "$(gettext "Passed")\n" >&2
685 else
686 printf -- "$(gettext "FAILED")\n" >&2
687 errors=1
691 idx=$((idx + 1))
692 done
694 if (( errors )); then
695 error "$(gettext "One or more files did not pass the validity check!")"
696 exit 1 # TODO: error code
698 elif (( ${#integrity_sums[@]} )); then
699 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
700 exit 1 # TODO: error code
702 done
704 if (( ! correlation )); then
705 error "$(gettext "Integrity checks are missing.")"
706 exit 1 # TODO: error code
710 check_pgpsigs() {
711 (( SKIPPGPCHECK )) && return 0
712 ! source_has_signatures && return 0
714 msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
716 local file pubkey
717 local warning=0
718 local errors=0
719 local statusfile=$(mktemp)
721 for file in "${source[@]}"; do
722 file="$(get_filename "$file")"
723 if [[ ! $file = *.@(sig?(n)|asc) ]]; then
724 continue
727 printf " %s ... " "${file%.*}" >&2
729 if ! file="$(get_filepath "$file")"; then
730 printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
731 errors=1
732 continue
735 if ! sourcefile="$(get_filepath "${file%.*}")"; then
736 printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
737 errors=1
738 continue
741 if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
742 printf '%s' "$(gettext "FAILED")" >&2
743 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then
744 printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
745 warnings=1
746 else
747 errors=1
749 printf '\n' >&2
750 else
751 if grep -q "REVKEYSIG" "$statusfile"; then
752 printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2
753 errors=1
754 else
755 printf '%s' "$(gettext "Passed")" >&2
756 if grep -q "EXPSIG" "$statusfile"; then
757 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
758 warnings=1
759 elif grep -q "EXPKEYSIG" "$statusfile"; then
760 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
761 warnings=1
764 printf '\n' >&2
766 done
768 rm -f "$statusfile"
770 if (( errors )); then
771 error "$(gettext "One or more PGP signatures could not be verified!")"
772 exit 1
775 if (( warnings )); then
776 warning "$(gettext "Warnings have occurred while verifying the signatures.")"
777 plain "$(gettext "Please make sure you really trust them.")"
781 check_source_integrity() {
782 if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
783 warning "$(gettext "Skipping all source file integrity checks.")"
784 elif (( SKIPCHECKSUMS )); then
785 warning "$(gettext "Skipping verification of source file checksums.")"
786 check_pgpsigs
787 elif (( SKIPPGPCHECK )); then
788 warning "$(gettext "Skipping verification of source file PGP signatures.")"
789 check_checksums
790 else
791 check_checksums
792 check_pgpsigs
796 extract_sources() {
797 msg "$(gettext "Extracting Sources...")"
798 local netfile
799 for netfile in "${source[@]}"; do
800 local file=$(get_filename "$netfile")
801 if in_array "$file" "${noextract[@]}"; then
802 #skip source files in the noextract=() array
803 # these are marked explicitly to NOT be extracted
804 continue
808 # fix flyspray #6246
809 local file_type=$(file -bizL "$file")
810 local ext=${file##*.}
811 local cmd=''
812 case "$file_type" in
813 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
814 cmd="bsdtar" ;;
815 *application/x-gzip*)
816 case "$ext" in
817 gz|z|Z) cmd="gzip" ;;
818 *) continue;;
819 esac ;;
820 *application/x-bzip*)
821 case "$ext" in
822 bz2|bz) cmd="bzip2" ;;
823 *) continue;;
824 esac ;;
825 *application/x-xz*)
826 case "$ext" in
827 xz) cmd="xz" ;;
828 *) continue;;
829 esac ;;
831 # See if bsdtar can recognize the file
832 if bsdtar -tf "$file" -q '*' &>/dev/null; then
833 cmd="bsdtar"
834 else
835 continue
836 fi ;;
837 esac
839 local ret=0
840 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
841 if [[ $cmd = bsdtar ]]; then
842 $cmd -xf "$file" || ret=$?
843 else
844 rm -f "${file%.*}"
845 $cmd -dcf "$file" > "${file%.*}" || ret=$?
847 if (( ret )); then
848 error "$(gettext "Failed to extract %s")" "$file"
849 plain "$(gettext "Aborting...")"
850 exit 1
852 done
854 if (( EUID == 0 )); then
855 # change perms of all source files to root user & root group
856 chown -R 0:0 "$srcdir"
860 error_function() {
861 if [[ -p $logpipe ]]; then
862 rm "$logpipe"
864 # first exit all subshells, then print the error
865 if (( ! BASH_SUBSHELL )); then
866 error "$(gettext "A failure occurred in %s().")" "$1"
867 plain "$(gettext "Aborting...")"
868 remove_deps
870 exit 2 # $E_BUILD_FAILED
873 run_function() {
874 if [[ -z $1 ]]; then
875 return 1
877 local pkgfunc="$1"
879 # clear user-specified buildflags if requested
880 if [[ $(check_option buildflags) = "n" ]]; then
881 unset CFLAGS CXXFLAGS LDFLAGS
884 # clear user-specified makeflags if requested
885 if [[ $(check_option makeflags) = "n" ]]; then
886 unset MAKEFLAGS
889 msg "$(gettext "Starting %s()...")" "$pkgfunc"
890 cd "$srcdir"
892 # ensure all necessary build variables are exported
893 export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
894 # save our shell options so pkgfunc() can't override what we need
895 local shellopts=$(shopt -p)
897 local ret=0
898 local restoretrap
899 if (( LOGGING )); then
900 local fullver=$(get_full_version)
901 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
902 if [[ -f $BUILDLOG ]]; then
903 local i=1
904 while true; do
905 if [[ -f $BUILDLOG.$i ]]; then
906 i=$(($i +1))
907 else
908 break
910 done
911 mv "$BUILDLOG" "$BUILDLOG.$i"
914 # ensure overridden package variables survive tee with split packages
915 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
916 mkfifo "$logpipe"
917 tee "$BUILDLOG" < "$logpipe" &
918 local teepid=$!
920 restoretrap=$(trap -p ERR)
921 trap 'error_function $pkgfunc' ERR
922 $pkgfunc &>"$logpipe"
923 eval $restoretrap
925 wait $teepid
926 rm "$logpipe"
927 else
928 restoretrap=$(trap -p ERR)
929 trap 'error_function $pkgfunc' ERR
930 $pkgfunc 2>&1
931 eval $restoretrap
933 # reset our shell options
934 eval "$shellopts"
937 run_build() {
938 # use distcc if it is requested (check buildenv and PKGBUILD opts)
939 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
940 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
941 export DISTCC_HOSTS
944 # use ccache if it is requested (check buildenv and PKGBUILD opts)
945 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
946 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
949 run_function "build"
952 run_check() {
953 run_function "check"
956 run_package() {
957 local pkgfunc
958 if [[ -z $1 ]]; then
959 pkgfunc="package"
960 else
961 pkgfunc="package_$1"
964 run_function "$pkgfunc"
967 tidy_install() {
968 cd "$pkgdir"
969 msg "$(gettext "Tidying install...")"
971 if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then
972 msg2 "$(gettext "Removing doc files...")"
973 rm -rf ${DOC_DIRS[@]}
976 if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then
977 msg2 "$(gettext "Purging unwanted files...")"
978 local pt
979 for pt in "${PURGE_TARGETS[@]}"; do
980 if [[ ${pt} = ${pt//\/} ]]; then
981 find . -type f -name "${pt}" -exec rm -f -- '{}' \;
982 else
983 rm -f ${pt}
985 done
988 if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then
989 msg2 "$(gettext "Compressing man and info pages...")"
990 local manpage ext file link hardlinks hl
991 find ${MAN_DIRS[@]} -type f 2>/dev/null |
992 while read manpage ; do
993 ext="${manpage##*.}"
994 file="${manpage##*/}"
995 if [[ $ext != gz && $ext != bz2 ]]; then
996 # update symlinks to this manpage
997 find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null |
998 while read link ; do
999 rm -f "$link" "${link}.gz"
1000 ln -s "${file}.gz" "${link}.gz"
1001 done
1003 # check file still exists (potentially already compressed due to hardlink)
1004 if [[ -f ${manpage} ]]; then
1005 # find hard links and remove them
1006 # the '|| true' part keeps the script from bailing on the EOF returned
1007 # by read at the end of the find output
1008 IFS=$'\n' read -rd '' -a hardlinks < \
1009 <(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" \
1010 2>/dev/null || true) || true
1011 rm -f "${hardlinks[@]}"
1012 # compress the original
1013 gzip -9 "$manpage"
1014 # recreate hard links removed earlier
1015 for hl in "${hardlinks[@]}"; do
1016 ln "${manpage}.gz" "${hl}.gz"
1017 chmod 644 ${hl}.gz
1018 done
1021 done
1024 if [[ $(check_option strip) = y ]]; then
1025 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1026 # make sure library stripping variables are defined to prevent excess stripping
1027 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1028 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1029 local binary
1030 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1031 case "$(file -bi "$binary")" in
1032 *application/x-sharedlib*) # Libraries (.so)
1033 strip $STRIP_SHARED "$binary";;
1034 *application/x-archive*) # Libraries (.a)
1035 strip $STRIP_STATIC "$binary";;
1036 *application/x-executable*) # Binaries
1037 strip $STRIP_BINARIES "$binary";;
1038 esac
1039 done
1042 if [[ $(check_option libtool) = "n" ]]; then
1043 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1044 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1047 if [[ $(check_option emptydirs) = "n" ]]; then
1048 msg2 "$(gettext "Removing empty directories...")"
1049 find . -depth -type d -empty -delete
1052 if [[ $(check_option upx) = "y" ]]; then
1053 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1054 local binary
1055 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1056 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1057 upx $UPXFLAGS "$binary" &>/dev/null ||
1058 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1060 done
1064 find_libdepends() {
1065 local libdepends
1066 find "$pkgdir" -type f -perm -u+x | while read filename
1068 # get architecture of the file; if soarch is empty it's not an ELF binary
1069 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1070 [ -n "$soarch" ] || continue
1071 # process all libraries needed by the binary
1072 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1074 # extract the library name: libfoo.so
1075 soname="${sofile%.so?(+(.+([0-9])))}".so
1076 # extract the major version: 1
1077 soversion="${sofile##*\.so\.}"
1078 if in_array "${soname}" ${depends[@]}; then
1079 if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then
1080 # libfoo.so=1-64
1081 echo "${soname}=${soversion}-${soarch}"
1082 libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}")
1085 done
1086 done
1089 find_libprovides() {
1090 local libprovides
1091 find "$pkgdir" -type f -name \*.so\* | while read filename
1093 # check if we really have a shared object
1094 if LC_ALL=C readelf -h "$filename" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1095 # 64
1096 soarch=$(LC_ALL=C readelf -h "$filename" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1097 # get the string binaries link to: libfoo.so.1.2 -> libfoo.so.1
1098 sofile=$(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1099 [ -z "$sofile" ] && sofile="${filename##*/}"
1101 # extract the library name: libfoo.so
1102 soname="${sofile%%\.so\.*}.so"
1103 # extract the major version: 1
1104 soversion="${sofile##*\.so\.}"
1105 if in_array "${soname}" ${provides[@]}; then
1106 if ! in_array "${soname}=${soversion}-${soarch}" ${libprovides[@]}; then
1107 # libfoo.so=1-64
1108 echo "${soname}=${soversion}-${soarch}"
1109 libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}")
1113 done
1116 write_pkginfo() {
1117 local builddate=$(date -u "+%s")
1118 if [[ -n $PACKAGER ]]; then
1119 local packager="$PACKAGER"
1120 else
1121 local packager="Unknown Packager"
1124 # btrfs's delayed allocation causes the stat buffers from the kernel to "lie"
1125 # to us momentarily and report 0 blocks allocated (which is how du calculates
1126 # size). Sleeping for a second here is about the dirtiest thing possible,
1127 # but avoids reporting entirely bogus install sizes.
1128 sleep 1
1129 local size="$(@DUPATH@ -sk)"
1130 size="$(( ${size%%[^0-9]*} * 1024 ))"
1132 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1133 echo "# Generated by makepkg $myver"
1134 if (( INFAKEROOT )); then
1135 echo "# using $(fakeroot -v)"
1137 echo "# $(LC_ALL=C date -u)"
1138 echo "pkgname = $1"
1139 (( SPLITPKG )) && echo pkgbase = $pkgbase
1140 echo "pkgver = $(get_full_version)"
1141 echo "pkgdesc = $pkgdesc"
1142 echo "url = $url"
1143 echo "builddate = $builddate"
1144 echo "packager = $packager"
1145 echo "size = $size"
1146 echo "arch = $PKGARCH"
1148 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1149 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1150 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1151 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1152 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1153 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1155 local it
1157 libprovides=$(find_libprovides)
1158 libdepends=$(find_libdepends)
1159 provides=("${provides[@]}" ${libprovides})
1160 depends=("${depends[@]}" ${libdepends})
1162 for it in "${depends[@]}"; do
1163 if [[ $it = *.so ]]; then
1164 # check if the entry has been found by find_libdepends
1165 # if not, it's unneeded; tell the user so he can remove it
1166 printf -v re '(^|\s)%s=.*' "$it"
1167 if [[ ! $libdepends =~ $re ]]; then
1168 error "$(gettext "Cannot find library listed in %s: %s")" "'depends'" "$it"
1169 return 1
1171 else
1172 echo "depend = $it"
1174 done
1176 for it in "${provides[@]}"; do
1177 # ignore versionless entires (those come from the PKGBUILD)
1178 if [[ $it = *.so ]]; then
1179 # check if the entry has been found by find_libprovides
1180 # if not, it's unneeded; tell the user so he can remove it
1181 if [[ ! $libprovides =~ (^|\s)${it}=.* ]]; then
1182 error "$(gettext "Cannot find library listed in %s: %s")" "'provides'" "$it"
1183 return 1
1185 else
1186 echo "provides = $it"
1188 done
1190 for it in "${packaging_options[@]}"; do
1191 local ret="$(check_option $it)"
1192 if [[ $ret != "?" ]]; then
1193 if [[ $ret = y ]]; then
1194 echo "makepkgopt = $it"
1195 else
1196 echo "makepkgopt = !$it"
1199 done
1201 # TODO maybe remove this at some point
1202 # warn if license array is not present or empty
1203 if [[ -z $license ]]; then
1204 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1205 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1209 check_package() {
1210 cd "$pkgdir"
1212 # check existence of backup files
1213 local file
1214 for file in "${backup[@]}"; do
1215 if [[ ! -f $file ]]; then
1216 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1218 done
1220 # check for references to the build and package directory
1221 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1222 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1224 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1225 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1230 create_package() {
1231 if [[ ! -d $pkgdir ]]; then
1232 error "$(gettext "Missing %s directory.")" "pkg/"
1233 plain "$(gettext "Aborting...")"
1234 exit 1 # $E_MISSING_PKGDIR
1237 check_package
1239 cd "$pkgdir"
1240 msg "$(gettext "Creating package...")"
1242 local nameofpkg
1243 if [[ -z $1 ]]; then
1244 nameofpkg="$pkgname"
1245 else
1246 nameofpkg="$1"
1249 if [[ $arch = "any" ]]; then
1250 PKGARCH="any"
1251 else
1252 PKGARCH=$CARCH
1255 write_pkginfo $nameofpkg > .PKGINFO
1257 local comp_files=".PKGINFO"
1259 # check for changelog/install files
1260 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1261 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1263 if [[ -n ${!orig} ]]; then
1264 msg2 "$(gettext "Adding %s file...")" "$orig"
1265 cp "$startdir/${!orig}" "$dest"
1266 chmod 644 "$dest"
1267 comp_files+=" $dest"
1269 done
1271 # tar it up
1272 msg2 "$(gettext "Compressing package...")"
1274 local fullver=$(get_full_version)
1275 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}"
1276 local ret=0
1278 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1279 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1281 # when fileglobbing, we want * in an empty directory to expand to
1282 # the null string rather than itself
1283 shopt -s nullglob
1284 # TODO: Maybe this can be set globally for robustness
1285 shopt -s -o pipefail
1286 # bsdtar's gzip compression always saves the time stamp, making one
1287 # archive created using the same command line distinct from another.
1288 # Disable bsdtar compression and use gzip -n for now.
1289 bsdtar -cf - $comp_files * |
1290 case "$PKGEXT" in
1291 *tar.gz) gzip -c -f -n ;;
1292 *tar.bz2) bzip2 -c -f ;;
1293 *tar.xz) xz -c -z - ;;
1294 *tar.Z) compress -c -f ;;
1295 *tar) cat ;;
1296 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1297 "$PKGEXT"; cat ;;
1298 esac > "${pkg_file}" || ret=$?
1300 shopt -u nullglob
1301 shopt -u -o pipefail
1303 if (( ret )); then
1304 error "$(gettext "Failed to create package file.")"
1305 exit 1 # TODO: error code
1308 create_signature "$pkg_file"
1310 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1311 rm -f "${pkg_file/$PKGDEST/$startdir}"
1312 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1313 ret=$?
1314 if [[ -f $pkg_file.sig ]]; then
1315 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1316 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1320 if (( ret )); then
1321 warning "$(gettext "Failed to create symlink to package file.")"
1325 create_signature() {
1326 if [[ $SIGNPKG != 'y' ]]; then
1327 return
1329 local ret=0
1330 local filename="$1"
1331 msg "$(gettext "Signing package...")"
1333 local SIGNWITHKEY=""
1334 if [[ -n $GPGKEY ]]; then
1335 SIGNWITHKEY="-u ${GPGKEY}"
1337 # The signature will be generated directly in ascii-friendly format
1338 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1341 if (( ! ret )); then
1342 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1343 else
1344 warning "$(gettext "Failed to sign package file.")"
1348 create_srcpackage() {
1349 local ret=0
1350 msg "$(gettext "Creating source package...")"
1351 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1352 mkdir "${srclinks}"/${pkgbase}
1354 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1355 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1357 local file
1358 for file in "${source[@]}"; do
1359 if [[ "$file" == $(get_filename "$file") ]] || (( SOURCEONLY == 2 )); then
1360 local absfile
1361 absfile=$(get_filepath "$file") || missing_source_file "$file"
1362 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1363 ln -s "$absfile" "$srclinks/$pkgbase"
1365 done
1367 local i
1368 for i in 'changelog' 'install'; do
1369 local file
1370 while read -r file; do
1371 # evaluate any bash variables used
1372 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1373 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1374 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1375 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1377 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1378 done
1380 local TAR_OPT
1381 case "$SRCEXT" in
1382 *tar.gz) TAR_OPT="z" ;;
1383 *tar.bz2) TAR_OPT="j" ;;
1384 *tar.xz) TAR_OPT="J" ;;
1385 *tar.Z) TAR_OPT="Z" ;;
1386 *tar) TAR_OPT="" ;;
1387 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1388 "$SRCEXT" ;;
1389 esac
1391 local fullver=$(get_full_version)
1392 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1394 # tar it up
1395 msg2 "$(gettext "Compressing source package...")"
1396 cd "${srclinks}"
1397 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1398 error "$(gettext "Failed to create source package file.")"
1399 exit 1 # TODO: error code
1402 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1403 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1404 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1405 ret=$?
1408 if (( ret )); then
1409 warning "$(gettext "Failed to create symlink to source package file.")"
1412 cd "${startdir}"
1413 rm -rf "${srclinks}"
1416 install_package() {
1417 (( ! INSTALL )) && return
1419 if (( ! SPLITPKG )); then
1420 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1421 else
1422 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1425 local fullver pkg pkglist
1426 for pkg in ${pkgname[@]}; do
1427 fullver=$(get_full_version $pkg)
1428 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} ]]; then
1429 pkglist+=" $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT}"
1430 else
1431 pkglist+=" $PKGDEST/${pkg}-${fullver}-any${PKGEXT}"
1433 done
1435 if ! run_pacman -U $pkglist; then
1436 warning "$(gettext "Failed to install built package(s).")"
1437 return 0
1441 check_sanity() {
1442 # check for no-no's in the build script
1443 local i
1444 local ret=0
1445 for i in 'pkgname' 'pkgrel' 'pkgver'; do
1446 if [[ -z ${!i} ]]; then
1447 error "$(gettext "%s is not allowed to be empty.")" "$i"
1448 ret=1
1450 done
1452 for i in "${pkgname[@]}"; do
1453 if [[ ${i:0:1} = "-" ]]; then
1454 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1455 ret=1
1457 done
1459 if [[ ${pkgbase:0:1} = "-" ]]; then
1460 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1461 ret=1
1464 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1465 while IFS='=' read -r _ i; do
1466 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1467 if [[ $i = *[[:space:]:-]* ]]; then
1468 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
1469 return 1
1471 done || ret=1
1473 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1474 while IFS='=' read -r _ i; do
1475 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1476 if [[ $i = *[[:space:]-]* ]]; then
1477 error "$(gettext "%s is not allowed to contain hyphens or whitespace.")" "pkgrel"
1478 return 1
1480 done || ret=1
1482 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1483 while IFS='=' read -r _ i; do
1484 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1485 if [[ $i != *([[:digit:]]) ]]; then
1486 error "$(gettext "%s must be an integer.")" "epoch"
1487 return 1
1489 done || ret=1
1491 if [[ $arch != 'any' ]]; then
1492 if ! in_array $CARCH ${arch[@]}; then
1493 if (( ! IGNOREARCH )); then
1494 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1495 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1496 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1497 ret=1
1502 if (( ${#pkgname[@]} > 1 )); then
1503 for i in ${pkgname[@]}; do
1504 local arch_list=""
1505 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1506 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1507 if ! in_array $CARCH ${arch_list[@]}; then
1508 if (( ! IGNOREARCH )); then
1509 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1510 ret=1
1514 done
1517 local provides_list=()
1518 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1519 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1520 for i in ${provides_list[@]}; do
1521 if [[ $i == *['<>']* ]]; then
1522 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1523 ret=1
1525 done
1527 local backup_list=()
1528 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1529 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1530 for i in "${backup_list[@]}"; do
1531 if [[ ${i:0:1} = "/" ]]; then
1532 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1533 ret=1
1535 done
1537 local optdepends_list=()
1538 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1539 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1540 for i in "${optdepends_list[@]}"; do
1541 local pkg=${i%%:[[:space:]]*}
1542 # the '-' character _must_ be first or last in the character range
1543 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1544 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1545 ret=1
1547 done
1549 for i in 'changelog' 'install'; do
1550 local file
1551 while read -r file; do
1552 # evaluate any bash variables used
1553 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1554 if [[ $file && ! -f $file ]]; then
1555 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1556 ret=1
1558 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1559 done
1561 local valid_options=1
1562 local known kopt options_list
1563 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1564 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1565 for i in ${options_list[@]}; do
1566 known=0
1567 # check if option matches a known option or its inverse
1568 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1569 if [[ ${i} = ${kopt} || ${i} = "!${kopt}" ]]; then
1570 known=1
1572 done
1573 if (( ! known )); then
1574 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1575 valid_options=0
1577 done
1578 if (( ! valid_options )); then
1579 ret=1
1582 if (( ${#pkgname[@]} > 1 )); then
1583 for i in ${pkgname[@]}; do
1584 if ! declare -f package_${i} >/dev/null; then
1585 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1586 ret=1
1588 done
1591 for i in ${PKGLIST[@]}; do
1592 if ! in_array $i ${pkgname[@]}; then
1593 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1594 ret=1
1596 done
1598 return $ret
1601 check_software() {
1602 # check for needed software
1603 local ret=0
1605 # check for sudo if we will need it during makepkg execution
1606 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1607 if ! type -p sudo >/dev/null; then
1608 warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")"
1612 # fakeroot - building as non-root user
1613 if [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then
1614 if ! type -p fakeroot >/dev/null; then
1615 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
1616 ret=1
1620 # gpg - package signing
1621 if [[ $SIGNPKG == 'y' || (-z "$SIGNPKG" && $(check_buildenv sign) == 'y') ]]; then
1622 if ! type -p gpg >/dev/null; then
1623 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
1624 ret=1
1628 # gpg - source verification
1629 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
1630 if ! type -p gpg >/dev/null; then
1631 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
1632 ret=1
1636 # openssl - checksum operations
1637 if (( ! SKIPCHECKSUMS )); then
1638 if ! type -p openssl >/dev/null; then
1639 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
1640 ret=1
1644 # upx - binary compression
1645 if [[ $(check_option upx) == 'y' ]]; then
1646 if ! type -p upx >/dev/null; then
1647 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
1648 ret=1
1652 # distcc - compilation with distcc
1653 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
1654 if ! type -p distcc >/dev/null; then
1655 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
1656 ret=1
1660 # ccache - compilation with ccache
1661 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
1662 if ! type -p ccache >/dev/null; then
1663 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
1664 ret=1
1668 # strip - strip symbols from binaries/libraries
1669 if [[ $(check_option strip) = "y" ]]; then
1670 if ! type -p strip >/dev/null; then
1671 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
1672 ret=1
1676 # gzip - compressig man and info pages
1677 if [[ $(check_option zipman) = "y" ]]; then
1678 if ! type -p gzip >/dev/null; then
1679 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
1680 ret=1
1684 return $ret
1687 devel_check() {
1688 newpkgver=""
1690 # Do not update pkgver if --holdver is set, when building a source package, repackaging,
1691 # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w)
1692 if (( HOLDVER || SOURCEONLY || REPKG )) ||
1693 [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = /dev/stdin ]]; then
1694 return
1697 if [[ -z $FORCE_VER ]]; then
1698 # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so.
1699 # This will only be used on the first call to makepkg; subsequent
1700 # calls to makepkg via fakeroot will explicitly pass the version
1701 # number to avoid having to determine the version number twice.
1702 # Also do a check to make sure we have the VCS tool available.
1703 oldpkgver=$pkgver
1704 if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then
1705 if ! type -p darcs >/dev/null; then
1706 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "darcs" "darcs"
1707 return 0
1709 msg "$(gettext "Determining latest %s revision...")" 'darcs'
1710 newpkgver=$(date +%Y%m%d)
1711 elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then
1712 if ! type -p cvs >/dev/null; then
1713 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "cvs" "cvs"
1714 return 0
1716 msg "$(gettext "Determining latest %s revision...")" 'cvs'
1717 newpkgver=$(date +%Y%m%d)
1718 elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then
1719 if ! type -p git >/dev/null; then
1720 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "git" "git"
1721 return 0
1723 msg "$(gettext "Determining latest %s revision...")" 'git'
1724 newpkgver=$(date +%Y%m%d)
1725 elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then
1726 if ! type -p svn >/dev/null; then
1727 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "svn" "svn"
1728 return 0
1730 msg "$(gettext "Determining latest %s revision...")" 'svn'
1731 newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p')
1732 elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then
1733 if ! type -p bzr >/dev/null; then
1734 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "bzr" "bzr"
1735 return 0
1737 msg "$(gettext "Determining latest %s revision...")" 'bzr'
1738 newpkgver=$(bzr revno ${_bzrtrunk})
1739 elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then
1740 if ! type -p hg >/dev/null; then
1741 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "hg" "hg"
1742 return 0
1744 msg "$(gettext "Determining latest %s revision...")" 'hg'
1745 if [[ -d ./src/$_hgrepo ]] ; then
1746 cd ./src/$_hgrepo
1747 local ret=0
1748 hg pull || ret=$?
1749 if (( ! ret )); then
1750 hg update
1751 elif (( ret != 1 )); then
1752 return 1
1754 else
1755 [[ ! -d ./src/ ]] && mkdir ./src/
1756 hg clone $_hgroot/$_hgrepo ./src/$_hgrepo
1757 cd ./src/$_hgrepo
1759 newpkgver=$(hg tip --template "{rev}")
1760 cd ../../
1763 if [[ -n $newpkgver ]]; then
1764 msg2 "$(gettext "Version found: %s")" "$newpkgver"
1767 else
1768 # Version number retrieved from fakeroot->makepkg argument
1769 newpkgver=$FORCE_VER
1773 devel_update() {
1774 # This is lame, but if we're wanting to use an updated pkgver for
1775 # retrieving svn/cvs/etc sources, we'll update the PKGBUILD with
1776 # the new pkgver and then re-source it. This is the most robust
1777 # method for dealing with PKGBUILDs that use, e.g.:
1779 # pkgver=23
1780 # ...
1781 # _foo=pkgver
1783 if [[ -n $newpkgver ]]; then
1784 if [[ $newpkgver != "$pkgver" ]]; then
1785 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
1786 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
1787 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
1788 source "$BUILDFILE"
1794 backup_package_variables() {
1795 local var
1796 for var in ${splitpkg_overrides[@]}; do
1797 local indirect="${var}_backup"
1798 eval "${indirect}=(\"\${$var[@]}\")"
1799 done
1802 restore_package_variables() {
1803 local var
1804 for var in ${splitpkg_overrides[@]}; do
1805 local indirect="${var}_backup"
1806 if [[ -n ${!indirect} ]]; then
1807 eval "${var}=(\"\${$indirect[@]}\")"
1808 else
1809 unset ${var}
1811 done
1814 run_split_packaging() {
1815 local pkgname_backup=${pkgname[@]}
1816 for pkgname in ${pkgname_backup[@]}; do
1817 pkgdir="$pkgdir/$pkgname"
1818 mkdir -p "$pkgdir"
1819 chmod a-s "$pkgdir"
1820 backup_package_variables
1821 run_package $pkgname
1822 tidy_install
1823 create_package $pkgname
1824 restore_package_variables
1825 pkgdir="${pkgdir%/*}"
1826 done
1827 pkgname=${pkgname_backup[@]}
1830 # Canonicalize a directory path if it exists
1831 canonicalize_path() {
1832 local path="$1";
1834 if [[ -d $path ]]; then
1836 cd "$path"
1837 pwd -P
1839 else
1840 echo "$path"
1844 m4_include(library/parse_options.sh)
1846 usage() {
1847 printf "makepkg (pacman) %s\n" "$myver"
1848 echo
1849 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
1850 echo
1851 printf -- "$(gettext "Options:")\n"
1852 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
1853 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
1854 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
1855 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
1856 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
1857 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
1858 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
1859 printf -- "$(gettext " -i, --install Install package after successful build")\n"
1860 printf -- "$(gettext " -L, --log Log package build process")\n"
1861 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
1862 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
1863 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
1864 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
1865 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
1866 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
1867 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
1868 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
1869 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
1870 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1871 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
1872 printf -- "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT"
1873 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
1874 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1875 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
1876 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
1877 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
1878 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
1879 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
1880 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
1881 echo
1882 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
1883 echo
1884 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
1885 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
1886 echo
1887 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
1888 echo
1891 version() {
1892 printf "makepkg (pacman) %s\n" "$myver"
1893 printf -- "$(gettext "\
1894 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
1895 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
1896 This is free software; see the source for copying conditions.\n\
1897 There is NO WARRANTY, to the extent permitted by law.\n")"
1900 # PROGRAM START
1902 # determine whether we have gettext; make it a no-op if we do not
1903 if ! type -p gettext >/dev/null; then
1904 gettext() {
1905 echo "$@"
1909 ARGLIST=("$@")
1911 # Parse Command Line Options.
1912 OPT_SHORT="AcdefFghiLmop:rRsSV"
1913 OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps"
1914 OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver,skippgpcheck"
1915 OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps"
1916 OPT_LONG+=",repackage,skipchecksums,skipinteg,skippgpcheck,sign,source,syncdeps"
1917 OPT_LONG+=",version,config:"
1919 # Pacman Options
1920 OPT_LONG+=",noconfirm,noprogressbar"
1921 if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then
1922 echo; usage; exit 1 # E_INVALID_OPTION;
1924 eval set -- "$OPT_TEMP"
1925 unset OPT_SHORT OPT_LONG OPT_TEMP
1927 while true; do
1928 case "$1" in
1929 # Pacman Options
1930 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
1931 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
1933 # Makepkg Options
1934 --allsource) SOURCEONLY=2 ;;
1935 --asroot) ASROOT=1 ;;
1936 -A|--ignorearch) IGNOREARCH=1 ;;
1937 -c|--clean) CLEANUP=1 ;;
1938 --check) RUN_CHECK='y' ;;
1939 --config) shift; MAKEPKG_CONF=$1 ;;
1940 -d|--nodeps) NODEPS=1 ;;
1941 -e|--noextract) NOEXTRACT=1 ;;
1942 -f|--force) FORCE=1 ;;
1943 #hidden opt used by fakeroot call for svn/cvs/etc PKGBUILDs to set pkgver
1944 --forcever) shift; FORCE_VER=$1;;
1945 -F) INFAKEROOT=1 ;;
1946 -g|--geninteg) GENINTEG=1 ;;
1947 --holdver) HOLDVER=1 ;;
1948 -i|--install) INSTALL=1 ;;
1949 --key) shift; GPGKEY=$1 ;;
1950 -L|--log) LOGGING=1 ;;
1951 -m|--nocolor) USE_COLOR='n' ;;
1952 --nocheck) RUN_CHECK='n' ;;
1953 --nosign) SIGNPKG='n' ;;
1954 -o|--nobuild) NOBUILD=1 ;;
1955 -p) shift; BUILDFILE=$1 ;;
1956 --pkg) shift; PKGLIST=($1) ;;
1957 -r|--rmdeps) RMDEPS=1 ;;
1958 -R|--repackage) REPKG=1 ;;
1959 --skipchecksums) SKIPCHECKSUMS=1 ;;
1960 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
1961 --skippgpcheck) SKIPPGPCHECK=1;;
1962 --sign) SIGNPKG='y' ;;
1963 -s|--syncdeps) DEP_BIN=1 ;;
1964 -S|--source) SOURCEONLY=1 ;;
1966 -h|--help) usage; exit 0 ;; # E_OK
1967 -V|--version) version; exit 0 ;; # E_OK
1969 --) OPT_IND=0; shift; break;;
1970 *) usage; exit 1 ;; # E_INVALID_OPTION
1971 esac
1972 shift
1973 done
1975 # setup signal traps
1976 trap 'clean_up' 0
1977 for signal in TERM HUP QUIT; do
1978 trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
1979 done
1980 trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT
1981 trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR
1982 set -E
1984 # preserve environment variables and canonicalize path
1985 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
1986 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
1987 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
1988 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
1989 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
1990 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
1991 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
1993 # default config is makepkg.conf
1994 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
1996 # Source the config file; fail if it is not found
1997 if [[ -r $MAKEPKG_CONF ]]; then
1998 source "$MAKEPKG_CONF"
1999 else
2000 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
2001 plain "$(gettext "Aborting...")"
2002 exit 1 # $E_CONFIG_ERROR
2005 # Source user-specific makepkg.conf overrides, but only if no override config
2006 # file was specified
2007 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
2008 source ~/.makepkg.conf
2011 # set pacman command if not already defined
2012 PACMAN=${PACMAN:-pacman}
2014 # check if messages are to be printed using color
2015 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2016 if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then
2017 # prefer terminal safe colored and bold text when tput is supported
2018 if tput setaf 0 &>/dev/null; then
2019 ALL_OFF="$(tput sgr0)"
2020 BOLD="$(tput bold)"
2021 BLUE="${BOLD}$(tput setaf 4)"
2022 GREEN="${BOLD}$(tput setaf 2)"
2023 RED="${BOLD}$(tput setaf 1)"
2024 YELLOW="${BOLD}$(tput setaf 3)"
2025 else
2026 ALL_OFF="\e[1;0m"
2027 BOLD="\e[1;1m"
2028 BLUE="${BOLD}\e[1;34m"
2029 GREEN="${BOLD}\e[1;32m"
2030 RED="${BOLD}\e[1;31m"
2031 YELLOW="${BOLD}\e[1;33m"
2034 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2036 # override settings with an environment variable for batch processing
2037 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2038 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2039 if [[ ! -d $BUILDDIR ]]; then
2040 mkdir -p "$BUILDDIR" ||
2041 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2042 chmod a-s "$BUILDDIR"
2044 if [[ ! -w $BUILDDIR ]]; then
2045 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2046 plain "$(gettext "Aborting...")"
2047 exit 1
2049 srcdir="$BUILDDIR/src"
2050 pkgdir="$BUILDDIR/pkg"
2052 PKGDEST=${_PKGDEST:-$PKGDEST}
2053 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2054 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2055 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2056 plain "$(gettext "Aborting...")"
2057 exit 1
2060 SRCDEST=${_SRCDEST:-$SRCDEST}
2061 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2062 if [[ ! -w $SRCDEST ]] ; then
2063 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2064 plain "$(gettext "Aborting...")"
2065 exit 1
2068 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2069 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2070 if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then
2071 error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
2072 plain "$(gettext "Aborting...")"
2073 exit 1
2076 PKGEXT=${_PKGEXT:-$PKGEXT}
2077 SRCEXT=${_SRCEXT:-$SRCEXT}
2078 GPGKEY=${_GPGKEY:-$GPGKEY}
2080 if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then
2081 # The '\\0' is here to prevent gettext from thinking --holdver is an option
2082 error "$(gettext "\\0%s and %s cannot both be specified" )" "--holdver" "--forcever"
2083 exit 1
2086 if (( ! INFAKEROOT )); then
2087 if (( EUID == 0 && ! ASROOT )); then
2088 # Warn those who like to live dangerously.
2089 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2090 catastrophic damage to your system. If you wish to run as root, please\n\
2091 use the %s option.")" "makepkg" "--asroot"
2092 exit 1 # $E_USER_ABORT
2093 elif (( EUID > 0 && ASROOT )); then
2094 # Warn those who try to use the --asroot option when they are not root
2095 error "$(gettext "The %s option is meant for the root user only. Please\n\
2096 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2097 exit 1 # $E_USER_ABORT
2098 elif (( EUID > 0 )) && [[ $(check_buildenv fakeroot) != "y" ]]; then
2099 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2100 ownership of the packaged files. Try using the %s environment by\n\
2101 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2102 sleep 1
2104 else
2105 if [[ -z $FAKEROOTKEY ]]; then
2106 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2107 exit 1 # TODO: error code
2111 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2112 unset md5sums replaces depends conflicts backup source install changelog build
2113 unset makedepends optdepends options noextract
2115 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2116 if [[ ! -f $BUILDFILE ]]; then
2117 if [[ -t 0 ]]; then
2118 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2119 exit 1
2120 else
2121 # PKGBUILD passed through a pipe
2122 BUILDFILE=/dev/stdin
2123 shopt -u extglob
2124 source "$BUILDFILE"
2125 shopt -s extglob
2127 else
2128 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2129 if [[ -n $crlftest ]]; then
2130 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2131 exit 1
2134 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2135 BUILDFILE="$startdir/$BUILDFILE"
2137 shopt -u extglob
2138 source "$BUILDFILE"
2139 shopt -s extglob
2142 # set defaults if they weren't specified in buildfile
2143 pkgbase=${pkgbase:-${pkgname[0]}}
2144 epoch=${epoch:-0}
2146 if (( GENINTEG )); then
2147 mkdir -p "$srcdir"
2148 chmod a-s "$srcdir"
2149 cd "$srcdir"
2150 download_sources
2151 generate_checksums
2152 exit 0 # $E_OK
2155 # check the PKGBUILD for some basic requirements
2156 check_sanity || exit 1
2158 # check we have the software required to process the PKGBUILD
2159 check_software || exit 1
2161 # We need to run devel_update regardless of whether we are in the fakeroot
2162 # build process so that if the user runs makepkg --forcever manually, we
2163 # 1) output the correct pkgver, and 2) use the correct filename when
2164 # checking if the package file already exists - fixes FS #9194
2165 devel_check
2166 devel_update
2168 if (( ${#pkgname[@]} > 1 )); then
2169 SPLITPKG=1
2172 # test for available PKGBUILD functions
2173 if declare -f build >/dev/null; then
2174 BUILDFUNC=1
2176 if declare -f check >/dev/null; then
2177 # "Hide" check() function if not going to be run
2178 if [[ $RUN_CHECK = 'y' || (! $(check_buildenv check) = "n" && ! $RUN_CHECK = "n") ]]; then
2179 CHECKFUNC=1
2182 if declare -f package >/dev/null; then
2183 PKGFUNC=1
2184 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2185 SPLITPKG=1
2188 if [[ -n "${PKGLIST[@]}" ]]; then
2189 unset pkgname
2190 pkgname=("${PKGLIST[@]}")
2193 # check if gpg signature is to be created and if signing key is valid
2194 [[ -z $SIGNPKG ]] && SIGNPKG=$(check_buildenv sign)
2195 if [[ $SIGNPKG == 'y' ]]; then
2196 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2197 if [[ ! -z $GPGKEY ]]; then
2198 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2199 else
2200 error "$(gettext "There is no key in your keyring.")"
2202 exit 1
2207 if (( ! SPLITPKG )); then
2208 fullver=$(get_full_version)
2209 if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \
2210 || -f $PKGDEST/${pkgname}-${fullver}-any${PKGEXT} ]] \
2211 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2212 if (( INSTALL )); then
2213 warning "$(gettext "A package has already been built, installing existing package...")"
2214 install_package
2215 exit $?
2216 else
2217 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2218 exit 1
2221 else
2222 allpkgbuilt=1
2223 somepkgbuilt=0
2224 for pkg in ${pkgname[@]}; do
2225 fullver=$(get_full_version $pkg)
2226 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} \
2227 || -f $PKGDEST/${pkg}-${fullver}-any${PKGEXT} ]]; then
2228 somepkgbuilt=1
2229 else
2230 allpkgbuilt=0
2232 done
2233 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2234 if (( allpkgbuilt )); then
2235 if (( INSTALL )); then
2236 warning "$(gettext "The package group has already been built, installing existing packages...")"
2237 install_package
2238 exit $?
2239 else
2240 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2241 exit 1
2244 if (( somepkgbuilt )); then
2245 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2246 exit 1
2249 unset allpkgbuilt somepkgbuilt
2252 # Run the bare minimum in fakeroot
2253 if (( INFAKEROOT )); then
2254 if (( SOURCEONLY )); then
2255 create_srcpackage
2256 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2257 exit 0 # $E_OK
2260 if (( ! SPLITPKG )); then
2261 if (( ! PKGFUNC )); then
2262 if (( ! REPKG )); then
2263 if (( BUILDFUNC )); then
2264 run_build
2265 (( CHECKFUNC )) && run_check
2266 tidy_install
2268 else
2269 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2270 plain "$(gettext "File permissions may not be preserved.")"
2272 else
2273 run_package
2274 tidy_install
2276 create_package
2277 else
2278 run_split_packaging
2281 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2282 exit 0 # $E_OK
2285 fullver=$(get_full_version)
2286 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2288 # if we are creating a source-only package, go no further
2289 if (( SOURCEONLY )); then
2290 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2291 && (( ! FORCE )); then
2292 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2293 exit 1
2296 # Get back to our src directory so we can begin with sources.
2297 mkdir -p "$srcdir"
2298 chmod a-s "$srcdir"
2299 cd "$srcdir"
2300 if ( (( ! SKIPCHECKSUMS )) || \
2301 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \
2302 (( SOURCEONLY == 2 )); then
2303 download_sources
2305 check_source_integrity
2306 cd "$startdir"
2308 # if we are root or if fakeroot is not enabled, then we don't use it
2309 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2310 create_srcpackage
2311 else
2312 enter_fakeroot
2315 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2316 exit 0
2319 if (( NODEPS || ( (NOBUILD || REPKG) && !DEP_BIN ) )); then
2320 # no warning message needed for nobuild, repkg
2321 if (( NODEPS || ( REPKG && PKGFUNC ) )); then
2322 warning "$(gettext "Skipping dependency checks.")"
2324 elif type -p "${PACMAN%% *}" >/dev/null; then
2325 if (( RMDEPS && ! INSTALL )); then
2326 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2328 deperr=0
2330 msg "$(gettext "Checking runtime dependencies...")"
2331 resolve_deps ${depends[@]} || deperr=1
2333 if (( RMDEPS && INSTALL )); then
2334 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2337 msg "$(gettext "Checking buildtime dependencies...")"
2338 resolve_deps ${makedepends[@]} || deperr=1
2340 if (( CHECKFUNC )); then
2341 resolve_deps ${checkdepends[@]} || deperr=1
2344 if (( RMDEPS )); then
2345 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2348 if (( deperr )); then
2349 error "$(gettext "Could not resolve all dependencies.")"
2350 exit 1
2352 else
2353 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2356 # ensure we have a sane umask set
2357 umask 0022
2359 # get back to our src directory so we can begin with sources
2360 mkdir -p "$srcdir"
2361 chmod a-s "$srcdir"
2362 cd "$srcdir"
2364 if (( NOEXTRACT )); then
2365 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2366 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2367 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2369 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2370 error "$(gettext "The source directory is empty, there is nothing to build!")"
2371 plain "$(gettext "Aborting...")"
2372 exit 1
2374 elif (( REPKG )); then
2375 if (( ! PKGFUNC && ! SPLITPKG )) \
2376 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2377 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2378 plain "$(gettext "Aborting...")"
2379 exit 1
2381 else
2382 download_sources
2383 check_source_integrity
2384 extract_sources
2387 if (( NOBUILD )); then
2388 msg "$(gettext "Sources are ready.")"
2389 exit 0 #E_OK
2390 else
2391 # check for existing pkg directory; don't remove if we are repackaging
2392 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2393 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2394 rm -rf "$pkgdir"
2396 mkdir -p "$pkgdir"
2397 chmod a-s "$pkgdir"
2398 cd "$startdir"
2400 # if we are root or if fakeroot is not enabled, then we don't use it
2401 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2402 if (( ! REPKG )); then
2403 devel_update
2404 (( BUILDFUNC )) && run_build
2405 (( CHECKFUNC )) && run_check
2407 if (( ! SPLITPKG )); then
2408 if (( PKGFUNC )); then
2409 run_package
2410 tidy_install
2411 else
2412 if (( ! REPKG )); then
2413 tidy_install
2414 else
2415 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2416 plain "$(gettext "File permissions may not be preserved.")"
2419 create_package
2420 else
2421 run_split_packaging
2423 else
2424 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2425 devel_update
2426 (( BUILDFUNC )) && run_build
2427 (( CHECKFUNC )) && run_check
2428 cd "$startdir"
2431 enter_fakeroot
2435 fullver=$(get_full_version)
2436 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2438 install_package
2440 exit 0 #E_OK
2442 # vim: set ts=2 sw=2 noet: