ALPM API adjustments for sanity and consistency
[pacman-ng.git] / scripts / makepkg.sh.in
blob827425541a6263c062d0759a6afefc3a39e32a5c
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'
40 declare -r myver='@PACKAGE_VERSION@'
41 declare -r confdir='@sysconfdir@'
42 declare -r BUILDSCRIPT='@BUILDSCRIPT@'
43 declare -r startdir="$PWD"
45 packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge' 'upx')
46 other_options=('ccache' 'distcc' 'buildflags' 'makeflags')
47 splitpkg_overrides=('pkgver' 'pkgrel' 'epoch' 'pkgdesc' 'arch' 'license' \
48 'groups' 'depends' 'optdepends' 'provides' 'conflicts' \
49 'replaces' 'backup' 'options' 'install' 'changelog')
50 readonly -a packaging_options other_options splitpkg_overrides
52 # Options
53 ASROOT=0
54 CLEANUP=0
55 DEP_BIN=0
56 FORCE=0
57 INFAKEROOT=0
58 GENINTEG=0
59 SKIPCHECKSUMS=0
60 SKIPPGPCHECK=0
61 INSTALL=0
62 NOBUILD=0
63 NODEPS=0
64 NOEXTRACT=0
65 RMDEPS=0
66 REPKG=0
67 LOGGING=0
68 SOURCEONLY=0
69 IGNOREARCH=0
70 HOLDVER=0
71 BUILDFUNC=0
72 CHECKFUNC=0
73 PKGFUNC=0
74 SPLITPKG=0
75 PKGLIST=()
76 SIGNPKG=''
78 # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call
79 # when dealing with svn/cvs/etc PKGBUILDs.
80 FORCE_VER=""
82 PACMAN_OPTS=
84 shopt -s extglob
86 ### SUBROUTINES ###
88 plain() {
89 local mesg=$1; shift
90 printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
93 msg() {
94 local mesg=$1; shift
95 printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
98 msg2() {
99 local mesg=$1; shift
100 printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
103 warning() {
104 local mesg=$1; shift
105 printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
108 error() {
109 local mesg=$1; shift
110 printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
115 # Special exit call for traps, Don't print any error messages when inside,
116 # the fakeroot call, the error message will be printed by the main call.
118 trap_exit() {
119 if (( ! INFAKEROOT )); then
120 echo
121 error "$@"
123 [[ -n $srclinks ]] && rm -rf "$srclinks"
124 exit 1
129 # Clean up function. Called automatically when the script exits.
131 clean_up() {
132 local EXIT_CODE=$?
134 if (( INFAKEROOT )); then
135 # Don't clean up when leaving fakeroot, we're not done yet.
136 return
139 if (( ! EXIT_CODE && CLEANUP )); then
140 local pkg file
142 # If it's a clean exit and -c/--clean has been passed...
143 msg "$(gettext "Cleaning up...")"
144 rm -rf "$pkgdir" "$srcdir"
145 if [[ -n $pkgbase ]]; then
146 local fullver=$(get_full_version)
147 # Can't do this unless the BUILDSCRIPT has been sourced.
148 if (( BUILDFUNC )); then
149 rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"*
151 if (( CHECKFUNC )); then
152 rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
154 if (( PKGFUNC )); then
155 rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
156 elif (( SPLITPKG )); then
157 for pkg in ${pkgname[@]}; do
158 rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"*
159 done
162 # clean up dangling symlinks to packages
163 for pkg in ${pkgname[@]}; do
164 for file in ${pkg}-*-*-${CARCH}{${PKGEXT},${SRCEXT}}; do
165 if [[ -h $file && ! -e $file ]]; then
166 rm -f $file
168 done
169 done
173 remove_deps
177 enter_fakeroot() {
178 msg "$(gettext "Entering %s environment...")" "fakeroot"
180 if [[ -n $newpkgver ]]; then
181 fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $?
182 else
183 fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
188 # a source entry can have two forms :
189 # 1) "filename::http://path/to/file"
190 # 2) "http://path/to/file"
192 # Return the absolute filename of a source entry
194 # This function accepts a source entry or the already extracted filename of a
195 # source entry as input
196 get_filepath() {
197 local file="$(get_filename "$1")"
199 if [[ -f "$startdir/$file" ]]; then
200 file="$startdir/$file"
201 elif [[ -f "$SRCDEST/$file" ]]; then
202 file="$SRCDEST/$file"
203 else
204 return 1
207 echo "$file"
210 # Print 'source not found' error message and exit makepkg
211 missing_source_file() {
212 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
213 plain "$(gettext "Aborting...")"
214 exit 1 # $E_MISSING_FILE
217 # extract the filename from a source entry
218 get_filename() {
219 # if a filename is specified, use it
220 local filename="${1%%::*}"
221 # if it is just an URL, we only keep the last component
222 echo "${filename##*/}"
225 # extract the URL from a source entry
226 get_url() {
227 # strip an eventual filename
228 echo "${1#*::}"
232 # usage : get_full_version( [$pkgname] )
233 # return : full version spec, including epoch (if necessary), pkgver, pkgrel
235 get_full_version() {
236 if [[ -z $1 ]]; then
237 if [[ $epoch ]] && (( ! $epoch )); then
238 echo $pkgver-$pkgrel
239 else
240 echo $epoch:$pkgver-$pkgrel
242 else
243 for i in pkgver pkgrel epoch; do
244 local indirect="${i}_override"
245 eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
246 [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
247 done
248 if (( ! $epoch_override )); then
249 echo $pkgver_override-$pkgrel_override
250 else
251 echo $epoch_override:$pkgver_override-$pkgrel_override
257 # Checks to see if options are present in makepkg.conf or PKGBUILD;
258 # PKGBUILD options always take precedence.
260 # usage : check_option( $option )
261 # return : y - enabled
262 # n - disabled
263 # ? - not found
265 check_option() {
266 local ret=$(in_opt_array "$1" ${options[@]})
267 if [[ $ret != '?' ]]; then
268 echo $ret
269 return
272 # fall back to makepkg.conf options
273 ret=$(in_opt_array "$1" ${OPTIONS[@]})
274 if [[ $ret != '?' ]]; then
275 echo $ret
276 return
279 echo '?' # Not Found
284 # Check if option is present in BUILDENV
286 # usage : check_buildenv( $option )
287 # return : y - enabled
288 # n - disabled
289 # ? - not found
291 check_buildenv() {
292 in_opt_array "$1" ${BUILDENV[@]}
297 # usage : in_opt_array( $needle, $haystack )
298 # return : y - enabled
299 # n - disabled
300 # ? - not found
302 in_opt_array() {
303 local needle=$1; shift
305 local opt
306 for opt in "$@"; do
307 if [[ $opt = $needle ]]; then
308 echo 'y' # Enabled
309 return
310 elif [[ $opt = "!$needle" ]]; then
311 echo 'n' # Disabled
312 return
314 done
316 echo '?' # Not Found
321 # usage : in_array( $needle, $haystack )
322 # return : 0 - found
323 # 1 - not found
325 in_array() {
326 local needle=$1; shift
327 local item
328 for item in "$@"; do
329 [[ $item = $needle ]] && return 0 # Found
330 done
331 return 1 # Not Found
334 source_has_signatures() {
335 local file
336 for file in "${source[@]}"; do
337 if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
338 return 0
340 done
341 return 1
344 get_downloadclient() {
345 # $1 = URL with valid protocol prefix
346 local url=$1
347 local proto="${url%%://*}"
349 # loop through DOWNLOAD_AGENTS variable looking for protocol
350 local i
351 for i in "${DLAGENTS[@]}"; do
352 local handler="${i%%::*}"
353 if [[ $proto = $handler ]]; then
354 local agent="${i##*::}"
355 break
357 done
359 # if we didn't find an agent, return an error
360 if [[ -z $agent ]]; then
361 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
362 plain "$(gettext "Aborting...")"
363 exit 1 # $E_CONFIG_ERROR
366 # ensure specified program is installed
367 local program="${agent%% *}"
368 if [[ ! -x $program ]]; then
369 local baseprog="${program##*/}"
370 error "$(gettext "The download program %s is not installed.")" "$baseprog"
371 plain "$(gettext "Aborting...")"
372 exit 1 # $E_MISSING_PROGRAM
375 echo "$agent"
378 download_file() {
379 # download command
380 local dlcmd=$1
381 # URL of the file
382 local url=$2
383 # destination file
384 local file=$3
385 # temporary download file, default to last component of the URL
386 local dlfile="${url##*/}"
388 # replace %o by the temporary dlfile if it exists
389 if [[ $dlcmd = *%o* ]]; then
390 dlcmd=${dlcmd//\%o/\"$file.part\"}
391 dlfile="$file.part"
393 # add the URL, either in place of %u or at the end
394 if [[ $dlcmd = *%u* ]]; then
395 dlcmd=${dlcmd//\%u/\"$url\"}
396 else
397 dlcmd="$dlcmd \"$url\""
400 local ret=0
401 eval "$dlcmd || ret=\$?"
402 if (( ret )); then
403 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
404 return $ret
407 # rename the temporary download file to the final destination
408 if [[ $dlfile != "$file" ]]; then
409 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$file"
413 run_pacman() {
414 local cmd
415 if [[ ! $1 = -@(T|Qq) ]]; then
416 printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@"
417 else
418 printf -v cmd "%q " "$PACMAN" "$@"
420 if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then
421 if type -p sudo >/dev/null; then
422 cmd="sudo $cmd"
423 else
424 cmd="su root -c '$cmd'"
427 eval "$cmd"
430 check_deps() {
431 (( $# > 0 )) || return 0
433 # Disable error trap in pacman subshell call as this breaks bash-3.2 compatibility
434 # Also, a non-zero return value is not unexpected and we are manually dealing them
435 set +E
436 local ret=0
437 local pmout
438 pmout=$(run_pacman -T "$@") || ret=$?
439 set -E
441 if (( ret == 127 )); then #unresolved deps
442 echo "$pmout"
443 elif (( ret )); then
444 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
445 return "$ret"
449 handle_deps() {
450 local R_DEPS_SATISFIED=0
451 local R_DEPS_MISSING=1
453 (( $# == 0 )) && return $R_DEPS_SATISFIED
455 local deplist="$*"
457 if (( ! DEP_BIN )); then
458 return $R_DEPS_MISSING
461 if (( DEP_BIN )); then
462 # install missing deps from binary packages (using pacman -S)
463 msg "$(gettext "Installing missing dependencies...")"
465 if ! run_pacman -S --asdeps $deplist; then
466 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
467 exit 1 # TODO: error code
471 # we might need the new system environment
472 # avoid triggering the ERR trap and exiting
473 set +e
474 local restoretrap=$(trap -p ERR)
475 trap - ERR
476 source /etc/profile &>/dev/null
477 eval $restoretrap
478 set -e
480 return $R_DEPS_SATISFIED
483 resolve_deps() {
484 local R_DEPS_SATISFIED=0
485 local R_DEPS_MISSING=1
487 # deplist cannot be declared like this: local deplist=$(foo)
488 # Otherwise, the return value will depend on the assignment.
489 local deplist
490 deplist="$(set +E; check_deps $*)" || exit 1
491 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
493 if handle_deps $deplist; then
494 # check deps again to make sure they were resolved
495 deplist="$(set +E; check_deps $*)" || exit 1
496 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
499 msg "$(gettext "Missing Dependencies:")"
500 local dep
501 for dep in $deplist; do
502 msg2 "$dep"
503 done
505 return $R_DEPS_MISSING
508 remove_deps() {
509 (( ! RMDEPS )) && return
511 # check for packages removed during dependency install (e.g. due to conflicts)
512 # removing all installed packages is risky in this case
513 if [[ -n $(grep -xvFf <(printf '%s\n' "${current_packagelist[@]}") \
514 <(printf '%s\n' "${original_packagelist[@]}") || true) ]]; then
515 warning "$(gettext "Failed to remove installed dependencies.")"
516 return 0
519 local deplist
520 deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \
521 <(printf "%s\n" "${current_pkglist[@]}") || true))
522 if [[ -n deplist ]]; then
523 return
526 msg "Removing installed dependencies..."
527 # exit cleanly on failure to remove deps as package has been built successfully
528 if ! run_pacman -Rn ${deplist[@]}; then
529 warning "$(gettext "Failed to remove installed dependencies.")"
530 return 0
534 download_sources() {
535 msg "$(gettext "Retrieving Sources...")"
537 pushd "$SRCDEST" &>/dev/null
539 local netfile
540 for netfile in "${source[@]}"; do
541 local file=$(get_filepath "$netfile" || true)
542 if [[ -n "$file" ]]; then
543 msg2 "$(gettext "Found %s")" "${file##*/}"
544 rm -f "$srcdir/${file##*/}"
545 ln -s "$file" "$srcdir/"
546 continue
549 file=$(get_filename "$netfile")
550 local url=$(get_url "$netfile")
552 # if we get here, check to make sure it was a URL, else fail
553 if [[ $file = $url ]]; then
554 error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file"
555 exit 1 # $E_MISSING_FILE
558 # find the client we should use for this URL
559 local dlclient
560 dlclient=$(get_downloadclient "$url") || exit $?
562 msg2 "$(gettext "Downloading %s...")" "$file"
563 # fix flyspray bug #3289
564 local ret=0
565 download_file "$dlclient" "$url" "$file" || ret=$?
566 if (( ret )); then
567 error "$(gettext "Failure while downloading %s")" "$file"
568 plain "$(gettext "Aborting...")"
569 exit 1
571 rm -f "$srcdir/$file"
572 ln -s "$SRCDEST/$file" "$srcdir/"
573 done
575 popd &>/dev/null
578 get_integlist() {
579 local integ
580 local integlist=()
582 for integ in md5 sha1 sha256 sha384 sha512; do
583 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
584 if [[ -n "$integrity_sums" ]]; then
585 integlist=(${integlist[@]} $integ)
587 done
589 if (( ${#integlist[@]} > 0 )); then
590 echo ${integlist[@]}
591 else
592 echo ${INTEGRITY_CHECK[@]}
596 generate_checksums() {
597 msg "$(gettext "Generating checksums for source files...")"
598 plain ""
600 if ! type -p openssl >/dev/null; then
601 error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
602 exit 1 # $E_MISSING_PROGRAM
605 local integlist
606 if (( $# == 0 )); then
607 integlist=$(get_integlist)
608 else
609 integlist=$@
612 local integ
613 for integ in ${integlist[@]}; do
614 case "$integ" in
615 md5|sha1|sha256|sha384|sha512) : ;;
617 error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
618 exit 1;; # $E_CONFIG_ERROR
619 esac
621 local ct=0
622 local numsrc=${#source[@]}
623 echo -n "${integ}sums=("
625 local i
626 local indent=''
627 for (( i = 0; i < ${#integ} + 6; i++ )); do
628 indent="$indent "
629 done
631 local netfile
632 for netfile in "${source[@]}"; do
633 local file
634 file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
635 local sum="$(openssl dgst -${integ} "$file")"
636 sum=${sum##* }
637 (( ct )) && echo -n "$indent"
638 echo -n "'$sum'"
639 ct=$(($ct+1))
640 (( $ct < $numsrc )) && echo
641 done
643 echo ")"
644 done
647 check_checksums() {
648 (( SKIPCHECKSUMS )) && return 0
649 (( ! ${#source[@]} )) && return 0
651 local correlation=0
652 local integ required
653 for integ in md5 sha1 sha256 sha384 sha512; do
654 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
655 if (( ${#integrity_sums[@]} == ${#source[@]} )); then
656 msg "$(gettext "Validating source files with %s...")" "${integ}sums"
657 correlation=1
658 local errors=0
659 local idx=0
660 local file
661 for file in "${source[@]}"; do
662 local found=1
663 file="$(get_filename "$file")"
664 echo -n " $file ... " >&2
666 if ! file="$(get_filepath "$file")"; then
667 printf -- "$(gettext "NOT FOUND")\n" >&2
668 errors=1
669 found=0
672 if (( $found )) ; then
673 if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then
674 echo "$(gettext "Skipped")" >&2
675 else
676 local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}")
677 local realsum="$(openssl dgst -${integ} "$file")"
678 realsum="${realsum##* }"
679 if [[ $expectedsum = $realsum ]]; then
680 printf -- "$(gettext "Passed")\n" >&2
681 else
682 printf -- "$(gettext "FAILED")\n" >&2
683 errors=1
688 idx=$((idx + 1))
689 done
691 if (( errors )); then
692 error "$(gettext "One or more files did not pass the validity check!")"
693 exit 1 # TODO: error code
695 elif (( ${#integrity_sums[@]} )); then
696 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
697 exit 1 # TODO: error code
699 done
701 if (( ! correlation )); then
702 error "$(gettext "Integrity checks are missing.")"
703 exit 1 # TODO: error code
707 check_pgpsigs() {
708 (( SKIPPGPCHECK )) && return 0
709 ! source_has_signatures && return 0
711 msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
713 local file pubkey
714 local warning=0
715 local errors=0
716 local statusfile=$(mktemp)
718 for file in "${source[@]}"; do
719 file="$(get_filename "$file")"
720 if [[ ! $file = *.@(sig?(n)|asc) ]]; then
721 continue
724 printf " %s ... " "${file%.*}" >&2
726 if ! file="$(get_filepath "$file")"; then
727 printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
728 errors=1
729 continue
732 if ! sourcefile="$(get_filepath "${file%.*}")"; then
733 printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
734 errors=1
735 continue
738 if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
739 printf '%s' "$(gettext "FAILED")" >&2
740 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then
741 printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
742 warnings=1
743 else
744 errors=1
746 printf '\n' >&2
747 else
748 if grep -q "REVKEYSIG" "$statusfile"; then
749 printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2
750 errors=1
751 else
752 printf '%s' "$(gettext "Passed")" >&2
753 if grep -q "EXPSIG" "$statusfile"; then
754 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
755 warnings=1
756 elif grep -q "EXPKEYSIG" "$statusfile"; then
757 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
758 warnings=1
761 printf '\n' >&2
763 done
765 rm -f "$statusfile"
767 if (( errors )); then
768 error "$(gettext "One or more PGP signatures could not be verified!")"
769 exit 1
772 if (( warnings )); then
773 warning "$(gettext "Warnings have occurred while verifying the signatures.")"
774 plain "$(gettext "Please make sure you really trust them.")"
778 check_source_integrity() {
779 if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
780 warning "$(gettext "Skipping all source file integrity checks.")"
781 elif (( SKIPCHECKSUMS )); then
782 warning "$(gettext "Skipping verification of source file checksums.")"
783 check_pgpsigs
784 elif (( SKIPPGPCHECK )); then
785 warning "$(gettext "Skipping verification of source file PGP signatures.")"
786 check_checksums
787 else
788 check_checksums
789 check_pgpsigs
793 extract_sources() {
794 msg "$(gettext "Extracting Sources...")"
795 local netfile
796 for netfile in "${source[@]}"; do
797 local file=$(get_filename "$netfile")
798 if in_array "$file" "${noextract[@]}"; then
799 #skip source files in the noextract=() array
800 # these are marked explicitly to NOT be extracted
801 continue
805 # fix flyspray #6246
806 local file_type=$(file -bizL "$file")
807 local ext=${file##*.}
808 local cmd=''
809 case "$file_type" in
810 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
811 cmd="bsdtar" ;;
812 *application/x-gzip*)
813 case "$ext" in
814 gz|z|Z) cmd="gzip" ;;
815 *) continue;;
816 esac ;;
817 *application/x-bzip*)
818 case "$ext" in
819 bz2|bz) cmd="bzip2" ;;
820 *) continue;;
821 esac ;;
822 *application/x-xz*)
823 case "$ext" in
824 xz) cmd="xz" ;;
825 *) continue;;
826 esac ;;
828 # See if bsdtar can recognize the file
829 if bsdtar -tf "$file" -q '*' &>/dev/null; then
830 cmd="bsdtar"
831 else
832 continue
833 fi ;;
834 esac
836 local ret=0
837 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
838 if [[ $cmd = bsdtar ]]; then
839 $cmd -xf "$file" || ret=$?
840 else
841 rm -f "${file%.*}"
842 $cmd -dcf "$file" > "${file%.*}" || ret=$?
844 if (( ret )); then
845 error "$(gettext "Failed to extract %s")" "$file"
846 plain "$(gettext "Aborting...")"
847 exit 1
849 done
851 if (( EUID == 0 )); then
852 # change perms of all source files to root user & root group
853 chown -R 0:0 "$srcdir"
857 error_function() {
858 if [[ -p $logpipe ]]; then
859 rm "$logpipe"
861 # first exit all subshells, then print the error
862 if (( ! BASH_SUBSHELL )); then
863 error "$(gettext "A failure occurred in %s().")" "$1"
864 plain "$(gettext "Aborting...")"
865 remove_deps
867 exit 2 # $E_BUILD_FAILED
870 run_function() {
871 if [[ -z $1 ]]; then
872 return 1
874 local pkgfunc="$1"
876 # clear user-specified buildflags if requested
877 if [[ $(check_option buildflags) = "n" ]]; then
878 unset CFLAGS CXXFLAGS LDFLAGS
881 # clear user-specified makeflags if requested
882 if [[ $(check_option makeflags) = "n" ]]; then
883 unset MAKEFLAGS
886 msg "$(gettext "Starting %s()...")" "$pkgfunc"
887 cd "$srcdir"
889 # ensure all necessary build variables are exported
890 export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
891 # save our shell options so pkgfunc() can't override what we need
892 local shellopts=$(shopt -p)
894 local ret=0
895 local restoretrap
896 if (( LOGGING )); then
897 local fullver=$(get_full_version)
898 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
899 if [[ -f $BUILDLOG ]]; then
900 local i=1
901 while true; do
902 if [[ -f $BUILDLOG.$i ]]; then
903 i=$(($i +1))
904 else
905 break
907 done
908 mv "$BUILDLOG" "$BUILDLOG.$i"
911 # ensure overridden package variables survive tee with split packages
912 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
913 mkfifo "$logpipe"
914 tee "$BUILDLOG" < "$logpipe" &
915 local teepid=$!
917 restoretrap=$(trap -p ERR)
918 trap 'error_function $pkgfunc' ERR
919 $pkgfunc &>"$logpipe"
920 eval $restoretrap
922 wait $teepid
923 rm "$logpipe"
924 else
925 restoretrap=$(trap -p ERR)
926 trap 'error_function $pkgfunc' ERR
927 $pkgfunc 2>&1
928 eval $restoretrap
930 # reset our shell options
931 eval "$shellopts"
934 run_build() {
935 # use distcc if it is requested (check buildenv and PKGBUILD opts)
936 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
937 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
938 export DISTCC_HOSTS
941 # use ccache if it is requested (check buildenv and PKGBUILD opts)
942 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
943 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
946 run_function "build"
949 run_check() {
950 run_function "check"
953 run_package() {
954 local pkgfunc
955 if [[ -z $1 ]]; then
956 pkgfunc="package"
957 else
958 pkgfunc="package_$1"
961 run_function "$pkgfunc"
964 tidy_install() {
965 cd "$pkgdir"
966 msg "$(gettext "Tidying install...")"
968 if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then
969 msg2 "$(gettext "Removing doc files...")"
970 rm -rf ${DOC_DIRS[@]}
973 if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then
974 msg2 "$(gettext "Purging unwanted files...")"
975 local pt
976 for pt in "${PURGE_TARGETS[@]}"; do
977 if [[ ${pt} = ${pt//\/} ]]; then
978 find . -type f -name "${pt}" -exec rm -f -- '{}' \;
979 else
980 rm -f ${pt}
982 done
985 if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then
986 msg2 "$(gettext "Compressing man and info pages...")"
987 local manpage ext file link hardlinks hl
988 find ${MAN_DIRS[@]} -type f 2>/dev/null |
989 while read manpage ; do
990 ext="${manpage##*.}"
991 file="${manpage##*/}"
992 if [[ $ext != gz && $ext != bz2 ]]; then
993 # update symlinks to this manpage
994 find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null |
995 while read link ; do
996 rm -f "$link" "${link}.gz"
997 ln -s "${file}.gz" "${link}.gz"
998 done
1000 # check file still exists (potentially already compressed due to hardlink)
1001 if [[ -f ${manpage} ]]; then
1002 # find hard links and remove them
1003 # the '|| true' part keeps the script from bailing on the EOF returned
1004 # by read at the end of the find output
1005 IFS=$'\n' read -rd '' -a hardlinks < \
1006 <(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" \
1007 2>/dev/null || true) || true
1008 rm -f "${hardlinks[@]}"
1009 # compress the original
1010 gzip -9 "$manpage"
1011 # recreate hard links removed earlier
1012 for hl in "${hardlinks[@]}"; do
1013 ln "${manpage}.gz" "${hl}.gz"
1014 chmod 644 ${hl}.gz
1015 done
1018 done
1021 if [[ $(check_option strip) = y ]]; then
1022 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1023 # make sure library stripping variables are defined to prevent excess stripping
1024 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1025 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1026 local binary
1027 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1028 case "$(file -bi "$binary")" in
1029 *application/x-sharedlib*) # Libraries (.so)
1030 strip $STRIP_SHARED "$binary";;
1031 *application/x-archive*) # Libraries (.a)
1032 strip $STRIP_STATIC "$binary";;
1033 *application/x-executable*) # Binaries
1034 strip $STRIP_BINARIES "$binary";;
1035 esac
1036 done
1039 if [[ $(check_option libtool) = "n" ]]; then
1040 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1041 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1044 if [[ $(check_option emptydirs) = "n" ]]; then
1045 msg2 "$(gettext "Removing empty directories...")"
1046 find . -depth -type d -empty -delete
1049 if [[ $(check_option upx) = "y" ]]; then
1050 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1051 local binary
1052 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1053 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1054 upx $UPXFLAGS "$binary" &>/dev/null ||
1055 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1057 done
1061 find_libdepends() {
1062 local libdepends
1063 find "$pkgdir" -type f -perm -u+x | while read filename
1065 # get architecture of the file; if soarch is empty it's not an ELF binary
1066 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1067 [ -n "$soarch" ] || continue
1068 # process all libraries needed by the binary
1069 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1071 # extract the library name: libfoo.so
1072 soname="${sofile%%\.so\.*}.so"
1073 # extract the major version: 1
1074 soversion="${sofile##*\.so\.}"
1075 if in_array "${soname}" ${depends[@]}; then
1076 if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then
1077 # libfoo.so=1-64
1078 echo "${soname}=${soversion}-${soarch}"
1079 libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}")
1082 done
1083 done
1086 find_libprovides() {
1087 local libprovides
1088 find "$pkgdir" -type f -name \*.so\* | while read filename
1090 # check if we really have a shared object
1091 if LC_ALL=C readelf -h "$filename" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1092 # 64
1093 soarch=$(LC_ALL=C readelf -h "$filename" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1094 # get the string binaries link to: libfoo.so.1.2 -> libfoo.so.1
1095 sofile=$(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1096 [ -z "$sofile" ] && sofile="${filename##*/}"
1098 # extract the library name: libfoo.so
1099 soname="${sofile%%\.so\.*}.so"
1100 # extract the major version: 1
1101 soversion="${sofile##*\.so\.}"
1102 if in_array "${soname}" ${provides[@]}; then
1103 if ! in_array "${soname}=${soversion}-${soarch}" ${libprovides[@]}; then
1104 # libfoo.so=1-64
1105 echo "${soname}=${soversion}-${soarch}"
1106 libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}")
1110 done
1113 check_license() {
1114 # TODO maybe remove this at some point
1115 # warn if license array is not present or empty
1116 if [[ -z $license ]]; then
1117 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1118 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1122 write_pkginfo() {
1123 local builddate=$(date -u "+%s")
1124 if [[ -n $PACKAGER ]]; then
1125 local packager="$PACKAGER"
1126 else
1127 local packager="Unknown Packager"
1129 local size="$(find . -print0 | xargs -0 @SIZECMD@ | awk '{ sum += $1 } END { print sum }')"
1131 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1132 echo "# Generated by makepkg $myver"
1133 if (( INFAKEROOT )); then
1134 echo "# using $(fakeroot -v)"
1136 echo "# $(LC_ALL=C date -u)"
1137 echo "pkgname = $1"
1138 (( SPLITPKG )) && echo pkgbase = $pkgbase
1139 echo "pkgver = $(get_full_version)"
1140 echo "pkgdesc = $pkgdesc"
1141 echo "url = $url"
1142 echo "builddate = $builddate"
1143 echo "packager = $packager"
1144 echo "size = $size"
1145 echo "arch = $PKGARCH"
1147 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1148 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1149 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1150 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1151 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1152 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1154 local it
1156 libprovides=$(find_libprovides)
1157 libdepends=$(find_libdepends)
1158 provides=("${provides[@]}" ${libprovides})
1159 depends=("${depends[@]}" ${libdepends})
1161 for it in "${depends[@]}"; do
1162 if [[ $it = *.so ]]; then
1163 # check if the entry has been found by find_libdepends
1164 # if not, it's unneeded; tell the user so he can remove it
1165 if [[ ! $libdepends =~ (^|\s)${it}=.* ]]; then
1166 error "$(gettext "Cannot find library listed in %s: %s")" "'depends'" "$it"
1167 return 1
1169 else
1170 echo "depend = $it"
1172 done
1174 for it in "${provides[@]}"; do
1175 # ignore versionless entires (those come from the PKGBUILD)
1176 if [[ $it = *.so ]]; then
1177 # check if the entry has been found by find_libprovides
1178 # if not, it's unneeded; tell the user so he can remove it
1179 if [[ ! $libprovides =~ (^|\s)${it}=.* ]]; then
1180 error "$(gettext "Cannot find library listed in %s: %s")" "'provides'" "$it"
1181 return 1
1183 else
1184 echo "provides = $it"
1186 done
1188 for it in "${packaging_options[@]}"; do
1189 local ret="$(check_option $it)"
1190 if [[ $ret != "?" ]]; then
1191 if [[ $ret = y ]]; then
1192 echo "makepkgopt = $it"
1193 else
1194 echo "makepkgopt = !$it"
1197 done
1199 check_license
1202 check_package() {
1203 cd "$pkgdir"
1205 # check existence of backup files
1206 local file
1207 for file in "${backup[@]}"; do
1208 if [[ ! -f $file ]]; then
1209 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1211 done
1213 # check for references to the build and package directory
1214 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1215 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1217 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1218 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1223 create_package() {
1224 if [[ ! -d $pkgdir ]]; then
1225 error "$(gettext "Missing %s directory.")" "pkg/"
1226 plain "$(gettext "Aborting...")"
1227 exit 1 # $E_MISSING_PKGDIR
1230 check_package
1232 cd "$pkgdir"
1233 msg "$(gettext "Creating package...")"
1235 local nameofpkg
1236 if [[ -z $1 ]]; then
1237 nameofpkg="$pkgname"
1238 else
1239 nameofpkg="$1"
1242 if [[ $arch = "any" ]]; then
1243 PKGARCH="any"
1244 else
1245 PKGARCH=$CARCH
1248 write_pkginfo $nameofpkg > .PKGINFO
1250 local comp_files=".PKGINFO"
1252 # check for changelog/install files
1253 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1254 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1256 if [[ -n ${!orig} ]]; then
1257 msg2 "$(gettext "Adding %s file...")" "$orig"
1258 cp "$startdir/${!orig}" "$dest"
1259 chmod 644 "$dest"
1260 comp_files+=" $dest"
1262 done
1264 # tar it up
1265 msg2 "$(gettext "Compressing package...")"
1267 local fullver=$(get_full_version)
1268 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}"
1269 local ret=0
1271 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1272 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1274 # when fileglobbing, we want * in an empty directory to expand to
1275 # the null string rather than itself
1276 shopt -s nullglob
1277 # TODO: Maybe this can be set globally for robustness
1278 shopt -s -o pipefail
1279 # bsdtar's gzip compression always saves the time stamp, making one
1280 # archive created using the same command line distinct from another.
1281 # Disable bsdtar compression and use gzip -n for now.
1282 bsdtar -cf - $comp_files * |
1283 case "$PKGEXT" in
1284 *tar.gz) gzip -c -f -n ;;
1285 *tar.bz2) bzip2 -c -f ;;
1286 *tar.xz) xz -c -z - ;;
1287 *tar.Z) compress -c -f ;;
1288 *tar) cat ;;
1289 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1290 "$PKGEXT"; cat ;;
1291 esac > "${pkg_file}" || ret=$?
1293 shopt -u nullglob
1294 shopt -u -o pipefail
1296 if (( ret )); then
1297 error "$(gettext "Failed to create package file.")"
1298 exit 1 # TODO: error code
1301 create_signature "$pkg_file"
1303 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1304 rm -f "${pkg_file/$PKGDEST/$startdir}"
1305 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1306 ret=$?
1307 if [[ -f $pkg_file.sig ]]; then
1308 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1309 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1313 if (( ret )); then
1314 warning "$(gettext "Failed to create symlink to package file.")"
1318 create_signature() {
1319 if [[ $SIGNPKG != 'y' ]]; then
1320 return
1322 local ret=0
1323 local filename="$1"
1324 msg "$(gettext "Signing package...")"
1326 local SIGNWITHKEY=""
1327 if [[ -n $GPGKEY ]]; then
1328 SIGNWITHKEY="-u ${GPGKEY}"
1330 # The signature will be generated directly in ascii-friendly format
1331 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1334 if (( ! ret )); then
1335 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1336 else
1337 warning "$(gettext "Failed to sign package file.")"
1341 create_srcpackage() {
1342 local ret=0
1343 msg "$(gettext "Creating source package...")"
1344 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1345 mkdir "${srclinks}"/${pkgbase}
1347 check_license
1349 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1350 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1352 local file
1353 for file in "${source[@]}"; do
1354 if [[ "$file" == $(get_filename "$file") ]] || (( SOURCEONLY == 2 )); then
1355 local absfile
1356 absfile=$(get_filepath "$file") || missing_source_file "$file"
1357 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1358 ln -s "$absfile" "$srclinks/$pkgbase"
1360 done
1362 local i
1363 for i in 'changelog' 'install'; do
1364 local file
1365 while read -r file; do
1366 # evaluate any bash variables used
1367 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1368 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1369 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1370 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1372 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1373 done
1375 local TAR_OPT
1376 case "$SRCEXT" in
1377 *tar.gz) TAR_OPT="z" ;;
1378 *tar.bz2) TAR_OPT="j" ;;
1379 *tar.xz) TAR_OPT="J" ;;
1380 *tar.Z) TAR_OPT="Z" ;;
1381 *tar) TAR_OPT="" ;;
1382 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1383 "$SRCEXT" ;;
1384 esac
1386 local fullver=$(get_full_version)
1387 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1389 # tar it up
1390 msg2 "$(gettext "Compressing source package...")"
1391 cd "${srclinks}"
1392 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1393 error "$(gettext "Failed to create source package file.")"
1394 exit 1 # TODO: error code
1397 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1398 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1399 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1400 ret=$?
1403 if (( ret )); then
1404 warning "$(gettext "Failed to create symlink to source package file.")"
1407 cd "${startdir}"
1408 rm -rf "${srclinks}"
1411 install_package() {
1412 (( ! INSTALL )) && return
1414 if (( ! SPLITPKG )); then
1415 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1416 else
1417 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1420 local fullver pkg pkglist
1421 for pkg in ${pkgname[@]}; do
1422 fullver=$(get_full_version $pkg)
1423 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} ]]; then
1424 pkglist+=" $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT}"
1425 else
1426 pkglist+=" $PKGDEST/${pkg}-${fullver}-any${PKGEXT}"
1428 done
1430 if ! run_pacman -U $pkglist; then
1431 warning "$(gettext "Failed to install built package(s).")"
1432 return 0
1436 check_sanity() {
1437 # check for no-no's in the build script
1438 local i
1439 local ret=0
1440 for i in 'pkgname' 'pkgrel' 'pkgver'; do
1441 if [[ -z ${!i} ]]; then
1442 error "$(gettext "%s is not allowed to be empty.")" "$i"
1443 ret=1
1445 done
1447 for i in "${pkgname[@]}"; do
1448 if [[ ${i:0:1} = "-" ]]; then
1449 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1450 ret=1
1452 done
1454 if [[ ${pkgbase:0:1} = "-" ]]; then
1455 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1456 ret=1
1459 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1460 while IFS='=' read -r _ i; do
1461 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1462 if [[ $i = *[[:space:]:-]* ]]; then
1463 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
1464 return 1
1466 done || ret=1
1468 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1469 while IFS='=' read -r _ i; do
1470 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1471 if [[ $i = *[[:space:]-]* ]]; then
1472 error "$(gettext "%s is not allowed to contain hyphens or whitespace.")" "pkgrel"
1473 return 1
1475 done || ret=1
1477 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1478 while IFS='=' read -r _ i; do
1479 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1480 if [[ $i != *([[:digit:]]) ]]; then
1481 error "$(gettext "%s must be an integer.")" "epoch"
1482 return 1
1484 done || ret=1
1486 if [[ $arch != 'any' ]]; then
1487 if ! in_array $CARCH ${arch[@]}; then
1488 if (( ! IGNOREARCH )); then
1489 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1490 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1491 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1492 ret=1
1497 if (( ${#pkgname[@]} > 1 )); then
1498 for i in ${pkgname[@]}; do
1499 local arch_list=""
1500 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1501 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1502 if ! in_array $CARCH ${arch_list[@]}; then
1503 if (( ! IGNOREARCH )); then
1504 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1505 ret=1
1509 done
1512 local provides_list=()
1513 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1514 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1515 for i in ${provides_list[@]}; do
1516 if [[ $i == *['<>']* ]]; then
1517 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1518 ret=1
1520 done
1522 local backup_list=()
1523 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1524 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1525 for i in "${backup_list[@]}"; do
1526 if [[ ${i:0:1} = "/" ]]; then
1527 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1528 ret=1
1530 done
1532 local optdepends_list=()
1533 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1534 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1535 for i in "${optdepends_list[@]}"; do
1536 local pkg=${i%%:[[:space:]]*}
1537 # the '-' character _must_ be first or last in the character range
1538 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1539 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1540 ret=1
1542 done
1544 for i in 'changelog' 'install'; do
1545 local file
1546 while read -r file; do
1547 # evaluate any bash variables used
1548 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1549 if [[ $file && ! -f $file ]]; then
1550 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1551 ret=1
1553 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1554 done
1556 local valid_options=1
1557 local known kopt options_list
1558 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1559 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1560 for i in ${options_list[@]}; do
1561 known=0
1562 # check if option matches a known option or its inverse
1563 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1564 if [[ ${i} = ${kopt} || ${i} = "!${kopt}" ]]; then
1565 known=1
1567 done
1568 if (( ! known )); then
1569 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1570 valid_options=0
1572 done
1573 if (( ! valid_options )); then
1574 ret=1
1577 if (( ${#pkgname[@]} > 1 )); then
1578 for i in ${pkgname[@]}; do
1579 if ! declare -f package_${i} >/dev/null; then
1580 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1581 ret=1
1583 done
1586 for i in ${PKGLIST[@]}; do
1587 if ! in_array $i ${pkgname[@]}; then
1588 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1589 ret=1
1591 done
1593 return $ret
1596 check_software() {
1597 # check for needed software
1598 local ret=0
1600 # check for sudo if we will need it during makepkg execution
1601 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1602 if ! type -p sudo >/dev/null; then
1603 warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")"
1607 # fakeroot - building as non-root user
1608 if [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then
1609 if ! type -p fakeroot >/dev/null; then
1610 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
1611 ret=1
1615 # gpg - package signing
1616 if [[ $SIGNPKG == 'y' || (-z "$SIGNPKG" && $(check_buildenv sign) == 'y') ]]; then
1617 if ! type -p gpg >/dev/null; then
1618 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
1619 ret=1
1623 # gpg - source verification
1624 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
1625 if ! type -p gpg >/dev/null; then
1626 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
1627 ret=1
1631 # openssl - checksum operations
1632 if (( ! SKIPCHECKSUMS )); then
1633 if ! type -p openssl >/dev/null; then
1634 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
1635 ret=1
1639 # upx - binary compression
1640 if [[ $(check_option upx) == 'y' ]]; then
1641 if ! type -p upx >/dev/null; then
1642 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
1643 ret=1
1647 # distcc - compilation with distcc
1648 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
1649 if ! type -p distcc >/dev/null; then
1650 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
1651 ret=1
1655 # ccache - compilation with ccache
1656 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
1657 if ! type -p ccache >/dev/null; then
1658 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
1659 ret=1
1663 # strip - strip symbols from binaries/libraries
1664 if [[ $(check_option strip) = "y" ]]; then
1665 if ! type -p strip >/dev/null; then
1666 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
1667 ret=1
1671 # gzip - compressig man and info pages
1672 if [[ $(check_option zipman) = "y" ]]; then
1673 if ! type -p gzip >/dev/null; then
1674 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
1675 ret=1
1679 return $ret
1682 devel_check() {
1683 newpkgver=""
1685 # Do not update pkgver if --holdver is set, when building a source package, repackaging,
1686 # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w)
1687 if (( HOLDVER || SOURCEONLY || REPKG )) ||
1688 [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = /dev/stdin ]]; then
1689 return
1692 if [[ -z $FORCE_VER ]]; then
1693 # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so.
1694 # This will only be used on the first call to makepkg; subsequent
1695 # calls to makepkg via fakeroot will explicitly pass the version
1696 # number to avoid having to determine the version number twice.
1697 # Also do a check to make sure we have the VCS tool available.
1698 oldpkgver=$pkgver
1699 if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then
1700 if ! type -p darcs >/dev/null; then
1701 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "darcs" "darcs"
1702 return 0
1704 msg "$(gettext "Determining latest %s revision...")" 'darcs'
1705 newpkgver=$(date +%Y%m%d)
1706 elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then
1707 if ! type -p cvs >/dev/null; then
1708 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "cvs" "cvs"
1709 return 0
1711 msg "$(gettext "Determining latest %s revision...")" 'cvs'
1712 newpkgver=$(date +%Y%m%d)
1713 elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then
1714 if ! type -p git >/dev/null; then
1715 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "git" "git"
1716 return 0
1718 msg "$(gettext "Determining latest %s revision...")" 'git'
1719 newpkgver=$(date +%Y%m%d)
1720 elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then
1721 if ! type -p svn >/dev/null; then
1722 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "svn" "svn"
1723 return 0
1725 msg "$(gettext "Determining latest %s revision...")" 'svn'
1726 newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p')
1727 elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then
1728 if ! type -p bzr >/dev/null; then
1729 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "bzr" "bzr"
1730 return 0
1732 msg "$(gettext "Determining latest %s revision...")" 'bzr'
1733 newpkgver=$(bzr revno ${_bzrtrunk})
1734 elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then
1735 if ! type -p hg >/dev/null; then
1736 warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "hg" "hg"
1737 return 0
1739 msg "$(gettext "Determining latest %s revision...")" 'hg'
1740 if [[ -d ./src/$_hgrepo ]] ; then
1741 cd ./src/$_hgrepo
1742 hg pull
1743 hg update
1744 else
1745 [[ ! -d ./src/ ]] && mkdir ./src/
1746 hg clone $_hgroot/$_hgrepo ./src/$_hgrepo
1747 cd ./src/$_hgrepo
1749 newpkgver=$(hg tip --template "{rev}")
1750 cd ../../
1753 if [[ -n $newpkgver ]]; then
1754 msg2 "$(gettext "Version found: %s")" "$newpkgver"
1757 else
1758 # Version number retrieved from fakeroot->makepkg argument
1759 newpkgver=$FORCE_VER
1763 devel_update() {
1764 # This is lame, but if we're wanting to use an updated pkgver for
1765 # retrieving svn/cvs/etc sources, we'll update the PKGBUILD with
1766 # the new pkgver and then re-source it. This is the most robust
1767 # method for dealing with PKGBUILDs that use, e.g.:
1769 # pkgver=23
1770 # ...
1771 # _foo=pkgver
1773 if [[ -n $newpkgver ]]; then
1774 if [[ $newpkgver != "$pkgver" ]]; then
1775 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
1776 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
1777 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
1778 source "$BUILDFILE"
1784 backup_package_variables() {
1785 local var
1786 for var in ${splitpkg_overrides[@]}; do
1787 local indirect="${var}_backup"
1788 eval "${indirect}=(\"\${$var[@]}\")"
1789 done
1792 restore_package_variables() {
1793 local var
1794 for var in ${splitpkg_overrides[@]}; do
1795 local indirect="${var}_backup"
1796 if [[ -n ${!indirect} ]]; then
1797 eval "${var}=(\"\${$indirect[@]}\")"
1798 else
1799 unset ${var}
1801 done
1804 run_split_packaging() {
1805 local pkgname_backup=${pkgname[@]}
1806 for pkgname in ${pkgname_backup[@]}; do
1807 pkgdir="$pkgdir/$pkgname"
1808 mkdir -p "$pkgdir"
1809 chmod a-s "$pkgdir"
1810 backup_package_variables
1811 run_package $pkgname
1812 tidy_install
1813 create_package $pkgname
1814 restore_package_variables
1815 pkgdir="${pkgdir%/*}"
1816 done
1817 pkgname=${pkgname_backup[@]}
1820 # Canonicalize a directory path if it exists
1821 canonicalize_path() {
1822 local path="$1";
1824 if [[ -d $path ]]; then
1826 cd "$path"
1827 pwd -P
1829 else
1830 echo "$path"
1834 m4_include(library/parse_options.sh)
1836 usage() {
1837 printf "makepkg (pacman) %s\n" "$myver"
1838 echo
1839 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
1840 echo
1841 printf -- "$(gettext "Options:")"
1842 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
1843 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
1844 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
1845 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
1846 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
1847 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
1848 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
1849 printf -- "$(gettext " -i, --install Install package after successful build")\n"
1850 printf -- "$(gettext " -L, --log Log package build process")\n"
1851 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
1852 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
1853 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
1854 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
1855 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
1856 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
1857 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
1858 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
1859 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
1860 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1861 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
1862 printf -- "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT"
1863 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
1864 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
1865 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
1866 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
1867 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
1868 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
1869 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
1870 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
1871 echo
1872 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
1873 echo
1874 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
1875 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
1876 echo
1877 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
1878 echo
1881 version() {
1882 printf "makepkg (pacman) %s\n" "$myver"
1883 printf -- "$(gettext "\
1884 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
1885 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
1886 This is free software; see the source for copying conditions.\n\
1887 There is NO WARRANTY, to the extent permitted by law.\n")"
1890 # PROGRAM START
1892 # determine whether we have gettext; make it a no-op if we do not
1893 if ! type -p gettext >/dev/null; then
1894 gettext() {
1895 echo "$@"
1899 ARGLIST=("$@")
1901 # Parse Command Line Options.
1902 OPT_SHORT="AcdefFghiLmop:rRsSV"
1903 OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps"
1904 OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver,skippgpcheck"
1905 OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps"
1906 OPT_LONG+=",repackage,skipchecksums,skipinteg,skippgpcheck,sign,source,syncdeps"
1907 OPT_LONG+=",version,config:"
1909 # Pacman Options
1910 OPT_LONG+=",noconfirm,noprogressbar"
1911 if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then
1912 echo; usage; exit 1 # E_INVALID_OPTION;
1914 eval set -- "$OPT_TEMP"
1915 unset OPT_SHORT OPT_LONG OPT_TEMP
1917 while true; do
1918 case "$1" in
1919 # Pacman Options
1920 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
1921 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
1923 # Makepkg Options
1924 --allsource) SOURCEONLY=2 ;;
1925 --asroot) ASROOT=1 ;;
1926 -A|--ignorearch) IGNOREARCH=1 ;;
1927 -c|--clean) CLEANUP=1 ;;
1928 --check) RUN_CHECK='y' ;;
1929 --config) shift; MAKEPKG_CONF=$1 ;;
1930 -d|--nodeps) NODEPS=1 ;;
1931 -e|--noextract) NOEXTRACT=1 ;;
1932 -f|--force) FORCE=1 ;;
1933 #hidden opt used by fakeroot call for svn/cvs/etc PKGBUILDs to set pkgver
1934 --forcever) shift; FORCE_VER=$1;;
1935 -F) INFAKEROOT=1 ;;
1936 -g|--geninteg) GENINTEG=1 ;;
1937 --holdver) HOLDVER=1 ;;
1938 -i|--install) INSTALL=1 ;;
1939 --key) shift; GPGKEY=$1 ;;
1940 -L|--log) LOGGING=1 ;;
1941 -m|--nocolor) USE_COLOR='n' ;;
1942 --nocheck) RUN_CHECK='n' ;;
1943 --nosign) SIGNPKG='n' ;;
1944 -o|--nobuild) NOBUILD=1 ;;
1945 -p) shift; BUILDFILE=$1 ;;
1946 --pkg) shift; PKGLIST=($1) ;;
1947 -r|--rmdeps) RMDEPS=1 ;;
1948 -R|--repackage) REPKG=1 ;;
1949 --skipchecksums) SKIPCHECKSUMS=1 ;;
1950 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
1951 --skippgpcheck) SKIPPGPCHECK=1;;
1952 --sign) SIGNPKG='y' ;;
1953 -s|--syncdeps) DEP_BIN=1 ;;
1954 -S|--source) SOURCEONLY=1 ;;
1956 -h|--help) usage; exit 0 ;; # E_OK
1957 -V|--version) version; exit 0 ;; # E_OK
1959 --) OPT_IND=0; shift; break;;
1960 *) usage; exit 1 ;; # E_INVALID_OPTION
1961 esac
1962 shift
1963 done
1965 # setup signal traps
1966 trap 'clean_up' 0
1967 for signal in TERM HUP QUIT; do
1968 trap "trap_exit \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
1969 done
1970 trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT
1971 trap 'trap_exit "$(gettext "An unknown error has occurred. Exiting...")"' ERR
1972 set -E
1974 # preserve environment variables and canonicalize path
1975 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
1976 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
1977 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
1978 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
1979 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
1980 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
1981 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
1982 [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
1984 # default config is makepkg.conf
1985 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
1987 # Source the config file; fail if it is not found
1988 if [[ -r $MAKEPKG_CONF ]]; then
1989 source "$MAKEPKG_CONF"
1990 else
1991 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
1992 plain "$(gettext "Aborting...")"
1993 exit 1 # $E_CONFIG_ERROR
1996 # Source user-specific makepkg.conf overrides, but only if no override config
1997 # file was specified
1998 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
1999 source ~/.makepkg.conf
2002 # set pacman command if not already defined
2003 PACMAN=${PACMAN:-pacman}
2005 # check if messages are to be printed using color
2006 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2007 if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then
2008 # prefer terminal safe colored and bold text when tput is supported
2009 if tput setaf 0 &>/dev/null; then
2010 ALL_OFF="$(tput sgr0)"
2011 BOLD="$(tput bold)"
2012 BLUE="${BOLD}$(tput setaf 4)"
2013 GREEN="${BOLD}$(tput setaf 2)"
2014 RED="${BOLD}$(tput setaf 1)"
2015 YELLOW="${BOLD}$(tput setaf 3)"
2016 else
2017 ALL_OFF="\e[1;0m"
2018 BOLD="\e[1;1m"
2019 BLUE="${BOLD}\e[1;34m"
2020 GREEN="${BOLD}\e[1;32m"
2021 RED="${BOLD}\e[1;31m"
2022 YELLOW="${BOLD}\e[1;33m"
2025 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2027 # override settings with an environment variable for batch processing
2028 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2029 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2030 if [[ ! -d $BUILDDIR ]]; then
2031 mkdir -p "$BUILDDIR" ||
2032 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2033 chmod a-s "$BUILDDIR"
2035 if [[ ! -w $BUILDDIR ]]; then
2036 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2037 plain "$(gettext "Aborting...")"
2038 exit 1
2040 srcdir="$BUILDDIR/src"
2041 pkgdir="$BUILDDIR/pkg"
2043 PKGDEST=${_PKGDEST:-$PKGDEST}
2044 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2045 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2046 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2047 plain "$(gettext "Aborting...")"
2048 exit 1
2051 SRCDEST=${_SRCDEST:-$SRCDEST}
2052 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2053 if [[ ! -w $SRCDEST ]] ; then
2054 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2055 plain "$(gettext "Aborting...")"
2056 exit 1
2059 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2060 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2062 PKGEXT=${_PKGEXT:-$PKGEXT}
2063 SRCEXT=${_SRCEXT:-$SRCEXT}
2064 GPGKEY=${_GPGKEY:-$GPGKEY}
2065 PACKAGER=${_PACKAGER:-$PACKAGER}
2067 if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then
2068 # The '\\0' is here to prevent gettext from thinking --holdver is an option
2069 error "$(gettext "\\0%s and %s cannot both be specified" )" "--holdver" "--forcever"
2070 exit 1
2073 if (( ! INFAKEROOT )); then
2074 if (( EUID == 0 && ! ASROOT )); then
2075 # Warn those who like to live dangerously.
2076 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2077 catastrophic damage to your system. If you wish to run as root, please\n\
2078 use the %s option.")" "makepkg" "--asroot"
2079 exit 1 # $E_USER_ABORT
2080 elif (( EUID > 0 && ASROOT )); then
2081 # Warn those who try to use the --asroot option when they are not root
2082 error "$(gettext "The %s option is meant for the root user only. Please\n\
2083 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2084 exit 1 # $E_USER_ABORT
2085 elif (( EUID > 0 )) && [[ $(check_buildenv fakeroot) != "y" ]]; then
2086 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2087 ownership of the packaged files. Try using the %s environment by\n\
2088 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2089 sleep 1
2091 else
2092 if [[ -z $FAKEROOTKEY ]]; then
2093 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2094 exit 1 # TODO: error code
2098 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2099 unset md5sums replaces depends conflicts backup source install changelog build
2100 unset makedepends optdepends options noextract
2102 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2103 if [[ ! -f $BUILDFILE ]]; then
2104 if [[ -t 0 ]]; then
2105 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2106 exit 1
2107 else
2108 # PKGBUILD passed through a pipe
2109 BUILDFILE=/dev/stdin
2110 source "$BUILDFILE"
2112 else
2113 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2114 if [[ -n $crlftest ]]; then
2115 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2116 exit 1
2119 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2120 BUILDFILE="$startdir/$BUILDFILE"
2122 source "$BUILDFILE"
2125 # set defaults if they weren't specified in buildfile
2126 pkgbase=${pkgbase:-${pkgname[0]}}
2127 epoch=${epoch:-0}
2129 if (( GENINTEG )); then
2130 mkdir -p "$srcdir"
2131 chmod a-s "$srcdir"
2132 cd "$srcdir"
2133 download_sources
2134 generate_checksums
2135 exit 0 # $E_OK
2138 # check the PKGBUILD for some basic requirements
2139 check_sanity || exit 1
2141 # check we have the software required to process the PKGBUILD
2142 check_software || exit 1
2144 # We need to run devel_update regardless of whether we are in the fakeroot
2145 # build process so that if the user runs makepkg --forcever manually, we
2146 # 1) output the correct pkgver, and 2) use the correct filename when
2147 # checking if the package file already exists - fixes FS #9194
2148 devel_check
2149 devel_update
2151 if (( ${#pkgname[@]} > 1 )); then
2152 SPLITPKG=1
2155 # test for available PKGBUILD functions
2156 if declare -f build >/dev/null; then
2157 BUILDFUNC=1
2159 if declare -f check >/dev/null; then
2160 # "Hide" check() function if not going to be run
2161 if [[ $RUN_CHECK = 'y' || (! $(check_buildenv check) = "n" && ! $RUN_CHECK = "n") ]]; then
2162 CHECKFUNC=1
2165 if declare -f package >/dev/null; then
2166 PKGFUNC=1
2167 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2168 SPLITPKG=1
2171 if [[ -n "${PKGLIST[@]}" ]]; then
2172 unset pkgname
2173 pkgname=("${PKGLIST[@]}")
2176 # check if gpg signature is to be created and if signing key is valid
2177 [[ -z $SIGNPKG ]] && SIGNPKG=$(check_buildenv sign)
2178 if [[ $SIGNPKG == 'y' ]]; then
2179 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2180 if [[ ! -z $GPGKEY ]]; then
2181 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2182 else
2183 error "$(gettext "There is no key in your keyring.")"
2185 exit 1
2190 if (( ! SPLITPKG )); then
2191 fullver=$(get_full_version)
2192 if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \
2193 || -f $PKGDEST/${pkgname}-${fullver}-any${PKGEXT} ]] \
2194 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2195 if (( INSTALL )); then
2196 warning "$(gettext "A package has already been built, installing existing package...")"
2197 install_package
2198 exit $?
2199 else
2200 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2201 exit 1
2204 else
2205 allpkgbuilt=1
2206 somepkgbuilt=0
2207 for pkg in ${pkgname[@]}; do
2208 fullver=$(get_full_version $pkg)
2209 if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} \
2210 || -f $PKGDEST/${pkg}-${fullver}-any${PKGEXT} ]]; then
2211 somepkgbuilt=1
2212 else
2213 allpkgbuilt=0
2215 done
2216 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2217 if (( allpkgbuilt )); then
2218 if (( INSTALL )); then
2219 warning "$(gettext "The package group has already been built, installing existing packages...")"
2220 install_package
2221 exit $?
2222 else
2223 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2224 exit 1
2227 if (( somepkgbuilt )); then
2228 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2229 exit 1
2232 unset allpkgbuilt somepkgbuilt
2235 # Run the bare minimum in fakeroot
2236 if (( INFAKEROOT )); then
2237 if (( SOURCEONLY )); then
2238 create_srcpackage
2239 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2240 exit 0 # $E_OK
2243 if (( ! SPLITPKG )); then
2244 if (( ! PKGFUNC )); then
2245 if (( ! REPKG )); then
2246 if (( BUILDFUNC )); then
2247 run_build
2248 (( CHECKFUNC )) && run_check
2249 tidy_install
2251 else
2252 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2253 plain "$(gettext "File permissions may not be preserved.")"
2255 else
2256 run_package
2257 tidy_install
2259 create_package
2260 else
2261 run_split_packaging
2264 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2265 exit 0 # $E_OK
2268 fullver=$(get_full_version)
2269 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2271 # if we are creating a source-only package, go no further
2272 if (( SOURCEONLY )); then
2273 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2274 && (( ! FORCE )); then
2275 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2276 exit 1
2279 # Get back to our src directory so we can begin with sources.
2280 mkdir -p "$srcdir"
2281 chmod a-s "$srcdir"
2282 cd "$srcdir"
2283 if ( (( ! SKIPCHECKSUMS )) || \
2284 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \
2285 (( SOURCEONLY == 2 )); then
2286 download_sources
2288 check_source_integrity
2289 cd "$startdir"
2291 # if we are root or if fakeroot is not enabled, then we don't use it
2292 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2293 create_srcpackage
2294 else
2295 enter_fakeroot
2298 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2299 exit 0
2302 if (( NODEPS || ( (NOBUILD || REPKG) && !DEP_BIN ) )); then
2303 # no warning message needed for nobuild, repkg
2304 if (( NODEPS || ( REPKG && PKGFUNC ) )); then
2305 warning "$(gettext "Skipping dependency checks.")"
2307 elif type -p "${PACMAN%% *}" >/dev/null; then
2308 if (( RMDEPS )); then
2309 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2311 deperr=0
2313 msg "$(gettext "Checking runtime dependencies...")"
2314 resolve_deps ${depends[@]} || deperr=1
2316 msg "$(gettext "Checking buildtime dependencies...")"
2317 resolve_deps ${makedepends[@]} || deperr=1
2319 if (( CHECKFUNC )); then
2320 resolve_deps ${checkdepends[@]} || deperr=1
2323 if (( RMDEPS )); then
2324 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2327 if (( deperr )); then
2328 error "$(gettext "Could not resolve all dependencies.")"
2329 exit 1
2331 else
2332 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2335 # ensure we have a sane umask set
2336 umask 0022
2338 # get back to our src directory so we can begin with sources
2339 mkdir -p "$srcdir"
2340 chmod a-s "$srcdir"
2341 cd "$srcdir"
2343 if (( NOEXTRACT )); then
2344 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2345 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2346 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2348 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2349 error "$(gettext "The source directory is empty, there is nothing to build!")"
2350 plain "$(gettext "Aborting...")"
2351 exit 1
2353 elif (( REPKG )); then
2354 if (( ! PKGFUNC && ! SPLITPKG )) \
2355 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2356 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2357 plain "$(gettext "Aborting...")"
2358 exit 1
2360 else
2361 download_sources
2362 check_source_integrity
2363 extract_sources
2366 if (( NOBUILD )); then
2367 msg "$(gettext "Sources are ready.")"
2368 exit 0 #E_OK
2369 else
2370 # check for existing pkg directory; don't remove if we are repackaging
2371 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2372 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2373 rm -rf "$pkgdir"
2375 mkdir -p "$pkgdir"
2376 chmod a-s "$pkgdir"
2377 cd "$startdir"
2379 # if we are root or if fakeroot is not enabled, then we don't use it
2380 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2381 if (( ! REPKG )); then
2382 devel_update
2383 (( BUILDFUNC )) && run_build
2384 (( CHECKFUNC )) && run_check
2386 if (( ! SPLITPKG )); then
2387 if (( PKGFUNC )); then
2388 run_package
2389 tidy_install
2390 else
2391 if (( ! REPKG )); then
2392 tidy_install
2393 else
2394 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2395 plain "$(gettext "File permissions may not be preserved.")"
2398 create_package
2399 else
2400 run_split_packaging
2402 else
2403 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2404 devel_update
2405 (( BUILDFUNC )) && run_build
2406 (( CHECKFUNC )) && run_check
2407 cd "$startdir"
2410 enter_fakeroot
2414 fullver=$(get_full_version)
2415 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2417 install_package
2419 exit 0 #E_OK
2421 # vim: set ts=2 sw=2 noet: