makepkg: check pkgver validity after updating
[pacman-ng.git] / scripts / makepkg.sh.in
blob3157a9cea03e557f4e7bd297b68166797809eece
1 #!/bin/bash
3 # makepkg - make packages compatible for use with pacman
4 # @configure_input@
6 # Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
7 # Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
8 # Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
9 # Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org>
10 # Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
11 # Copyright (c) 2006 by Alex Smith <alex@alex-smith.me.uk>
12 # Copyright (c) 2006 by Andras Voroskoi <voroskoi@frugalware.org>
14 # This program is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
28 # makepkg uses quite a few external programs during its execution. You
29 # need to have at least the following installed for makepkg to function:
30 # awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils),
31 # gettext, gpg, grep, gzip, openssl, sed, tput (ncurses), xz
33 # gettext initialization
34 export TEXTDOMAIN='pacman-scripts'
35 export TEXTDOMAINDIR='@localedir@'
37 # file -i does not work on Mac OSX unless legacy mode is set
38 export COMMAND_MODE='legacy'
39 # Ensure CDPATH doesn't screw with our cd calls
40 unset CDPATH
42 declare -r makepkg_version='@PACKAGE_VERSION@'
43 declare -r confdir='@sysconfdir@'
44 declare -r BUILDSCRIPT='@BUILDSCRIPT@'
45 declare -r startdir="$PWD"
47 packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge' 'upx')
48 other_options=('ccache' 'distcc' 'buildflags' 'makeflags')
49 splitpkg_overrides=('pkgver' 'pkgrel' 'epoch' 'pkgdesc' 'arch' 'url' '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 ASDEPS=0
56 ASROOT=0
57 CLEANUP=0
58 DEP_BIN=0
59 FORCE=0
60 INFAKEROOT=0
61 GENINTEG=0
62 HOLDVER=0
63 SKIPCHECKSUMS=0
64 SKIPPGPCHECK=0
65 INSTALL=0
66 NOBUILD=0
67 NODEPS=0
68 NOEXTRACT=0
69 RMDEPS=0
70 REPKG=0
71 LOGGING=0
72 SOURCEONLY=0
73 IGNOREARCH=0
74 PREPAREFUNC=0
75 BUILDFUNC=0
76 CHECKFUNC=0
77 PKGFUNC=0
78 SPLITPKG=0
79 PKGLIST=()
80 SIGNPKG=''
82 # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call
83 # when dealing with svn/cvs/etc PKGBUILDs.
84 FORCE_VER=""
86 PACMAN_OPTS=
88 shopt -s extglob
90 ### SUBROUTINES ###
92 plain() {
93 local mesg=$1; shift
94 printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
97 msg() {
98 local mesg=$1; shift
99 printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
102 msg2() {
103 local mesg=$1; shift
104 printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
107 warning() {
108 local mesg=$1; shift
109 printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
112 error() {
113 local mesg=$1; shift
114 printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
119 # Special exit call for traps, Don't print any error messages when inside,
120 # the fakeroot call, the error message will be printed by the main call.
122 trap_exit() {
123 local signal=$1; shift
125 if (( ! INFAKEROOT )); then
126 echo
127 error "$@"
129 [[ -n $srclinks ]] && rm -rf "$srclinks"
131 # unset the trap for this signal, and then call the default handler
132 trap -- "$signal"
133 kill "-$signal" "$$"
138 # Clean up function. Called automatically when the script exits.
140 clean_up() {
141 local EXIT_CODE=$?
143 if (( INFAKEROOT )); then
144 # Don't clean up when leaving fakeroot, we're not done yet.
145 return
148 if (( ! EXIT_CODE && CLEANUP )); then
149 local pkg file
151 # If it's a clean exit and -c/--clean has been passed...
152 msg "$(gettext "Cleaning up...")"
153 rm -rf "$pkgdir" "$srcdir"
154 if [[ -n $pkgbase ]]; then
155 local fullver=$(get_full_version)
156 # Can't do this unless the BUILDSCRIPT has been sourced.
157 if (( BUILDFUNC )); then
158 rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"*
160 if (( CHECKFUNC )); then
161 rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
163 if (( PKGFUNC )); then
164 rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
165 elif (( SPLITPKG )); then
166 for pkg in ${pkgname[@]}; do
167 rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"*
168 done
171 # clean up dangling symlinks to packages
172 for pkg in ${pkgname[@]}; do
173 for file in ${pkg}-*-*-*{${PKGEXT},${SRCEXT}}; do
174 if [[ -h $file && ! -e $file ]]; then
175 rm -f "$file"
177 done
178 done
182 remove_deps
186 enter_fakeroot() {
187 msg "$(gettext "Entering %s environment...")" "fakeroot"
188 fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
192 # a source entry can have two forms :
193 # 1) "filename::http://path/to/file"
194 # 2) "http://path/to/file"
196 # Return the absolute filename of a source entry
197 get_filepath() {
198 local file="$(get_filename "$1")"
199 local proto="$(get_protocol "$1")"
201 case $proto in
202 git*|svn*)
203 if [[ -d "$startdir/$file" ]]; then
204 file="$startdir/$file"
205 elif [[ -d "$SRCDEST/$file" ]]; then
206 file="$SRCDEST/$file"
207 else
208 return 1
212 if [[ -f "$startdir/$file" ]]; then
213 file="$startdir/$file"
214 elif [[ -f "$SRCDEST/$file" ]]; then
215 file="$SRCDEST/$file"
216 else
217 return 1
220 esac
222 printf "%s\n" "$file"
225 # extract the filename from a source entry
226 get_filename() {
227 local netfile=$1
229 # if a filename is specified, use it
230 if [[ $netfile = *::* ]]; then
231 printf "%s\n" ${netfile%%::*}
232 return
235 local proto=$(get_protocol "$netfile")
237 case $proto in
238 git*|svn*)
239 filename=${netfile##*/}
240 filename=${filename%%#*}
241 # fall-through
243 git*)
244 filename=${filename%%.git*}
247 # if it is just an URL, we only keep the last component
248 filename="${netfile##*/}"
250 esac
251 printf "%s\n" "${filename}"
254 # extract the URL from a source entry
255 get_url() {
256 # strip an eventual filename
257 printf "%s\n" "${1#*::}"
260 # extract the protocol from a source entry - return "local" for local sources
261 get_protocol() {
262 if [[ $1 = *://* ]]; then
263 # strip leading filename
264 local proto="${1##*::}"
265 printf "%s\n" "${proto%%://*}"
266 else
267 printf "%s\n" local
271 get_downloadclient() {
272 local proto=$1
274 # loop through DOWNLOAD_AGENTS variable looking for protocol
275 local i
276 for i in "${DLAGENTS[@]}"; do
277 local handler="${i%%::*}"
278 if [[ $proto = "$handler" ]]; then
279 local agent="${i##*::}"
280 break
282 done
284 # if we didn't find an agent, return an error
285 if [[ -z $agent ]]; then
286 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
287 plain "$(gettext "Aborting...")"
288 exit 1 # $E_CONFIG_ERROR
291 # ensure specified program is installed
292 local program="${agent%% *}"
293 if [[ ! -x $program ]]; then
294 local baseprog="${program##*/}"
295 error "$(gettext "The download program %s is not installed.")" "$baseprog"
296 plain "$(gettext "Aborting...")"
297 exit 1 # $E_MISSING_PROGRAM
300 printf "%s\n" "$agent"
303 download_local() {
304 local netfile=$1
305 local filepath=$(get_filepath "$netfile")
307 if [[ -n "$filepath" ]]; then
308 msg2 "$(gettext "Found %s")" "${filepath##*/}"
309 rm -f "$srcdir/${filepath##*/}"
310 ln -s "$filepath" "$srcdir/"
311 continue
312 else
313 local filename=$(get_filename "$netfile")
314 error "$(gettext "%s was not found in the build directory and is not a URL.")" "$filename"
315 exit 1 # $E_MISSING_FILE
319 download_file() {
320 local netfile=$1
322 local filepath=$(get_filepath "$netfile")
323 if [[ -n "$filepath" ]]; then
324 msg2 "$(gettext "Found %s")" "${filepath##*/}"
325 rm -f "$srcdir/${filepath##*/}"
326 ln -s "$filepath" "$srcdir/"
327 return
330 local proto=$(get_protocol "$netfile")
332 # find the client we should use for this URL
333 local dlcmd
334 dlcmd=$(get_downloadclient "$proto") || exit $?
336 local filename=$(get_filename "$netfile")
337 local url=$(get_url "$netfile")
339 if [[ $proto = "scp" ]]; then
340 # scp downloads should not pass the protocol in the url
341 url="${url##*://}"
344 msg2 "$(gettext "Downloading %s...")" "$filename"
346 # temporary download file, default to last component of the URL
347 local dlfile="${url##*/}"
349 # replace %o by the temporary dlfile if it exists
350 if [[ $dlcmd = *%o* ]]; then
351 dlcmd=${dlcmd//\%o/\"$filename.part\"}
352 dlfile="$filename.part"
354 # add the URL, either in place of %u or at the end
355 if [[ $dlcmd = *%u* ]]; then
356 dlcmd=${dlcmd//\%u/\"$url\"}
357 else
358 dlcmd="$dlcmd \"$url\""
361 local ret=0
362 eval "$dlcmd || ret=\$?"
363 if (( ret )); then
364 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
365 error "$(gettext "Failure while downloading %s")" "$filename"
366 plain "$(gettext "Aborting...")"
367 exit 1
370 # rename the temporary download file to the final destination
371 if [[ $dlfile != "$filename" ]]; then
372 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$filename"
375 rm -f "$srcdir/$filename"
376 ln -s "$SRCDEST/$filename" "$srcdir/"
379 download_git() {
380 local netfile=$1
382 local fragment=${netfile##*#}
383 if [[ $fragment = "$netfile" ]]; then
384 unset fragment
387 local dir=$(get_filepath "$netfile")
388 [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"
390 local repo=${netfile##*/}
391 repo=${repo%%#*}
392 repo=${repo%%.git*}
394 local url=$(get_url "$netfile")
395 url=${url##*git+}
396 url=${url%%#*}
398 if [[ ! -d "$dir" ]]; then
399 msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git"
400 if ! git clone --mirror "$url" "$dir"; then
401 error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "git"
402 plain "$(gettext "Aborting...")"
403 exit 1
405 elif (( ! HOLDVER )); then
406 msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "git"
407 cd_safe "$dir"
408 if ! git fetch --all -p; then
409 # only warn on failure to allow offline builds
410 warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "git"
414 msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "git"
415 pushd "$srcdir" &>/dev/null
416 rm -rf "${dir##*/}"
418 if ! git clone "$dir"; then
419 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
420 plain "$(gettext "Aborting...")"
421 exit 1
424 cd_safe "${dir##*/}"
426 local ref
427 if [[ -n $fragment ]]; then
428 case ${fragment%%=*} in
429 commit|tag)
430 ref=${fragment##*=}
432 branch)
433 ref=origin/${fragment##*=}
436 error "$(gettext "Unrecognized reference: %s")" "${fragment}"
437 plain "$(gettext "Aborting...")"
438 exit 1
439 esac
442 if [[ -n $ref ]]; then
443 if ! git checkout -b makepkg $ref; then
444 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
445 plain "$(gettext "Aborting...")"
446 exit 1
450 popd &>/dev/null
453 download_svn() {
454 local netfile=$1
456 local fragment=${netfile##*#}
457 if [[ $fragment = "$netfile" ]]; then
458 unset fragment
461 local dir=$(get_filepath "$netfile")
462 [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"
464 local repo=${netfile##*/}
465 repo=${repo%%#*}
467 local url=$(get_url "$netfile")
468 if [[ $url != svn+ssh* ]]; then
469 url=${url##*svn+}
471 url=${url%%#*}
473 if [[ ! -d "$dir" ]]; then
474 msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "svn"
475 if ! svn checkout --config-dir "$dir" "$url" "$dir"; then
476 error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "svn"
477 plain "$(gettext "Aborting...")"
478 exit 1
480 elif (( ! HOLDVER )); then
481 msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "svn"
482 cd_safe "$dir"
483 if ! svn update; then
484 # only warn on failure to allow offline builds
485 warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "svn"
489 msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "svn"
490 pushd "$srcdir" &>/dev/null
491 rm -rf "${dir##*/}"
493 local ref
494 if [[ -n $fragment ]]; then
495 case ${fragment%%=*} in
496 revision)
497 ref=('-r' "${fragment##*=}")
500 error "$(gettext "Unrecognized reference: %s")" "${fragment}"
501 plain "$(gettext "Aborting...")"
502 exit 1
503 esac
506 if ! svn export $(ref[@]) "$dir"; then
507 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "svn"
508 plain "$(gettext "Aborting...")"
511 popd &>/dev/null
514 download_sources() {
515 msg "$(gettext "Retrieving Sources...")"
517 local GET_VCS=1
518 if [[ $1 == "fast" ]]; then
519 GET_VCS=0
522 pushd "$SRCDEST" &>/dev/null
524 local netfile
525 for netfile in "${source[@]}"; do
526 local proto=$(get_protocol "$netfile")
528 case "$proto" in
529 local)
530 download_local "$netfile"
532 ftp|http|https|rsync|scp)
533 download_file "$netfile"
535 git*)
536 (( GET_VCS )) && download_git "$netfile"
538 svn*)
539 (( GET_VCS )) && download_svn "$netfile"
542 error "$(gettext "Unknown download protocol: %s")" "$proto"
543 plain "$(gettext "Aborting...")"
544 exit 1
546 esac
547 done
549 if declare -f pkgver >/dev/null && (( GET_VCS )); then
550 update_pkgver
551 check_pkgver || exit 1
554 popd &>/dev/null
557 # Automatically update pkgver variable if a pkgver() function is provided
558 # Re-sources the PKGBUILD afterwards to allow for other variables that use $pkgver
559 update_pkgver() {
560 newpkgver=$(run_function_safe pkgver)
562 if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then
563 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
564 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
565 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
566 source "$BUILDFILE"
567 else
568 warning "$(gettext "%s is not writeable -- pkgver will not be updated")" \
569 "$BUILDFILE"
574 # Print 'source not found' error message and exit makepkg
575 missing_source_file() {
576 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
577 plain "$(gettext "Aborting...")"
578 exit 1 # $E_MISSING_FILE
582 # usage : get_full_version( [$pkgname] )
583 # return : full version spec, including epoch (if necessary), pkgver, pkgrel
585 get_full_version() {
586 if [[ -z $1 ]]; then
587 if [[ $epoch ]] && (( ! $epoch )); then
588 printf "%s\n" "$pkgver-$pkgrel"
589 else
590 printf "%s\n" "$epoch:$pkgver-$pkgrel"
592 else
593 for i in pkgver pkgrel epoch; do
594 local indirect="${i}_override"
595 eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
596 [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
597 done
598 if (( ! $epoch_override )); then
599 printf "%s\n" "$pkgver_override-$pkgrel_override"
600 else
601 printf "%s\n" "$epoch_override:$pkgver_override-$pkgrel_override"
607 # usage : get_pkg_arch( [$pkgname] )
608 # return : architecture of the package
610 get_pkg_arch() {
611 if [[ -z $1 ]]; then
612 if [[ $arch = "any" ]]; then
613 printf "%s\n" "any"
614 else
615 printf "%s\n" "$CARCH"
617 else
618 local arch_override
619 eval $(declare -f package_$1 | sed -n 's/\(^[[:space:]]*arch=\)/arch_override=/p')
620 (( ${#arch_override[@]} == 0 )) && arch_override=("${arch[@]}")
621 if [[ $arch_override = "any" ]]; then
622 printf "%s\n" "any"
623 else
624 printf "%s\n" "$CARCH"
630 # Checks to see if options are present in makepkg.conf or PKGBUILD;
631 # PKGBUILD options always take precedence.
633 # usage : check_option( $option, $expected_val )
634 # return : 0 - matches expected
635 # 1 - does not match expected
636 # 127 - not found
638 check_option() {
639 in_opt_array "$1" ${options[@]}
640 case $? in
641 0) # assert enabled
642 [[ $2 = y ]]
643 return ;;
644 1) # assert disabled
645 [[ $2 = n ]]
646 return
647 esac
649 # fall back to makepkg.conf options
650 in_opt_array "$1" ${OPTIONS[@]}
651 case $? in
652 0) # assert enabled
653 [[ $2 = y ]]
654 return ;;
655 1) # assert disabled
656 [[ $2 = n ]]
657 return
658 esac
660 # not found
661 return 127
666 # Check if option is present in BUILDENV
668 # usage : check_buildenv( $option, $expected_val )
669 # return : 0 - matches expected
670 # 1 - does not match expected
671 # 127 - not found
673 check_buildenv() {
674 in_opt_array "$1" ${BUILDENV[@]}
675 case $? in
676 0) # assert enabled
677 [[ $2 = "y" ]]
678 return ;;
679 1) # assert disabled
680 [[ $2 = "n" ]]
681 return ;;
682 esac
684 # not found
685 return 127
690 # usage : in_opt_array( $needle, $haystack )
691 # return : 0 - enabled
692 # 1 - disabled
693 # 127 - not found
695 in_opt_array() {
696 local needle=$1; shift
698 local opt
699 for opt in "$@"; do
700 if [[ $opt = "$needle" ]]; then
701 # enabled
702 return 0
703 elif [[ $opt = "!$needle" ]]; then
704 # disabled
705 return 1
707 done
709 # not found
710 return 127
715 # usage : in_array( $needle, $haystack )
716 # return : 0 - found
717 # 1 - not found
719 in_array() {
720 local needle=$1; shift
721 local item
722 for item in "$@"; do
723 [[ $item = "$needle" ]] && return 0 # Found
724 done
725 return 1 # Not Found
728 source_has_signatures() {
729 local file
730 for file in "${source[@]}"; do
731 if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
732 return 0
734 done
735 return 1
738 run_pacman() {
739 local cmd
740 if [[ ! $1 = -@(T|Qq) ]]; then
741 cmd=("$PACMAN" $PACMAN_OPTS "$@")
742 else
743 cmd=("$PACMAN" "$@")
745 if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then
746 if type -p sudo >/dev/null; then
747 cmd=(sudo "${cmd[@]}")
748 else
749 cmd=(su root -c "$(printf '%q ' "${cmd[@]}")")
752 "${cmd[@]}"
755 check_deps() {
756 (( $# > 0 )) || return 0
758 local ret=0
759 local pmout
760 pmout=$(run_pacman -T "$@")
761 ret=$?
763 if (( ret == 127 )); then #unresolved deps
764 printf "%s\n" "$pmout"
765 elif (( ret )); then
766 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
767 return "$ret"
771 handle_deps() {
772 local R_DEPS_SATISFIED=0
773 local R_DEPS_MISSING=1
775 (( $# == 0 )) && return $R_DEPS_SATISFIED
777 local deplist="$*"
779 if (( ! DEP_BIN )); then
780 return $R_DEPS_MISSING
783 if (( DEP_BIN )); then
784 # install missing deps from binary packages (using pacman -S)
785 msg "$(gettext "Installing missing dependencies...")"
787 if ! run_pacman -S --asdeps $deplist; then
788 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
789 exit 1 # TODO: error code
793 # we might need the new system environment
794 # save our shell options and turn off extglob
795 local shellopts=$(shopt -p)
796 shopt -u extglob
797 source /etc/profile &>/dev/null
798 eval "$shellopts"
800 return $R_DEPS_SATISFIED
803 resolve_deps() {
804 local R_DEPS_SATISFIED=0
805 local R_DEPS_MISSING=1
807 # deplist cannot be declared like this: local deplist=$(foo)
808 # Otherwise, the return value will depend on the assignment.
809 local deplist
810 deplist="$(set +E; check_deps $*)" || exit 1
811 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
813 if handle_deps $deplist; then
814 # check deps again to make sure they were resolved
815 deplist="$(set +E; check_deps $*)" || exit 1
816 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
819 msg "$(gettext "Missing Dependencies:")"
820 local dep
821 for dep in $deplist; do
822 msg2 "$dep"
823 done
825 return $R_DEPS_MISSING
828 remove_deps() {
829 (( ! RMDEPS )) && return
831 # check for packages removed during dependency install (e.g. due to conflicts)
832 # removing all installed packages is risky in this case
833 if [[ -n $(grep -xvFf <(printf '%s\n' "${current_packagelist[@]}") \
834 <(printf '%s\n' "${original_packagelist[@]}") || true) ]]; then
835 warning "$(gettext "Failed to remove installed dependencies.")"
836 return 0
839 local deplist
840 deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \
841 <(printf "%s\n" "${current_pkglist[@]}") || true))
842 if [[ -z $deplist ]]; then
843 return
846 msg "Removing installed dependencies..."
847 # exit cleanly on failure to remove deps as package has been built successfully
848 if ! run_pacman -Rn ${deplist[@]}; then
849 warning "$(gettext "Failed to remove installed dependencies.")"
850 return 0
854 get_integlist() {
855 local integ
856 local integlist=()
858 for integ in md5 sha1 sha256 sha384 sha512; do
859 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
860 if [[ -n "$integrity_sums" ]]; then
861 integlist=(${integlist[@]} $integ)
863 done
865 if (( ${#integlist[@]} > 0 )); then
866 printf "%s\n" "${integlist[@]}"
867 else
868 printf "%s\n" "${INTEGRITY_CHECK[@]}"
872 generate_checksums() {
873 msg "$(gettext "Generating checksums for source files...")"
875 if ! type -p openssl >/dev/null; then
876 error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
877 exit 1 # $E_MISSING_PROGRAM
880 local integlist
881 if (( $# == 0 )); then
882 integlist=$(get_integlist)
883 else
884 integlist=$@
887 local integ
888 for integ in ${integlist[@]}; do
889 case "$integ" in
890 md5|sha1|sha256|sha384|sha512) : ;;
892 error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
893 exit 1;; # $E_CONFIG_ERROR
894 esac
896 local ct=0
897 local numsrc=${#source[@]}
898 printf "%s" "${integ}sums=("
900 local i
901 local indent=''
902 for (( i = 0; i < ${#integ} + 6; i++ )); do
903 indent="$indent "
904 done
906 local netfile
907 for netfile in "${source[@]}"; do
908 local proto sum
909 proto="$(get_protocol "$netfile")"
911 case $proto in
912 git*|svn*)
913 sum="SKIP"
916 local file
917 file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
918 sum="$(openssl dgst -${integ} "$file")"
919 sum=${sum##* }
921 esac
923 (( ct )) && printf "%s" "$indent"
924 printf "%s" "'$sum'"
925 ct=$(($ct+1))
926 (( $ct < $numsrc )) && echo
927 done
929 echo ")"
930 done
933 check_checksums() {
934 (( SKIPCHECKSUMS )) && return 0
935 (( ! ${#source[@]} )) && return 0
937 local correlation=0
938 local integ required
939 for integ in md5 sha1 sha256 sha384 sha512; do
940 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
941 if (( ${#integrity_sums[@]} == ${#source[@]} )); then
942 msg "$(gettext "Validating source files with %s...")" "${integ}sums"
943 correlation=1
944 local errors=0
945 local idx=0
946 local file
947 for file in "${source[@]}"; do
948 local found=1
949 file="$(get_filename "$file")"
950 printf "%s" " $file ... " >&2
952 if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then
953 echo "$(gettext "Skipped")" >&2
954 idx=$((idx + 1))
955 continue
958 if ! file="$(get_filepath "$file")"; then
959 printf -- "$(gettext "NOT FOUND")\n" >&2
960 errors=1
961 found=0
964 if (( $found )) ; then
965 local expectedsum="${integrity_sums[idx],,}"
966 local realsum="$(openssl dgst -${integ} "$file")"
967 realsum="${realsum##* }"
968 if [[ $expectedsum = "$realsum" ]]; then
969 printf -- "$(gettext "Passed")\n" >&2
970 else
971 printf -- "$(gettext "FAILED")\n" >&2
972 errors=1
976 idx=$((idx + 1))
977 done
979 if (( errors )); then
980 error "$(gettext "One or more files did not pass the validity check!")"
981 exit 1 # TODO: error code
983 elif (( ${#integrity_sums[@]} )); then
984 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
985 exit 1 # TODO: error code
987 done
989 if (( ! correlation )); then
990 error "$(gettext "Integrity checks are missing.")"
991 exit 1 # TODO: error code
995 check_pgpsigs() {
996 (( SKIPPGPCHECK )) && return 0
997 ! source_has_signatures && return 0
999 msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
1001 local file pubkey
1002 local warning=0
1003 local errors=0
1004 local statusfile=$(mktemp)
1006 for file in "${source[@]}"; do
1007 file="$(get_filename "$file")"
1008 if [[ ! $file = *.@(sig?(n)|asc) ]]; then
1009 continue
1012 printf " %s ... " "${file%.*}" >&2
1014 if ! file="$(get_filepath "$file")"; then
1015 printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
1016 errors=1
1017 continue
1020 if ! sourcefile="$(get_filepath "${file%.*}")"; then
1021 printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
1022 errors=1
1023 continue
1026 if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
1027 printf '%s' "$(gettext "FAILED")" >&2
1028 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then
1029 printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
1030 warnings=1
1031 else
1032 errors=1
1034 printf '\n' >&2
1035 else
1036 if grep -q "REVKEYSIG" "$statusfile"; then
1037 printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2
1038 errors=1
1039 else
1040 printf '%s' "$(gettext "Passed")" >&2
1041 if grep -q "EXPSIG" "$statusfile"; then
1042 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
1043 warnings=1
1044 elif grep -q "EXPKEYSIG" "$statusfile"; then
1045 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
1046 warnings=1
1049 printf '\n' >&2
1051 done
1053 rm -f "$statusfile"
1055 if (( errors )); then
1056 error "$(gettext "One or more PGP signatures could not be verified!")"
1057 exit 1
1060 if (( warnings )); then
1061 warning "$(gettext "Warnings have occurred while verifying the signatures.")"
1062 plain "$(gettext "Please make sure you really trust them.")"
1066 check_source_integrity() {
1067 if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
1068 warning "$(gettext "Skipping all source file integrity checks.")"
1069 elif (( SKIPCHECKSUMS )); then
1070 warning "$(gettext "Skipping verification of source file checksums.")"
1071 check_pgpsigs
1072 elif (( SKIPPGPCHECK )); then
1073 warning "$(gettext "Skipping verification of source file PGP signatures.")"
1074 check_checksums
1075 else
1076 check_checksums
1077 check_pgpsigs
1081 extract_sources() {
1082 msg "$(gettext "Extracting Sources...")"
1083 local netfile
1084 for netfile in "${source[@]}"; do
1085 local file=$(get_filename "$netfile")
1086 if in_array "$file" "${noextract[@]}"; then
1087 #skip source files in the noextract=() array
1088 # these are marked explicitly to NOT be extracted
1089 continue
1093 # fix flyspray #6246
1094 local file_type=$(file -bizL "$file")
1095 local ext=${file##*.}
1096 local cmd=''
1097 case "$file_type" in
1098 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
1099 cmd="bsdtar" ;;
1100 *application/x-gzip*)
1101 case "$ext" in
1102 gz|z|Z) cmd="gzip" ;;
1103 *) continue;;
1104 esac ;;
1105 *application/x-bzip*)
1106 case "$ext" in
1107 bz2|bz) cmd="bzip2" ;;
1108 *) continue;;
1109 esac ;;
1110 *application/x-xz*)
1111 case "$ext" in
1112 xz) cmd="xz" ;;
1113 *) continue;;
1114 esac ;;
1116 # See if bsdtar can recognize the file
1117 if bsdtar -tf "$file" -q '*' &>/dev/null; then
1118 cmd="bsdtar"
1119 else
1120 continue
1121 fi ;;
1122 esac
1124 local ret=0
1125 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
1126 if [[ $cmd = "bsdtar" ]]; then
1127 $cmd -xf "$file" || ret=$?
1128 else
1129 rm -f -- "${file%.*}"
1130 $cmd -dcf "$file" > "${file%.*}" || ret=$?
1132 if (( ret )); then
1133 error "$(gettext "Failed to extract %s")" "$file"
1134 plain "$(gettext "Aborting...")"
1135 exit 1
1137 done
1139 if (( EUID == 0 )); then
1140 # change perms of all source files to root user & root group
1141 chown -R 0:0 "$srcdir"
1145 error_function() {
1146 if [[ -p $logpipe ]]; then
1147 rm "$logpipe"
1149 # first exit all subshells, then print the error
1150 if (( ! BASH_SUBSHELL )); then
1151 error "$(gettext "A failure occurred in %s().")" "$1"
1152 plain "$(gettext "Aborting...")"
1153 remove_deps
1155 exit 2 # $E_BUILD_FAILED
1158 cd_safe() {
1159 if ! cd "$1"; then
1160 error "$(gettext "Failed to change to directory %s")" "$1"
1161 plain "$(gettext "Aborting...")"
1162 exit 1
1166 source_safe() {
1167 shopt -u extglob
1168 if ! source "$@"; then
1169 error "$(gettext "Failed to source %s")" "$1"
1170 exit 1
1172 shopt -s extglob
1175 run_function_safe() {
1176 local restoretrap
1178 set -e
1179 set -E
1181 restoretrap=$(trap -p ERR)
1182 trap 'error_function $pkgfunc' ERR
1184 run_function "$1"
1186 eval $restoretrap
1188 set +E
1189 set +e
1192 run_function() {
1193 if [[ -z $1 ]]; then
1194 return 1
1196 local pkgfunc="$1"
1198 # clear user-specified buildflags if requested
1199 if check_option "buildflags" "n"; then
1200 unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
1203 # clear user-specified makeflags if requested
1204 if check_option "makeflags" "n"; then
1205 unset MAKEFLAGS
1208 msg "$(gettext "Starting %s()...")" "$pkgfunc"
1209 cd_safe "$srcdir"
1211 # ensure all necessary build variables are exported
1212 export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
1213 # save our shell options so pkgfunc() can't override what we need
1214 local shellopts=$(shopt -p)
1216 local ret=0
1217 if (( LOGGING )); then
1218 local fullver=$(get_full_version)
1219 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
1220 if [[ -f $BUILDLOG ]]; then
1221 local i=1
1222 while true; do
1223 if [[ -f $BUILDLOG.$i ]]; then
1224 i=$(($i +1))
1225 else
1226 break
1228 done
1229 mv "$BUILDLOG" "$BUILDLOG.$i"
1232 # ensure overridden package variables survive tee with split packages
1233 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
1234 mkfifo "$logpipe"
1235 tee "$BUILDLOG" < "$logpipe" &
1236 local teepid=$!
1238 $pkgfunc &>"$logpipe"
1240 wait $teepid
1241 rm "$logpipe"
1242 else
1243 $pkgfunc 2>&1
1245 # reset our shell options
1246 eval "$shellopts"
1249 run_prepare() {
1250 run_function_safe "prepare"
1253 run_build() {
1254 # use distcc if it is requested (check buildenv and PKGBUILD opts)
1255 if check_buildenv "distcc" "y" && ! check_option "distc" "n"; then
1256 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
1257 export DISTCC_HOSTS
1260 # use ccache if it is requested (check buildenv and PKGBUILD opts)
1261 if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
1262 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
1265 run_function_safe "build"
1268 run_check() {
1269 run_function_safe "check"
1272 run_package() {
1273 local pkgfunc
1274 if [[ -z $1 ]]; then
1275 pkgfunc="package"
1276 else
1277 pkgfunc="package_$1"
1280 run_function_safe "$pkgfunc"
1283 tidy_install() {
1284 cd_safe "$pkgdir"
1285 msg "$(gettext "Tidying install...")"
1287 if check_option "docs" "n" && [[ -n ${DOC_DIRS[*]} ]]; then
1288 msg2 "$(gettext "Removing doc files...")"
1289 rm -rf -- ${DOC_DIRS[@]}
1292 if check_option "purge" "y" && [[ -n ${PURGE_TARGETS[*]} ]]; then
1293 msg2 "$(gettext "Purging unwanted files...")"
1294 local pt
1295 for pt in "${PURGE_TARGETS[@]}"; do
1296 if [[ ${pt} = "${pt//\/}" ]]; then
1297 find . ! -type d -name "${pt}" -exec rm -f -- '{}' \;
1298 else
1299 rm -f ${pt}
1301 done
1304 if check_option "zipman" "y" && [[ -n ${MAN_DIRS[*]} ]]; then
1305 msg2 "$(gettext "Compressing man and info pages...")"
1306 local file files inode link
1307 while read -rd ' ' inode; do
1308 read file
1309 find ${MAN_DIRS[@]} -type l 2>/dev/null |
1310 while read link ; do
1311 if [[ "${file}" -ef "${link}" ]] ; then
1312 rm -f "$link" "${link}.gz"
1313 if [[ ${file%/*} = ${link%/*} ]]; then
1314 ln -s -- "${file##*/}.gz" "${link}.gz"
1315 else
1316 ln -s -- "/${file}.gz" "${link}.gz"
1319 done
1320 if [[ -z ${files[$inode]} ]]; then
1321 files[$inode]=$file
1322 gzip -9 -f "$file"
1323 else
1324 rm -f "$file"
1325 ln "${files[$inode]}.gz" "${file}.gz"
1326 chmod 644 "${file}.gz"
1328 done < <(find ${MAN_DIRS[@]} -type f \! -name "*.gz" \! -name "*.bz2" \
1329 -exec @INODECMD@ '{}' + 2>/dev/null)
1332 if check_option "strip" "y"; then
1333 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1334 # make sure library stripping variables are defined to prevent excess stripping
1335 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1336 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1337 local binary
1338 find . -type f -perm -u+w -print0 2>/dev/null | while read -d '' binary ; do
1339 case "$(file -bi "$binary")" in
1340 *application/x-sharedlib*) # Libraries (.so)
1341 strip $STRIP_SHARED "$binary";;
1342 *application/x-archive*) # Libraries (.a)
1343 strip $STRIP_STATIC "$binary";;
1344 *application/x-executable*) # Binaries
1345 strip $STRIP_BINARIES "$binary";;
1346 esac
1347 done
1350 if check_option "libtool" "n"; then
1351 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1352 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1355 if check_option "emptydirs" "n"; then
1356 msg2 "$(gettext "Removing empty directories...")"
1357 find . -depth -type d -exec rmdir '{}' + 2>/dev/null
1360 if check_option "upx" "y"; then
1361 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1362 local binary
1363 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1364 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1365 upx $UPXFLAGS "$binary" &>/dev/null ||
1366 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1368 done
1372 find_libdepends() {
1373 local d sodepends;
1375 sodepends=0;
1376 for d in "${depends[@]}"; do
1377 if [[ $d = *.so ]]; then
1378 sodepends=1;
1379 break;
1381 done
1383 if (( sodepends == 0 )); then
1384 printf '%s\n' "${depends[@]}"
1385 return;
1388 local libdeps filename soarch sofile soname soversion;
1389 declare -A libdeps;
1391 while read filename; do
1392 # get architecture of the file; if soarch is empty it's not an ELF binary
1393 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1394 [[ -n "$soarch" ]] || continue
1396 # process all libraries needed by the binary
1397 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1399 # extract the library name: libfoo.so
1400 soname="${sofile%.so?(+(.+([0-9])))}".so
1401 # extract the major version: 1
1402 soversion="${sofile##*\.so\.}"
1404 if [[ ${libdeps[$soname]} ]]; then
1405 if [[ ${libdeps[$soname]} != *${soversion}-${soarch}* ]]; then
1406 libdeps[$soname]+=" ${soversion}-${soarch}"
1408 else
1409 libdeps[$soname]="${soversion}-${soarch}"
1411 done
1412 done < <(find "$pkgdir" -type f -perm -u+x)
1414 local libdepends v
1415 for d in "${depends[@]}"; do
1416 case "$d" in
1417 *.so)
1418 if [[ ${libdeps[$d]} ]]; then
1419 for v in ${libdeps[$d]}; do
1420 libdepends+=("$d=$v")
1421 done
1422 else
1423 warning "$(gettext "Library listed in %s is not required by any files: %s")" "'depends'" "$d"
1424 libdepends+=("$d")
1428 libdepends+=("$d")
1430 esac
1431 done
1433 printf '%s\n' "${libdepends[@]}"
1437 find_libprovides() {
1438 local p libprovides missing
1439 for p in "${provides[@]}"; do
1440 missing=0
1441 case "$p" in
1442 *.so)
1443 mapfile -t filename < <(find "$pkgdir" -type f -name $p\*)
1444 if [[ $filename ]]; then
1445 # packages may provide multiple versions of the same library
1446 for fn in "${filename[@]}"; do
1447 # check if we really have a shared object
1448 if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1449 # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1)
1450 local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1451 if [[ -z "$sofile" ]]; then
1452 warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p"
1453 libprovides+=("$p")
1454 continue
1457 # get the library architecture (32 or 64 bit)
1458 local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1460 # extract the library major version
1461 local soversion="${sofile##*\.so\.}"
1463 libprovides+=("${p}=${soversion}-${soarch}")
1464 else
1465 warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p"
1466 libprovides+=("$p")
1468 done
1469 else
1470 libprovides+=("$p")
1471 missing=1
1475 libprovides+=("$p")
1477 esac
1479 if (( missing )); then
1480 warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p"
1482 done
1484 printf '%s\n' "${libprovides[@]}"
1487 check_license() {
1488 # TODO maybe remove this at some point
1489 # warn if license array is not present or empty
1490 if [[ -z $license ]]; then
1491 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1492 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1496 write_pkginfo() {
1497 local builddate=$(date -u "+%s")
1498 if [[ -n $PACKAGER ]]; then
1499 local packager="$PACKAGER"
1500 else
1501 local packager="Unknown Packager"
1504 # btrfs's delayed allocation causes the stat buffers from the kernel to "lie"
1505 # to us momentarily and report 0 blocks allocated (which is how du calculates
1506 # size). Sleeping for a second here is about the dirtiest thing possible,
1507 # but avoids reporting entirely bogus install sizes.
1508 sleep 1
1509 local size="$(@DUPATH@ -sk)"
1510 size="$(( ${size%%[^0-9]*} * 1024 ))"
1512 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1513 echo "# Generated by makepkg $makepkg_version"
1514 if (( INFAKEROOT )); then
1515 echo "# using $(fakeroot -v)"
1517 echo "# $(LC_ALL=C date -u)"
1518 printf "pkgname = %s\n" "$1"
1519 (( SPLITPKG )) && echo pkgbase = $pkgbase
1520 echo "pkgver = $(get_full_version)"
1521 printf "pkgdesc = %s\n" "$pkgdesc"
1522 printf "url = %s\n" "$url"
1523 printf "builddate = %s\n" "$builddate"
1524 printf "packager = %s\n" "$packager"
1525 printf "size = %s\n" "$size"
1526 printf "arch = %s\n" "$pkgarch"
1528 mapfile -t provides < <(find_libprovides)
1529 mapfile -t depends < <(find_libdepends)
1531 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1532 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1533 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1534 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1535 [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
1536 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1537 [[ $depends ]] && printf "depend = %s\n" "${depends[@]}"
1538 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1539 [[ $makedepends ]] && printf "makedepend = %s\n" "${makedepends[@]}"
1540 [[ $checkdepends ]] && printf "checkdepend = %s\n" "${checkdepends[@]}"
1542 local it
1543 for it in "${packaging_options[@]}"; do
1544 check_option "$it" "y"
1545 case $? in
1547 printf "makepkgopt = %s\n" "$it"
1550 printf "makepkgopt = %s\n" "!$it"
1552 esac
1553 done
1555 check_license
1558 check_package() {
1559 cd_safe "$pkgdir"
1561 # check existence of backup files
1562 local file
1563 for file in "${backup[@]}"; do
1564 if [[ ! -f $file ]]; then
1565 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1567 done
1569 # check for references to the build and package directory
1570 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1571 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1573 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1574 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1579 create_package() {
1580 if [[ ! -d $pkgdir ]]; then
1581 error "$(gettext "Missing %s directory.")" "pkg/"
1582 plain "$(gettext "Aborting...")"
1583 exit 1 # $E_MISSING_PKGDIR
1586 check_package
1588 cd_safe "$pkgdir"
1589 msg "$(gettext "Creating package...")"
1591 local nameofpkg
1592 if [[ -z $1 ]]; then
1593 nameofpkg="$pkgname"
1594 else
1595 nameofpkg="$1"
1598 pkgarch=$(get_pkg_arch)
1600 write_pkginfo $nameofpkg > .PKGINFO
1602 local comp_files=('.PKGINFO')
1604 # check for changelog/install files
1605 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1606 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1608 if [[ -n ${!orig} ]]; then
1609 msg2 "$(gettext "Adding %s file...")" "$orig"
1610 cp "$startdir/${!orig}" "$dest"
1611 chmod 644 "$dest"
1612 comp_files+=("$dest")
1614 done
1616 # tar it up
1617 msg2 "$(gettext "Compressing package...")"
1619 local fullver=$(get_full_version)
1620 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${pkgarch}${PKGEXT}"
1621 local ret=0
1623 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1624 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1626 # when fileglobbing, we want * in an empty directory to expand to
1627 # the null string rather than itself
1628 shopt -s nullglob
1629 # TODO: Maybe this can be set globally for robustness
1630 shopt -s -o pipefail
1631 # bsdtar's gzip compression always saves the time stamp, making one
1632 # archive created using the same command line distinct from another.
1633 # Disable bsdtar compression and use gzip -n for now.
1634 bsdtar -cf - "${comp_files[@]}" * |
1635 case "$PKGEXT" in
1636 *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;;
1637 *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;;
1638 *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;;
1639 *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;;
1640 *tar) cat ;;
1641 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1642 "$PKGEXT"; cat ;;
1643 esac > "${pkg_file}" || ret=$?
1645 shopt -u nullglob
1646 shopt -u -o pipefail
1648 if (( ret )); then
1649 error "$(gettext "Failed to create package file.")"
1650 exit 1 # TODO: error code
1653 create_signature "$pkg_file"
1655 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1656 rm -f "${pkg_file/$PKGDEST/$startdir}"
1657 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1658 ret=$?
1659 if [[ -f $pkg_file.sig ]]; then
1660 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1661 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1665 if (( ret )); then
1666 warning "$(gettext "Failed to create symlink to package file.")"
1670 create_signature() {
1671 if [[ $SIGNPKG != 'y' ]]; then
1672 return
1674 local ret=0
1675 local filename="$1"
1676 msg "$(gettext "Signing package...")"
1678 local SIGNWITHKEY=""
1679 if [[ -n $GPGKEY ]]; then
1680 SIGNWITHKEY="-u ${GPGKEY}"
1682 # The signature will be generated directly in ascii-friendly format
1683 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1686 if (( ! ret )); then
1687 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1688 else
1689 warning "$(gettext "Failed to sign package file.")"
1693 create_srcpackage() {
1694 local ret=0
1695 msg "$(gettext "Creating source package...")"
1696 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1697 mkdir "${srclinks}"/${pkgbase}
1699 check_license
1701 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1702 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1704 local file
1705 for file in "${source[@]}"; do
1706 if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then
1707 local absfile
1708 absfile=$(get_filepath "$file") || missing_source_file "$file"
1709 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1710 ln -s "$absfile" "$srclinks/$pkgbase"
1712 done
1714 local i
1715 for i in 'changelog' 'install'; do
1716 local file
1717 while read -r file; do
1718 # evaluate any bash variables used
1719 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1720 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1721 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1722 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1724 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1725 done
1727 local TAR_OPT
1728 case "$SRCEXT" in
1729 *tar.gz) TAR_OPT="z" ;;
1730 *tar.bz2) TAR_OPT="j" ;;
1731 *tar.xz) TAR_OPT="J" ;;
1732 *tar.Z) TAR_OPT="Z" ;;
1733 *tar) TAR_OPT="" ;;
1734 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1735 "$SRCEXT" ;;
1736 esac
1738 local fullver=$(get_full_version)
1739 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1741 # tar it up
1742 msg2 "$(gettext "Compressing source package...")"
1743 cd_safe "${srclinks}"
1744 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1745 error "$(gettext "Failed to create source package file.")"
1746 exit 1 # TODO: error code
1749 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1750 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1751 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1752 ret=$?
1755 if (( ret )); then
1756 warning "$(gettext "Failed to create symlink to source package file.")"
1759 cd_safe "${startdir}"
1760 rm -rf "${srclinks}"
1763 install_package() {
1764 (( ! INSTALL )) && return
1766 if (( ! SPLITPKG )); then
1767 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1768 else
1769 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1772 local fullver pkgarch pkg pkglist
1773 (( ASDEPS )) && pkglist+=('--asdeps')
1775 for pkg in ${pkgname[@]}; do
1776 fullver=$(get_full_version $pkg)
1777 pkgarch=$(get_pkg_arch $pkg)
1778 pkglist+=("$PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT}")
1779 done
1781 if ! run_pacman -U ${pkglist[@]}; then
1782 warning "$(gettext "Failed to install built package(s).")"
1783 return 0
1787 check_sanity() {
1788 # check for no-no's in the build script
1789 local i
1790 local ret=0
1791 for i in 'pkgname' 'pkgrel'; do
1792 if [[ -z ${!i} ]]; then
1793 error "$(gettext "%s is not allowed to be empty.")" "$i"
1794 ret=1
1796 done
1798 for i in "${pkgname[@]}"; do
1799 if [[ ${i:0:1} = "-" ]]; then
1800 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1801 ret=1
1803 if [[ $i = *[^[:alnum:]+_.@-]* ]]; then
1804 error "$(gettext "%s contains invalid characters: '%s'")" \
1805 'pkgname' "${pkgname//[[:alnum:]+_.@-]}"
1806 ret=1
1808 done
1810 if [[ ${pkgbase:0:1} = "-" ]]; then
1811 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1812 ret=1
1815 if ! declare -f pkgver >/dev/null; then
1816 check_pkgver || ret=1
1819 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1820 while IFS='=' read -r _ i; do
1821 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1822 if [[ $i != +([0-9])?(.+([0-9])) ]]; then
1823 error "$(gettext "%s must be a decimal.")" "pkgrel"
1824 return 1
1826 done || ret=1
1828 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1829 while IFS='=' read -r _ i; do
1830 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1831 if [[ $i != *([[:digit:]]) ]]; then
1832 error "$(gettext "%s must be an integer.")" "epoch"
1833 return 1
1835 done || ret=1
1837 if [[ $arch != 'any' ]]; then
1838 if ! in_array $CARCH ${arch[@]}; then
1839 if (( ! IGNOREARCH )); then
1840 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1841 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1842 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1843 ret=1
1848 if (( ${#pkgname[@]} > 1 )); then
1849 for i in ${pkgname[@]}; do
1850 local arch_list=""
1851 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1852 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1853 if ! in_array $CARCH ${arch_list[@]}; then
1854 if (( ! IGNOREARCH )); then
1855 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1856 ret=1
1860 done
1863 local provides_list=()
1864 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1865 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1866 for i in ${provides_list[@]}; do
1867 if [[ $i == *['<>']* ]]; then
1868 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1869 ret=1
1871 done
1873 local backup_list=()
1874 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1875 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1876 for i in "${backup_list[@]}"; do
1877 if [[ ${i:0:1} = "/" ]]; then
1878 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1879 ret=1
1881 done
1883 local optdepends_list=()
1884 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1885 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1886 for i in "${optdepends_list[@]}"; do
1887 local pkg=${i%%:[[:space:]]*}
1888 # the '-' character _must_ be first or last in the character range
1889 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1890 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1891 ret=1
1893 done
1895 for i in 'changelog' 'install'; do
1896 local file
1897 while read -r file; do
1898 # evaluate any bash variables used
1899 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1900 if [[ $file && ! -f $file ]]; then
1901 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1902 ret=1
1904 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1905 done
1907 local valid_options=1
1908 local known kopt options_list
1909 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1910 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1911 for i in ${options_list[@]}; do
1912 known=0
1913 # check if option matches a known option or its inverse
1914 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1915 if [[ ${i} = "${kopt}" || ${i} = "!${kopt}" ]]; then
1916 known=1
1918 done
1919 if (( ! known )); then
1920 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1921 valid_options=0
1923 done
1924 if (( ! valid_options )); then
1925 ret=1
1928 if (( ${#pkgname[@]} > 1 )); then
1929 for i in ${pkgname[@]}; do
1930 if ! declare -f package_${i} >/dev/null; then
1931 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1932 ret=1
1934 done
1937 for i in ${PKGLIST[@]}; do
1938 if ! in_array $i ${pkgname[@]}; then
1939 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1940 ret=1
1942 done
1944 return $ret
1947 check_pkgver() {
1948 local ret=0
1950 if [[ -z ${pkgver} ]]; then
1951 error "$(gettext "%s is not allowed to be empty.")" "pkgver"
1952 ret=1
1955 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1956 while IFS='=' read -r _ i; do
1957 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1958 if [[ $i = *[[:space:]:-]* ]]; then
1959 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
1960 return 1
1962 done || ret=1
1964 return $ret
1967 check_software() {
1968 # check for needed software
1969 local ret=0
1971 # check for sudo if we will need it during makepkg execution
1972 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1973 if ! type -p sudo >/dev/null; then
1974 warning "$(gettext "Cannot find the %s binary. Will use %s to acquire root privileges.")" "sudo" "su"
1978 # fakeroot - building as non-root user
1979 if check_buildenv "fakeroot" "y" && (( EUID > 0 )); then
1980 if ! type -p fakeroot >/dev/null; then
1981 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
1982 ret=1
1986 # gpg - package signing
1987 if [[ $SIGNPKG == 'y' ]] || { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; }; then
1988 if ! type -p gpg >/dev/null; then
1989 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
1990 ret=1
1994 # gpg - source verification
1995 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
1996 if ! type -p gpg >/dev/null; then
1997 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
1998 ret=1
2002 # openssl - checksum operations
2003 if (( ! SKIPCHECKSUMS )); then
2004 if ! type -p openssl >/dev/null; then
2005 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
2006 ret=1
2010 # upx - binary compression
2011 if check_option "upx" "y"; then
2012 if ! type -p upx >/dev/null; then
2013 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
2014 ret=1
2018 # distcc - compilation with distcc
2019 if check_buildenv "distcc" "y" && ! check_option "distcc" "n" ]]; then
2020 if ! type -p distcc >/dev/null; then
2021 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
2022 ret=1
2026 # ccache - compilation with ccache
2027 if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
2028 if ! type -p ccache >/dev/null; then
2029 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
2030 ret=1
2034 # strip - strip symbols from binaries/libraries
2035 if check_option "strip" "y"; then
2036 if ! type -p strip >/dev/null; then
2037 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
2038 ret=1
2042 # gzip - compressig man and info pages
2043 if check_option "zipman" "y"; then
2044 if ! type -p gzip >/dev/null; then
2045 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
2046 ret=1
2050 return $ret
2053 backup_package_variables() {
2054 local var
2055 for var in ${splitpkg_overrides[@]}; do
2056 local indirect="${var}_backup"
2057 eval "${indirect}=(\"\${$var[@]}\")"
2058 done
2061 restore_package_variables() {
2062 local var
2063 for var in ${splitpkg_overrides[@]}; do
2064 local indirect="${var}_backup"
2065 if [[ -n ${!indirect} ]]; then
2066 eval "${var}=(\"\${$indirect[@]}\")"
2067 else
2068 unset ${var}
2070 done
2073 run_split_packaging() {
2074 local pkgname_backup=${pkgname[@]}
2075 for pkgname in ${pkgname_backup[@]}; do
2076 pkgdir="$pkgdir/$pkgname"
2077 mkdir -p "$pkgdir"
2078 chmod a-s "$pkgdir"
2079 backup_package_variables
2080 run_package $pkgname
2081 tidy_install
2082 create_package $pkgname
2083 restore_package_variables
2084 pkgdir="${pkgdir%/*}"
2085 done
2086 pkgname=${pkgname_backup[@]}
2089 # Canonicalize a directory path if it exists
2090 canonicalize_path() {
2091 local path="$1";
2093 if [[ -d $path ]]; then
2095 cd_safe "$path"
2096 pwd -P
2098 else
2099 printf "%s\n" "$path"
2103 m4_include(library/parseopts.sh)
2105 usage() {
2106 printf "makepkg (pacman) %s\n" "$makepkg_version"
2107 echo
2108 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
2109 echo
2110 printf -- "$(gettext "Options:")\n"
2111 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
2112 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
2113 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
2114 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
2115 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
2116 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
2117 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
2118 printf -- "$(gettext " -i, --install Install package after successful build")\n"
2119 printf -- "$(gettext " -L, --log Log package build process")\n"
2120 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
2121 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
2122 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
2123 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
2124 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
2125 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
2126 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
2127 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
2128 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
2129 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
2130 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
2131 printf -- "$(gettext " --holdver Do not update VCS sources")\n"
2132 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
2133 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
2134 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
2135 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
2136 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
2137 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
2138 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
2139 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
2140 echo
2141 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
2142 echo
2143 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
2144 printf -- "$(gettext " --asdeps Install packages as non-explicitly installed")\n"
2145 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
2146 echo
2147 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
2148 echo
2151 version() {
2152 printf "makepkg (pacman) %s\n" "$makepkg_version"
2153 printf -- "$(gettext "\
2154 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
2155 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
2156 This is free software; see the source for copying conditions.\n\
2157 There is NO WARRANTY, to the extent permitted by law.\n")"
2160 # PROGRAM START
2162 # determine whether we have gettext; make it a no-op if we do not
2163 if ! type -p gettext >/dev/null; then
2164 gettext() {
2165 printf "%s\n" "$@"
2169 ARGLIST=("$@")
2171 # Parse Command Line Options.
2172 OPT_SHORT="AcdefFghiLmop:rRsSV"
2173 OPT_LONG=('allsource' 'asroot' 'check' 'clean' 'config:' 'force' 'geninteg'
2174 'help' 'holdver' 'ignorearch' 'install' 'key:' 'log' 'nobuild' 'nocolor'
2175 'nocheck' 'nodeps' 'noextract' 'nosign' 'pkg:' 'repackage' 'rmdeps'
2176 'skipchecksums' 'skipinteg' 'skippgpcheck' 'skippgpcheck' 'sign'
2177 'source' 'syncdeps' 'version')
2179 # Pacman Options
2180 OPT_LONG+=('asdeps' 'noconfirm' 'noprogressbar')
2182 if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
2183 exit 1 # E_INVALID_OPTION;
2185 set -- "${OPTRET[@]}"
2186 unset OPT_SHORT OPT_LONG OPTRET
2188 while true; do
2189 case "$1" in
2190 # Pacman Options
2191 --asdeps) ASDEPS=1;;
2192 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
2193 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
2195 # Makepkg Options
2196 --allsource) SOURCEONLY=2 ;;
2197 --asroot) ASROOT=1 ;;
2198 -A|--ignorearch) IGNOREARCH=1 ;;
2199 -c|--clean) CLEANUP=1 ;;
2200 --check) RUN_CHECK='y' ;;
2201 --config) shift; MAKEPKG_CONF=$1 ;;
2202 -d|--nodeps) NODEPS=1 ;;
2203 -e|--noextract) NOEXTRACT=1 ;;
2204 -f|--force) FORCE=1 ;;
2205 -F) INFAKEROOT=1 ;;
2206 -g|--geninteg) GENINTEG=1 ;;
2207 --holdver) HOLDVER=1 ;;
2208 -i|--install) INSTALL=1 ;;
2209 --key) shift; GPGKEY=$1 ;;
2210 -L|--log) LOGGING=1 ;;
2211 -m|--nocolor) USE_COLOR='n' ;;
2212 --nocheck) RUN_CHECK='n' ;;
2213 --nosign) SIGNPKG='n' ;;
2214 -o|--nobuild) NOBUILD=1 ;;
2215 -p) shift; BUILDFILE=$1 ;;
2216 --pkg) shift; IFS=, read -ra p <<<"$1"; PKGLIST+=("${p[@]}"); unset p ;;
2217 -r|--rmdeps) RMDEPS=1 ;;
2218 -R|--repackage) REPKG=1 ;;
2219 --skipchecksums) SKIPCHECKSUMS=1 ;;
2220 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
2221 --skippgpcheck) SKIPPGPCHECK=1;;
2222 --sign) SIGNPKG='y' ;;
2223 -s|--syncdeps) DEP_BIN=1 ;;
2224 -S|--source) SOURCEONLY=1 ;;
2226 -h|--help) usage; exit 0 ;; # E_OK
2227 -V|--version) version; exit 0 ;; # E_OK
2229 --) OPT_IND=0; shift; break 2;;
2230 esac
2231 shift
2232 done
2234 # setup signal traps
2235 trap 'clean_up' 0
2236 for signal in TERM HUP QUIT; do
2237 trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
2238 done
2239 trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT
2240 trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR
2242 # preserve environment variables and canonicalize path
2243 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
2244 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
2245 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
2246 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
2247 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
2248 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
2249 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
2250 [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
2252 # default config is makepkg.conf
2253 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
2255 # Source the config file; fail if it is not found
2256 if [[ -r $MAKEPKG_CONF ]]; then
2257 source_safe "$MAKEPKG_CONF"
2258 else
2259 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
2260 plain "$(gettext "Aborting...")"
2261 exit 1 # $E_CONFIG_ERROR
2264 # Source user-specific makepkg.conf overrides, but only if no override config
2265 # file was specified
2266 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
2267 source_safe ~/.makepkg.conf
2270 # set pacman command if not already defined
2271 PACMAN=${PACMAN:-pacman}
2273 # check if messages are to be printed using color
2274 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2275 if [[ -t 2 && ! $USE_COLOR = "n" ]] && check_buildenv "color" "y"; then
2276 # prefer terminal safe colored and bold text when tput is supported
2277 if tput setaf 0 &>/dev/null; then
2278 ALL_OFF="$(tput sgr0)"
2279 BOLD="$(tput bold)"
2280 BLUE="${BOLD}$(tput setaf 4)"
2281 GREEN="${BOLD}$(tput setaf 2)"
2282 RED="${BOLD}$(tput setaf 1)"
2283 YELLOW="${BOLD}$(tput setaf 3)"
2284 else
2285 ALL_OFF="\e[1;0m"
2286 BOLD="\e[1;1m"
2287 BLUE="${BOLD}\e[1;34m"
2288 GREEN="${BOLD}\e[1;32m"
2289 RED="${BOLD}\e[1;31m"
2290 YELLOW="${BOLD}\e[1;33m"
2293 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2295 # override settings with an environment variable for batch processing
2296 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2297 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2298 if [[ ! -d $BUILDDIR ]]; then
2299 if ! mkdir -p "$BUILDDIR"; then
2300 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2301 plain "$(gettext "Aborting...")"
2302 exit 1
2304 chmod a-s "$BUILDDIR"
2306 if [[ ! -w $BUILDDIR ]]; then
2307 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2308 plain "$(gettext "Aborting...")"
2309 exit 1
2312 PKGDEST=${_PKGDEST:-$PKGDEST}
2313 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2314 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2315 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2316 plain "$(gettext "Aborting...")"
2317 exit 1
2320 SRCDEST=${_SRCDEST:-$SRCDEST}
2321 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2322 if [[ ! -w $SRCDEST ]] ; then
2323 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2324 plain "$(gettext "Aborting...")"
2325 exit 1
2328 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2329 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2330 if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then
2331 error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
2332 plain "$(gettext "Aborting...")"
2333 exit 1
2336 PKGEXT=${_PKGEXT:-$PKGEXT}
2337 SRCEXT=${_SRCEXT:-$SRCEXT}
2338 GPGKEY=${_GPGKEY:-$GPGKEY}
2339 PACKAGER=${_PACKAGER:-$PACKAGER}
2341 if (( ! INFAKEROOT )); then
2342 if (( EUID == 0 && ! ASROOT )); then
2343 # Warn those who like to live dangerously.
2344 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2345 catastrophic damage to your system. If you wish to run as root, please\n\
2346 use the %s option.")" "makepkg" "--asroot"
2347 exit 1 # $E_USER_ABORT
2348 elif (( EUID > 0 && ASROOT )); then
2349 # Warn those who try to use the --asroot option when they are not root
2350 error "$(gettext "The %s option is meant for the root user only. Please\n\
2351 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2352 exit 1 # $E_USER_ABORT
2353 elif (( EUID > 0 )) && ! check_buildenv "fakeroot" "y"; then
2354 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2355 ownership of the packaged files. Try using the %s environment by\n\
2356 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2357 sleep 1
2359 else
2360 if [[ -z $FAKEROOTKEY ]]; then
2361 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2362 exit 1 # TODO: error code
2366 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2367 unset md5sums replaces depends conflicts backup source install changelog build
2368 unset makedepends optdepends options noextract
2370 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2371 if [[ ! -f $BUILDFILE ]]; then
2372 if [[ -t 0 ]]; then
2373 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2374 exit 1
2375 else
2376 # PKGBUILD passed through a pipe
2377 BUILDFILE=/dev/stdin
2378 source_safe "$BUILDFILE"
2380 else
2381 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2382 if [[ -n $crlftest ]]; then
2383 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2384 exit 1
2387 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2388 BUILDFILE="$startdir/$BUILDFILE"
2390 source_safe "$BUILDFILE"
2393 # set defaults if they weren't specified in buildfile
2394 pkgbase=${pkgbase:-${pkgname[0]}}
2395 epoch=${epoch:-0}
2397 if [[ $BUILDDIR = "$startdir" ]]; then
2398 srcdir="$BUILDDIR/src"
2399 pkgdir="$BUILDDIR/pkg"
2400 else
2401 srcdir="$BUILDDIR/$pkgbase/src"
2402 pkgdir="$BUILDDIR/$pkgbase/pkg"
2405 if (( GENINTEG )); then
2406 mkdir -p "$srcdir"
2407 chmod a-s "$srcdir"
2408 cd_safe "$srcdir"
2409 download_sources fast
2410 generate_checksums
2411 exit 0 # $E_OK
2414 # check the PKGBUILD for some basic requirements
2415 check_sanity || exit 1
2417 # check we have the software required to process the PKGBUILD
2418 check_software || exit 1
2420 if (( ${#pkgname[@]} > 1 )); then
2421 SPLITPKG=1
2424 # test for available PKGBUILD functions
2425 if declare -f prepare >/dev/null; then
2426 PREPAREFUNC=1
2428 if declare -f build >/dev/null; then
2429 BUILDFUNC=1
2431 if declare -f check >/dev/null; then
2432 # "Hide" check() function if not going to be run
2433 if [[ $RUN_CHECK = 'y' ]] || { ! check_buildenv "check" "n" && [[ $RUN_CHECK != "n" ]]; }; then
2434 CHECKFUNC=1
2437 if declare -f package >/dev/null; then
2438 PKGFUNC=1
2439 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2440 SPLITPKG=1
2443 if [[ -n "${PKGLIST[@]}" ]]; then
2444 unset pkgname
2445 pkgname=("${PKGLIST[@]}")
2448 # check if gpg signature is to be created and if signing key is valid
2449 if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then
2450 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2451 if [[ ! -z $GPGKEY ]]; then
2452 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2453 else
2454 error "$(gettext "There is no key in your keyring.")"
2456 exit 1
2461 if (( ! SPLITPKG )); then
2462 fullver=$(get_full_version)
2463 pkgarch=$(get_pkg_arch)
2464 if [[ -f $PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT} ]] \
2465 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2466 if (( INSTALL )); then
2467 warning "$(gettext "A package has already been built, installing existing package...")"
2468 install_package
2469 exit $?
2470 else
2471 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2472 exit 1
2475 else
2476 allpkgbuilt=1
2477 somepkgbuilt=0
2478 for pkg in ${pkgname[@]}; do
2479 fullver=$(get_full_version $pkg)
2480 pkgarch=$(get_pkg_arch $pkg)
2481 if [[ -f $PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT} ]]; then
2482 somepkgbuilt=1
2483 else
2484 allpkgbuilt=0
2486 done
2487 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2488 if (( allpkgbuilt )); then
2489 if (( INSTALL )); then
2490 warning "$(gettext "The package group has already been built, installing existing packages...")"
2491 install_package
2492 exit $?
2493 else
2494 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2495 exit 1
2498 if (( somepkgbuilt )); then
2499 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2500 exit 1
2503 unset allpkgbuilt somepkgbuilt
2506 # Run the bare minimum in fakeroot
2507 if (( INFAKEROOT )); then
2508 if (( SOURCEONLY )); then
2509 create_srcpackage
2510 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2511 exit 0 # $E_OK
2514 if (( ! SPLITPKG )); then
2515 if (( ! PKGFUNC )); then
2516 if (( ! REPKG )); then
2517 if (( BUILDFUNC )); then
2518 run_build
2519 (( CHECKFUNC )) && run_check
2520 tidy_install
2522 else
2523 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2524 plain "$(gettext "File permissions may not be preserved.")"
2526 else
2527 run_package
2528 tidy_install
2530 create_package
2531 else
2532 run_split_packaging
2535 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2536 exit 0 # $E_OK
2539 fullver=$(get_full_version)
2540 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2542 # if we are creating a source-only package, go no further
2543 if (( SOURCEONLY )); then
2544 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2545 && (( ! FORCE )); then
2546 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2547 exit 1
2550 # Get back to our src directory so we can begin with sources.
2551 mkdir -p "$srcdir"
2552 chmod a-s "$srcdir"
2553 cd_safe "$srcdir"
2554 if (( SOURCEONLY == 2 )); then
2555 download_sources
2556 elif ( (( ! SKIPCHECKSUMS )) || \
2557 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ); then
2558 download_sources fast
2560 check_source_integrity
2561 cd_safe "$startdir"
2563 # if we are root or if fakeroot is not enabled, then we don't use it
2564 if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
2565 create_srcpackage
2566 else
2567 enter_fakeroot
2570 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2571 exit 0
2574 if (( NODEPS || (NOBUILD && !DEP_BIN ) )); then
2575 # no warning message needed for nobuild
2576 if (( NODEPS )); then
2577 warning "$(gettext "Skipping dependency checks.")"
2579 elif type -p "${PACMAN%% *}" >/dev/null; then
2580 if (( RMDEPS && ! INSTALL )); then
2581 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2583 deperr=0
2585 msg "$(gettext "Checking runtime dependencies...")"
2586 resolve_deps ${depends[@]} || deperr=1
2588 if (( RMDEPS && INSTALL )); then
2589 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2592 msg "$(gettext "Checking buildtime dependencies...")"
2593 resolve_deps ${makedepends[@]} || deperr=1
2595 if (( CHECKFUNC )); then
2596 resolve_deps ${checkdepends[@]} || deperr=1
2599 if (( RMDEPS )); then
2600 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2603 if (( deperr )); then
2604 error "$(gettext "Could not resolve all dependencies.")"
2605 exit 1
2607 else
2608 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2611 # ensure we have a sane umask set
2612 umask 0022
2614 # get back to our src directory so we can begin with sources
2615 mkdir -p "$srcdir"
2616 chmod a-s "$srcdir"
2617 cd_safe "$srcdir"
2619 if (( NOEXTRACT )); then
2620 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2621 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2622 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2624 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2625 error "$(gettext "The source directory is empty, there is nothing to build!")"
2626 plain "$(gettext "Aborting...")"
2627 exit 1
2629 elif (( REPKG )); then
2630 if (( ! PKGFUNC && ! SPLITPKG )) \
2631 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2632 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2633 plain "$(gettext "Aborting...")"
2634 exit 1
2636 else
2637 download_sources
2638 check_source_integrity
2639 extract_sources
2640 if (( PREPAREFUNC )); then
2641 run_prepare
2645 if (( NOBUILD )); then
2646 msg "$(gettext "Sources are ready.")"
2647 exit 0 #E_OK
2648 else
2649 # check for existing pkg directory; don't remove if we are repackaging
2650 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2651 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2652 rm -rf "$pkgdir"
2654 mkdir -p "$pkgdir"
2655 chmod a-s "$pkgdir"
2656 cd_safe "$startdir"
2658 # if we are root or if fakeroot is not enabled, then we don't use it
2659 if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
2660 if (( ! REPKG )); then
2661 (( BUILDFUNC )) && run_build
2662 (( CHECKFUNC )) && run_check
2664 if (( ! SPLITPKG )); then
2665 if (( PKGFUNC )); then
2666 run_package
2667 tidy_install
2668 else
2669 if (( ! REPKG )); then
2670 tidy_install
2671 else
2672 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2673 plain "$(gettext "File permissions may not be preserved.")"
2676 create_package
2677 else
2678 run_split_packaging
2680 else
2681 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2682 (( BUILDFUNC )) && run_build
2683 (( CHECKFUNC )) && run_check
2684 cd_safe "$startdir"
2687 enter_fakeroot
2691 fullver=$(get_full_version)
2692 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2694 install_package
2696 exit 0 #E_OK
2698 # vim: set ts=2 sw=2 noet: