makepkg: do not download VCS sources unless needed
[pacman-ng.git] / scripts / makepkg.sh.in
blobaec448768fb46a465dbea015bbb2071120bd4e85
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 SKIPCHECKSUMS=0
63 SKIPPGPCHECK=0
64 INSTALL=0
65 NOBUILD=0
66 NODEPS=0
67 NOEXTRACT=0
68 RMDEPS=0
69 REPKG=0
70 LOGGING=0
71 SOURCEONLY=0
72 IGNOREARCH=0
73 PREPAREFUNC=0
74 BUILDFUNC=0
75 CHECKFUNC=0
76 PKGFUNC=0
77 SPLITPKG=0
78 PKGLIST=()
79 SIGNPKG=''
81 # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call
82 # when dealing with svn/cvs/etc PKGBUILDs.
83 FORCE_VER=""
85 PACMAN_OPTS=
87 shopt -s extglob
89 ### SUBROUTINES ###
91 plain() {
92 local mesg=$1; shift
93 printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
96 msg() {
97 local mesg=$1; shift
98 printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
101 msg2() {
102 local mesg=$1; shift
103 printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
106 warning() {
107 local mesg=$1; shift
108 printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
111 error() {
112 local mesg=$1; shift
113 printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
118 # Special exit call for traps, Don't print any error messages when inside,
119 # the fakeroot call, the error message will be printed by the main call.
121 trap_exit() {
122 local signal=$1; shift
124 if (( ! INFAKEROOT )); then
125 echo
126 error "$@"
128 [[ -n $srclinks ]] && rm -rf "$srclinks"
130 # unset the trap for this signal, and then call the default handler
131 trap -- "$signal"
132 kill "-$signal" "$$"
137 # Clean up function. Called automatically when the script exits.
139 clean_up() {
140 local EXIT_CODE=$?
142 if (( INFAKEROOT )); then
143 # Don't clean up when leaving fakeroot, we're not done yet.
144 return
147 if (( ! EXIT_CODE && CLEANUP )); then
148 local pkg file
150 # If it's a clean exit and -c/--clean has been passed...
151 msg "$(gettext "Cleaning up...")"
152 rm -rf "$pkgdir" "$srcdir"
153 if [[ -n $pkgbase ]]; then
154 local fullver=$(get_full_version)
155 # Can't do this unless the BUILDSCRIPT has been sourced.
156 if (( BUILDFUNC )); then
157 rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"*
159 if (( CHECKFUNC )); then
160 rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
162 if (( PKGFUNC )); then
163 rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
164 elif (( SPLITPKG )); then
165 for pkg in ${pkgname[@]}; do
166 rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"*
167 done
170 # clean up dangling symlinks to packages
171 for pkg in ${pkgname[@]}; do
172 for file in ${pkg}-*-*-*{${PKGEXT},${SRCEXT}}; do
173 if [[ -h $file && ! -e $file ]]; then
174 rm -f "$file"
176 done
177 done
181 remove_deps
185 enter_fakeroot() {
186 msg "$(gettext "Entering %s environment...")" "fakeroot"
187 fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
191 # a source entry can have two forms :
192 # 1) "filename::http://path/to/file"
193 # 2) "http://path/to/file"
195 # Return the absolute filename of a source entry
196 get_filepath() {
197 local file="$(get_filename "$1")"
198 local proto="$(get_protocol "$1")"
200 case $proto in
201 git*|svn*)
202 if [[ -d "$startdir/$file" ]]; then
203 file="$startdir/$file"
204 elif [[ -d "$SRCDEST/$file" ]]; then
205 file="$SRCDEST/$file"
206 else
207 return 1
211 if [[ -f "$startdir/$file" ]]; then
212 file="$startdir/$file"
213 elif [[ -f "$SRCDEST/$file" ]]; then
214 file="$SRCDEST/$file"
215 else
216 return 1
219 esac
221 printf "%s\n" "$file"
224 # extract the filename from a source entry
225 get_filename() {
226 local netfile=$1
228 # if a filename is specified, use it
229 if [[ $netfile = *::* ]]; then
230 printf "%s\n" ${netfile%%::*}
231 return
234 local proto=$(get_protocol "$netfile")
236 case $proto in
237 git*|svn*)
238 filename=${netfile##*/}
239 filename=${filename%%#*}
240 # fall-through
242 git*)
243 filename=${filename%%.git*}
246 # if it is just an URL, we only keep the last component
247 filename="${netfile##*/}"
249 esac
250 printf "%s\n" "${filename}"
253 # extract the URL from a source entry
254 get_url() {
255 # strip an eventual filename
256 printf "%s\n" "${1#*::}"
259 # extract the protocol from a source entry - return "local" for local sources
260 get_protocol() {
261 if [[ $1 = *://* ]]; then
262 # strip leading filename
263 local proto="${1##*::}"
264 printf "%s\n" "${proto%%://*}"
265 else
266 printf "%s\n" local
270 get_downloadclient() {
271 local proto=$1
273 # loop through DOWNLOAD_AGENTS variable looking for protocol
274 local i
275 for i in "${DLAGENTS[@]}"; do
276 local handler="${i%%::*}"
277 if [[ $proto = "$handler" ]]; then
278 local agent="${i##*::}"
279 break
281 done
283 # if we didn't find an agent, return an error
284 if [[ -z $agent ]]; then
285 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
286 plain "$(gettext "Aborting...")"
287 exit 1 # $E_CONFIG_ERROR
290 # ensure specified program is installed
291 local program="${agent%% *}"
292 if [[ ! -x $program ]]; then
293 local baseprog="${program##*/}"
294 error "$(gettext "The download program %s is not installed.")" "$baseprog"
295 plain "$(gettext "Aborting...")"
296 exit 1 # $E_MISSING_PROGRAM
299 printf "%s\n" "$agent"
302 download_local() {
303 local netfile=$1
304 local filepath=$(get_filepath "$netfile")
306 if [[ -n "$filepath" ]]; then
307 msg2 "$(gettext "Found %s")" "${filepath##*/}"
308 rm -f "$srcdir/${filepath##*/}"
309 ln -s "$filepath" "$srcdir/"
310 continue
311 else
312 local filename=$(get_filename "$netfile")
313 error "$(gettext "%s was not found in the build directory and is not a URL.")" "$filename"
314 exit 1 # $E_MISSING_FILE
318 download_file() {
319 local netfile=$1
321 local filepath=$(get_filepath "$netfile")
322 if [[ -n "$filepath" ]]; then
323 msg2 "$(gettext "Found %s")" "${filepath##*/}"
324 rm -f "$srcdir/${filepath##*/}"
325 ln -s "$filepath" "$srcdir/"
326 return
329 local proto=$(get_protocol "$netfile")
331 # find the client we should use for this URL
332 local dlcmd
333 dlcmd=$(get_downloadclient "$proto") || exit $?
335 local filename=$(get_filename "$netfile")
336 local url=$(get_url "$netfile")
338 if [[ $proto = "scp" ]]; then
339 # scp downloads should not pass the protocol in the url
340 url="${url##*://}"
343 msg2 "$(gettext "Downloading %s...")" "$filename"
345 # temporary download file, default to last component of the URL
346 local dlfile="${url##*/}"
348 # replace %o by the temporary dlfile if it exists
349 if [[ $dlcmd = *%o* ]]; then
350 dlcmd=${dlcmd//\%o/\"$filename.part\"}
351 dlfile="$filename.part"
353 # add the URL, either in place of %u or at the end
354 if [[ $dlcmd = *%u* ]]; then
355 dlcmd=${dlcmd//\%u/\"$url\"}
356 else
357 dlcmd="$dlcmd \"$url\""
360 local ret=0
361 eval "$dlcmd || ret=\$?"
362 if (( ret )); then
363 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
364 error "$(gettext "Failure while downloading %s")" "$filename"
365 plain "$(gettext "Aborting...")"
366 exit 1
369 # rename the temporary download file to the final destination
370 if [[ $dlfile != "$filename" ]]; then
371 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$filename"
374 rm -f "$srcdir/$filename"
375 ln -s "$SRCDEST/$filename" "$srcdir/"
378 download_git() {
379 local netfile=$1
381 local fragment=${netfile##*#}
382 if [[ $fragment = "$netfile" ]]; then
383 unset fragment
386 local dir=$(get_filepath "$netfile")
387 [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"
389 local repo=${netfile##*/}
390 repo=${repo%%#*}
391 repo=${repo%%.git*}
393 local url=$(get_url "$netfile")
394 url=${url##*git+}
395 url=${url%%#*}
397 if [[ ! -d "$dir" ]]; then
398 msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git"
399 if ! git clone --mirror "$url" "$dir"; then
400 error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "git"
401 plain "$(gettext "Aborting...")"
402 exit 1
404 else
405 msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "git"
406 cd_safe "$dir"
407 if ! git fetch --all -p; then
408 # only warn on failure to allow offline builds
409 warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "git"
413 msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "git"
414 pushd "$srcdir" &>/dev/null
415 rm -rf "${dir##*/}"
417 if ! git clone "$dir"; then
418 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
419 plain "$(gettext "Aborting...")"
420 exit 1
423 cd_safe "${dir##*/}"
425 local ref
426 if [[ -n $fragment ]]; then
427 case ${fragment%%=*} in
428 commit|tag)
429 ref=${fragment##*=}
431 branch)
432 ref=origin/${fragment##*=}
435 error "$(gettext "Unrecognized reference: %s")" "${fragment}"
436 plain "$(gettext "Aborting...")"
437 exit 1
438 esac
441 if [[ -n $ref ]]; then
442 if ! git checkout -b makepkg $ref; then
443 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
444 plain "$(gettext "Aborting...")"
445 exit 1
449 popd &>/dev/null
452 download_svn() {
453 local netfile=$1
455 local fragment=${netfile##*#}
456 if [[ $fragment = "$netfile" ]]; then
457 unset fragment
460 local dir=$(get_filepath "$netfile")
461 [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"
463 local repo=${netfile##*/}
464 repo=${repo%%#*}
466 local url=$(get_url "$netfile")
467 if [[ $url != svn+ssh* ]]; then
468 url=${url##*svn+}
470 url=${url%%#*}
472 if [[ ! -d "$dir" ]]; then
473 msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "svn"
474 if ! svn checkout --config-dir "$dir" "$url" "$dir"; then
475 error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "svn"
476 plain "$(gettext "Aborting...")"
477 exit 1
479 else
480 msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "svn"
481 cd_safe "$dir"
482 if ! svn update; then
483 # only warn on failure to allow offline builds
484 warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "svn"
488 msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "svn"
489 pushd "$srcdir" &>/dev/null
490 rm -rf "${dir##*/}"
492 local ref
493 if [[ -n $fragment ]]; then
494 case ${fragment%%=*} in
495 revision)
496 ref=('-r' "${fragment##*=}")
499 error "$(gettext "Unrecognized reference: %s")" "${fragment}"
500 plain "$(gettext "Aborting...")"
501 exit 1
502 esac
505 if ! svn export $(ref[@]) "$dir"; then
506 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "svn"
507 plain "$(gettext "Aborting...")"
510 popd &>/dev/null
513 download_sources() {
514 msg "$(gettext "Retrieving Sources...")"
516 local GET_VCS=1
517 if [[ $1 == "fast" ]]; then
518 GET_VCS=0
521 pushd "$SRCDEST" &>/dev/null
523 local netfile
524 for netfile in "${source[@]}"; do
525 local proto=$(get_protocol "$netfile")
527 case "$proto" in
528 local)
529 download_local "$netfile"
531 ftp|http|https|rsync|scp)
532 download_file "$netfile"
534 git*)
535 (( GET_VCS )) && download_git "$netfile"
537 svn*)
538 (( GET_VCS )) && download_svn "$netfile"
541 error "$(gettext "Unknown download protocol: %s")" "$proto"
542 plain "$(gettext "Aborting...")"
543 exit 1
545 esac
546 done
548 if declare -f pkgver >/dev/null; then
549 update_pkgver
552 popd &>/dev/null
555 # Automatically update pkgver variable if a pkgver() function is provided
556 # Re-sources the PKGBUILD afterwards to allow for other variables that use $pkgver
557 update_pkgver() {
558 newpkgver=$(run_function_safe pkgver)
560 if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then
561 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
562 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
563 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
564 source "$BUILDFILE"
565 else
566 warning "$(gettext "%s is not writeable -- pkgver will not be updated")" \
567 "$BUILDFILE"
572 # Print 'source not found' error message and exit makepkg
573 missing_source_file() {
574 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
575 plain "$(gettext "Aborting...")"
576 exit 1 # $E_MISSING_FILE
580 # usage : get_full_version( [$pkgname] )
581 # return : full version spec, including epoch (if necessary), pkgver, pkgrel
583 get_full_version() {
584 if [[ -z $1 ]]; then
585 if [[ $epoch ]] && (( ! $epoch )); then
586 printf "%s\n" "$pkgver-$pkgrel"
587 else
588 printf "%s\n" "$epoch:$pkgver-$pkgrel"
590 else
591 for i in pkgver pkgrel epoch; do
592 local indirect="${i}_override"
593 eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
594 [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
595 done
596 if (( ! $epoch_override )); then
597 printf "%s\n" "$pkgver_override-$pkgrel_override"
598 else
599 printf "%s\n" "$epoch_override:$pkgver_override-$pkgrel_override"
605 # usage : get_pkg_arch( [$pkgname] )
606 # return : architecture of the package
608 get_pkg_arch() {
609 if [[ -z $1 ]]; then
610 if [[ $arch = "any" ]]; then
611 printf "%s\n" "any"
612 else
613 printf "%s\n" "$CARCH"
615 else
616 local arch_override
617 eval $(declare -f package_$1 | sed -n 's/\(^[[:space:]]*arch=\)/arch_override=/p')
618 (( ${#arch_override[@]} == 0 )) && arch_override=("${arch[@]}")
619 if [[ $arch_override = "any" ]]; then
620 printf "%s\n" "any"
621 else
622 printf "%s\n" "$CARCH"
628 # Checks to see if options are present in makepkg.conf or PKGBUILD;
629 # PKGBUILD options always take precedence.
631 # usage : check_option( $option, $expected_val )
632 # return : 0 - matches expected
633 # 1 - does not match expected
634 # 127 - not found
636 check_option() {
637 in_opt_array "$1" ${options[@]}
638 case $? in
639 0) # assert enabled
640 [[ $2 = y ]]
641 return ;;
642 1) # assert disabled
643 [[ $2 = n ]]
644 return
645 esac
647 # fall back to makepkg.conf options
648 in_opt_array "$1" ${OPTIONS[@]}
649 case $? in
650 0) # assert enabled
651 [[ $2 = y ]]
652 return ;;
653 1) # assert disabled
654 [[ $2 = n ]]
655 return
656 esac
658 # not found
659 return 127
664 # Check if option is present in BUILDENV
666 # usage : check_buildenv( $option, $expected_val )
667 # return : 0 - matches expected
668 # 1 - does not match expected
669 # 127 - not found
671 check_buildenv() {
672 in_opt_array "$1" ${BUILDENV[@]}
673 case $? in
674 0) # assert enabled
675 [[ $2 = "y" ]]
676 return ;;
677 1) # assert disabled
678 [[ $2 = "n" ]]
679 return ;;
680 esac
682 # not found
683 return 127
688 # usage : in_opt_array( $needle, $haystack )
689 # return : 0 - enabled
690 # 1 - disabled
691 # 127 - not found
693 in_opt_array() {
694 local needle=$1; shift
696 local opt
697 for opt in "$@"; do
698 if [[ $opt = "$needle" ]]; then
699 # enabled
700 return 0
701 elif [[ $opt = "!$needle" ]]; then
702 # disabled
703 return 1
705 done
707 # not found
708 return 127
713 # usage : in_array( $needle, $haystack )
714 # return : 0 - found
715 # 1 - not found
717 in_array() {
718 local needle=$1; shift
719 local item
720 for item in "$@"; do
721 [[ $item = "$needle" ]] && return 0 # Found
722 done
723 return 1 # Not Found
726 source_has_signatures() {
727 local file
728 for file in "${source[@]}"; do
729 if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
730 return 0
732 done
733 return 1
736 run_pacman() {
737 local cmd
738 if [[ ! $1 = -@(T|Qq) ]]; then
739 cmd=("$PACMAN" $PACMAN_OPTS "$@")
740 else
741 cmd=("$PACMAN" "$@")
743 if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then
744 if type -p sudo >/dev/null; then
745 cmd=(sudo "${cmd[@]}")
746 else
747 cmd=(su root -c "$(printf '%q ' "${cmd[@]}")")
750 "${cmd[@]}"
753 check_deps() {
754 (( $# > 0 )) || return 0
756 local ret=0
757 local pmout
758 pmout=$(run_pacman -T "$@")
759 ret=$?
761 if (( ret == 127 )); then #unresolved deps
762 printf "%s\n" "$pmout"
763 elif (( ret )); then
764 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
765 return "$ret"
769 handle_deps() {
770 local R_DEPS_SATISFIED=0
771 local R_DEPS_MISSING=1
773 (( $# == 0 )) && return $R_DEPS_SATISFIED
775 local deplist="$*"
777 if (( ! DEP_BIN )); then
778 return $R_DEPS_MISSING
781 if (( DEP_BIN )); then
782 # install missing deps from binary packages (using pacman -S)
783 msg "$(gettext "Installing missing dependencies...")"
785 if ! run_pacman -S --asdeps $deplist; then
786 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
787 exit 1 # TODO: error code
791 # we might need the new system environment
792 # save our shell options and turn off extglob
793 local shellopts=$(shopt -p)
794 shopt -u extglob
795 source /etc/profile &>/dev/null
796 eval "$shellopts"
798 return $R_DEPS_SATISFIED
801 resolve_deps() {
802 local R_DEPS_SATISFIED=0
803 local R_DEPS_MISSING=1
805 # deplist cannot be declared like this: local deplist=$(foo)
806 # Otherwise, the return value will depend on the assignment.
807 local deplist
808 deplist="$(set +E; check_deps $*)" || exit 1
809 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
811 if handle_deps $deplist; then
812 # check deps again to make sure they were resolved
813 deplist="$(set +E; check_deps $*)" || exit 1
814 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
817 msg "$(gettext "Missing Dependencies:")"
818 local dep
819 for dep in $deplist; do
820 msg2 "$dep"
821 done
823 return $R_DEPS_MISSING
826 remove_deps() {
827 (( ! RMDEPS )) && return
829 # check for packages removed during dependency install (e.g. due to conflicts)
830 # removing all installed packages is risky in this case
831 if [[ -n $(grep -xvFf <(printf '%s\n' "${current_packagelist[@]}") \
832 <(printf '%s\n' "${original_packagelist[@]}") || true) ]]; then
833 warning "$(gettext "Failed to remove installed dependencies.")"
834 return 0
837 local deplist
838 deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \
839 <(printf "%s\n" "${current_pkglist[@]}") || true))
840 if [[ -z $deplist ]]; then
841 return
844 msg "Removing installed dependencies..."
845 # exit cleanly on failure to remove deps as package has been built successfully
846 if ! run_pacman -Rn ${deplist[@]}; then
847 warning "$(gettext "Failed to remove installed dependencies.")"
848 return 0
852 get_integlist() {
853 local integ
854 local integlist=()
856 for integ in md5 sha1 sha256 sha384 sha512; do
857 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
858 if [[ -n "$integrity_sums" ]]; then
859 integlist=(${integlist[@]} $integ)
861 done
863 if (( ${#integlist[@]} > 0 )); then
864 printf "%s\n" "${integlist[@]}"
865 else
866 printf "%s\n" "${INTEGRITY_CHECK[@]}"
870 generate_checksums() {
871 msg "$(gettext "Generating checksums for source files...")"
873 if ! type -p openssl >/dev/null; then
874 error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
875 exit 1 # $E_MISSING_PROGRAM
878 local integlist
879 if (( $# == 0 )); then
880 integlist=$(get_integlist)
881 else
882 integlist=$@
885 local integ
886 for integ in ${integlist[@]}; do
887 case "$integ" in
888 md5|sha1|sha256|sha384|sha512) : ;;
890 error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
891 exit 1;; # $E_CONFIG_ERROR
892 esac
894 local ct=0
895 local numsrc=${#source[@]}
896 printf "%s" "${integ}sums=("
898 local i
899 local indent=''
900 for (( i = 0; i < ${#integ} + 6; i++ )); do
901 indent="$indent "
902 done
904 local netfile
905 for netfile in "${source[@]}"; do
906 local proto sum
907 proto="$(get_protocol "$netfile")"
909 case $proto in
910 git*|svn*)
911 sum="SKIP"
914 local file
915 file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
916 sum="$(openssl dgst -${integ} "$file")"
917 sum=${sum##* }
919 esac
921 (( ct )) && printf "%s" "$indent"
922 printf "%s" "'$sum'"
923 ct=$(($ct+1))
924 (( $ct < $numsrc )) && echo
925 done
927 echo ")"
928 done
931 check_checksums() {
932 (( SKIPCHECKSUMS )) && return 0
933 (( ! ${#source[@]} )) && return 0
935 local correlation=0
936 local integ required
937 for integ in md5 sha1 sha256 sha384 sha512; do
938 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
939 if (( ${#integrity_sums[@]} == ${#source[@]} )); then
940 msg "$(gettext "Validating source files with %s...")" "${integ}sums"
941 correlation=1
942 local errors=0
943 local idx=0
944 local file
945 for file in "${source[@]}"; do
946 local found=1
947 file="$(get_filename "$file")"
948 printf "%s" " $file ... " >&2
950 if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then
951 echo "$(gettext "Skipped")" >&2
952 idx=$((idx + 1))
953 continue
956 if ! file="$(get_filepath "$file")"; then
957 printf -- "$(gettext "NOT FOUND")\n" >&2
958 errors=1
959 found=0
962 if (( $found )) ; then
963 local expectedsum="${integrity_sums[idx],,}"
964 local realsum="$(openssl dgst -${integ} "$file")"
965 realsum="${realsum##* }"
966 if [[ $expectedsum = "$realsum" ]]; then
967 printf -- "$(gettext "Passed")\n" >&2
968 else
969 printf -- "$(gettext "FAILED")\n" >&2
970 errors=1
974 idx=$((idx + 1))
975 done
977 if (( errors )); then
978 error "$(gettext "One or more files did not pass the validity check!")"
979 exit 1 # TODO: error code
981 elif (( ${#integrity_sums[@]} )); then
982 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
983 exit 1 # TODO: error code
985 done
987 if (( ! correlation )); then
988 error "$(gettext "Integrity checks are missing.")"
989 exit 1 # TODO: error code
993 check_pgpsigs() {
994 (( SKIPPGPCHECK )) && return 0
995 ! source_has_signatures && return 0
997 msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
999 local file pubkey
1000 local warning=0
1001 local errors=0
1002 local statusfile=$(mktemp)
1004 for file in "${source[@]}"; do
1005 file="$(get_filename "$file")"
1006 if [[ ! $file = *.@(sig?(n)|asc) ]]; then
1007 continue
1010 printf " %s ... " "${file%.*}" >&2
1012 if ! file="$(get_filepath "$file")"; then
1013 printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
1014 errors=1
1015 continue
1018 if ! sourcefile="$(get_filepath "${file%.*}")"; then
1019 printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
1020 errors=1
1021 continue
1024 if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
1025 printf '%s' "$(gettext "FAILED")" >&2
1026 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then
1027 printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
1028 warnings=1
1029 else
1030 errors=1
1032 printf '\n' >&2
1033 else
1034 if grep -q "REVKEYSIG" "$statusfile"; then
1035 printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2
1036 errors=1
1037 else
1038 printf '%s' "$(gettext "Passed")" >&2
1039 if grep -q "EXPSIG" "$statusfile"; then
1040 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
1041 warnings=1
1042 elif grep -q "EXPKEYSIG" "$statusfile"; then
1043 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
1044 warnings=1
1047 printf '\n' >&2
1049 done
1051 rm -f "$statusfile"
1053 if (( errors )); then
1054 error "$(gettext "One or more PGP signatures could not be verified!")"
1055 exit 1
1058 if (( warnings )); then
1059 warning "$(gettext "Warnings have occurred while verifying the signatures.")"
1060 plain "$(gettext "Please make sure you really trust them.")"
1064 check_source_integrity() {
1065 if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
1066 warning "$(gettext "Skipping all source file integrity checks.")"
1067 elif (( SKIPCHECKSUMS )); then
1068 warning "$(gettext "Skipping verification of source file checksums.")"
1069 check_pgpsigs
1070 elif (( SKIPPGPCHECK )); then
1071 warning "$(gettext "Skipping verification of source file PGP signatures.")"
1072 check_checksums
1073 else
1074 check_checksums
1075 check_pgpsigs
1079 extract_sources() {
1080 msg "$(gettext "Extracting Sources...")"
1081 local netfile
1082 for netfile in "${source[@]}"; do
1083 local file=$(get_filename "$netfile")
1084 if in_array "$file" "${noextract[@]}"; then
1085 #skip source files in the noextract=() array
1086 # these are marked explicitly to NOT be extracted
1087 continue
1091 # fix flyspray #6246
1092 local file_type=$(file -bizL "$file")
1093 local ext=${file##*.}
1094 local cmd=''
1095 case "$file_type" in
1096 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
1097 cmd="bsdtar" ;;
1098 *application/x-gzip*)
1099 case "$ext" in
1100 gz|z|Z) cmd="gzip" ;;
1101 *) continue;;
1102 esac ;;
1103 *application/x-bzip*)
1104 case "$ext" in
1105 bz2|bz) cmd="bzip2" ;;
1106 *) continue;;
1107 esac ;;
1108 *application/x-xz*)
1109 case "$ext" in
1110 xz) cmd="xz" ;;
1111 *) continue;;
1112 esac ;;
1114 # See if bsdtar can recognize the file
1115 if bsdtar -tf "$file" -q '*' &>/dev/null; then
1116 cmd="bsdtar"
1117 else
1118 continue
1119 fi ;;
1120 esac
1122 local ret=0
1123 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
1124 if [[ $cmd = "bsdtar" ]]; then
1125 $cmd -xf "$file" || ret=$?
1126 else
1127 rm -f -- "${file%.*}"
1128 $cmd -dcf "$file" > "${file%.*}" || ret=$?
1130 if (( ret )); then
1131 error "$(gettext "Failed to extract %s")" "$file"
1132 plain "$(gettext "Aborting...")"
1133 exit 1
1135 done
1137 if (( EUID == 0 )); then
1138 # change perms of all source files to root user & root group
1139 chown -R 0:0 "$srcdir"
1143 error_function() {
1144 if [[ -p $logpipe ]]; then
1145 rm "$logpipe"
1147 # first exit all subshells, then print the error
1148 if (( ! BASH_SUBSHELL )); then
1149 error "$(gettext "A failure occurred in %s().")" "$1"
1150 plain "$(gettext "Aborting...")"
1151 remove_deps
1153 exit 2 # $E_BUILD_FAILED
1156 cd_safe() {
1157 if ! cd "$1"; then
1158 error "$(gettext "Failed to change to directory %s")" "$1"
1159 plain "$(gettext "Aborting...")"
1160 exit 1
1164 source_safe() {
1165 shopt -u extglob
1166 if ! source "$@"; then
1167 error "$(gettext "Failed to source %s")" "$1"
1168 exit 1
1170 shopt -s extglob
1173 run_function_safe() {
1174 local restoretrap
1176 set -e
1177 set -E
1179 restoretrap=$(trap -p ERR)
1180 trap 'error_function $pkgfunc' ERR
1182 run_function "$1"
1184 eval $restoretrap
1186 set +E
1187 set +e
1190 run_function() {
1191 if [[ -z $1 ]]; then
1192 return 1
1194 local pkgfunc="$1"
1196 # clear user-specified buildflags if requested
1197 if check_option "buildflags" "n"; then
1198 unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
1201 # clear user-specified makeflags if requested
1202 if check_option "makeflags" "n"; then
1203 unset MAKEFLAGS
1206 msg "$(gettext "Starting %s()...")" "$pkgfunc"
1207 cd_safe "$srcdir"
1209 # ensure all necessary build variables are exported
1210 export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
1211 # save our shell options so pkgfunc() can't override what we need
1212 local shellopts=$(shopt -p)
1214 local ret=0
1215 if (( LOGGING )); then
1216 local fullver=$(get_full_version)
1217 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
1218 if [[ -f $BUILDLOG ]]; then
1219 local i=1
1220 while true; do
1221 if [[ -f $BUILDLOG.$i ]]; then
1222 i=$(($i +1))
1223 else
1224 break
1226 done
1227 mv "$BUILDLOG" "$BUILDLOG.$i"
1230 # ensure overridden package variables survive tee with split packages
1231 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
1232 mkfifo "$logpipe"
1233 tee "$BUILDLOG" < "$logpipe" &
1234 local teepid=$!
1236 $pkgfunc &>"$logpipe"
1238 wait $teepid
1239 rm "$logpipe"
1240 else
1241 $pkgfunc 2>&1
1243 # reset our shell options
1244 eval "$shellopts"
1247 run_prepare() {
1248 run_function_safe "prepare"
1251 run_build() {
1252 # use distcc if it is requested (check buildenv and PKGBUILD opts)
1253 if check_buildenv "distcc" "y" && ! check_option "distc" "n"; then
1254 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
1255 export DISTCC_HOSTS
1258 # use ccache if it is requested (check buildenv and PKGBUILD opts)
1259 if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
1260 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
1263 run_function_safe "build"
1266 run_check() {
1267 run_function_safe "check"
1270 run_package() {
1271 local pkgfunc
1272 if [[ -z $1 ]]; then
1273 pkgfunc="package"
1274 else
1275 pkgfunc="package_$1"
1278 run_function_safe "$pkgfunc"
1281 tidy_install() {
1282 cd_safe "$pkgdir"
1283 msg "$(gettext "Tidying install...")"
1285 if check_option "docs" "n" && [[ -n ${DOC_DIRS[*]} ]]; then
1286 msg2 "$(gettext "Removing doc files...")"
1287 rm -rf -- ${DOC_DIRS[@]}
1290 if check_option "purge" "y" && [[ -n ${PURGE_TARGETS[*]} ]]; then
1291 msg2 "$(gettext "Purging unwanted files...")"
1292 local pt
1293 for pt in "${PURGE_TARGETS[@]}"; do
1294 if [[ ${pt} = "${pt//\/}" ]]; then
1295 find . ! -type d -name "${pt}" -exec rm -f -- '{}' \;
1296 else
1297 rm -f ${pt}
1299 done
1302 if check_option "zipman" "y" && [[ -n ${MAN_DIRS[*]} ]]; then
1303 msg2 "$(gettext "Compressing man and info pages...")"
1304 local file files inode link
1305 while read -rd ' ' inode; do
1306 read file
1307 find ${MAN_DIRS[@]} -type l 2>/dev/null |
1308 while read link ; do
1309 if [[ "${file}" -ef "${link}" ]] ; then
1310 rm -f "$link" "${link}.gz"
1311 if [[ ${file%/*} = ${link%/*} ]]; then
1312 ln -s -- "${file##*/}.gz" "${link}.gz"
1313 else
1314 ln -s -- "/${file}.gz" "${link}.gz"
1317 done
1318 if [[ -z ${files[$inode]} ]]; then
1319 files[$inode]=$file
1320 gzip -9 -f "$file"
1321 else
1322 rm -f "$file"
1323 ln "${files[$inode]}.gz" "${file}.gz"
1324 chmod 644 "${file}.gz"
1326 done < <(find ${MAN_DIRS[@]} -type f \! -name "*.gz" \! -name "*.bz2" \
1327 -exec @INODECMD@ '{}' + 2>/dev/null)
1330 if check_option "strip" "y"; then
1331 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1332 # make sure library stripping variables are defined to prevent excess stripping
1333 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1334 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1335 local binary
1336 find . -type f -perm -u+w -print0 2>/dev/null | while read -d '' binary ; do
1337 case "$(file -bi "$binary")" in
1338 *application/x-sharedlib*) # Libraries (.so)
1339 strip $STRIP_SHARED "$binary";;
1340 *application/x-archive*) # Libraries (.a)
1341 strip $STRIP_STATIC "$binary";;
1342 *application/x-executable*) # Binaries
1343 strip $STRIP_BINARIES "$binary";;
1344 esac
1345 done
1348 if check_option "libtool" "n"; then
1349 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1350 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1353 if check_option "emptydirs" "n"; then
1354 msg2 "$(gettext "Removing empty directories...")"
1355 find . -depth -type d -exec rmdir '{}' + 2>/dev/null
1358 if check_option "upx" "y"; then
1359 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1360 local binary
1361 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1362 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1363 upx $UPXFLAGS "$binary" &>/dev/null ||
1364 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1366 done
1370 find_libdepends() {
1371 local d sodepends;
1373 sodepends=0;
1374 for d in "${depends[@]}"; do
1375 if [[ $d = *.so ]]; then
1376 sodepends=1;
1377 break;
1379 done
1381 if (( sodepends == 0 )); then
1382 printf '%s\n' "${depends[@]}"
1383 return;
1386 local libdeps filename soarch sofile soname soversion;
1387 declare -A libdeps;
1389 while read filename; do
1390 # get architecture of the file; if soarch is empty it's not an ELF binary
1391 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1392 [[ -n "$soarch" ]] || continue
1394 # process all libraries needed by the binary
1395 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1397 # extract the library name: libfoo.so
1398 soname="${sofile%.so?(+(.+([0-9])))}".so
1399 # extract the major version: 1
1400 soversion="${sofile##*\.so\.}"
1402 if [[ ${libdeps[$soname]} ]]; then
1403 if [[ ${libdeps[$soname]} != *${soversion}-${soarch}* ]]; then
1404 libdeps[$soname]+=" ${soversion}-${soarch}"
1406 else
1407 libdeps[$soname]="${soversion}-${soarch}"
1409 done
1410 done < <(find "$pkgdir" -type f -perm -u+x)
1412 local libdepends v
1413 for d in "${depends[@]}"; do
1414 case "$d" in
1415 *.so)
1416 if [[ ${libdeps[$d]} ]]; then
1417 for v in ${libdeps[$d]}; do
1418 libdepends+=("$d=$v")
1419 done
1420 else
1421 warning "$(gettext "Library listed in %s is not required by any files: %s")" "'depends'" "$d"
1422 libdepends+=("$d")
1426 libdepends+=("$d")
1428 esac
1429 done
1431 printf '%s\n' "${libdepends[@]}"
1435 find_libprovides() {
1436 local p libprovides missing
1437 for p in "${provides[@]}"; do
1438 missing=0
1439 case "$p" in
1440 *.so)
1441 mapfile -t filename < <(find "$pkgdir" -type f -name $p\*)
1442 if [[ $filename ]]; then
1443 # packages may provide multiple versions of the same library
1444 for fn in "${filename[@]}"; do
1445 # check if we really have a shared object
1446 if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1447 # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1)
1448 local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1449 if [[ -z "$sofile" ]]; then
1450 warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p"
1451 libprovides+=("$p")
1452 continue
1455 # get the library architecture (32 or 64 bit)
1456 local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1458 # extract the library major version
1459 local soversion="${sofile##*\.so\.}"
1461 libprovides+=("${p}=${soversion}-${soarch}")
1462 else
1463 warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p"
1464 libprovides+=("$p")
1466 done
1467 else
1468 libprovides+=("$p")
1469 missing=1
1473 libprovides+=("$p")
1475 esac
1477 if (( missing )); then
1478 warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p"
1480 done
1482 printf '%s\n' "${libprovides[@]}"
1485 check_license() {
1486 # TODO maybe remove this at some point
1487 # warn if license array is not present or empty
1488 if [[ -z $license ]]; then
1489 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1490 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1494 write_pkginfo() {
1495 local builddate=$(date -u "+%s")
1496 if [[ -n $PACKAGER ]]; then
1497 local packager="$PACKAGER"
1498 else
1499 local packager="Unknown Packager"
1502 # btrfs's delayed allocation causes the stat buffers from the kernel to "lie"
1503 # to us momentarily and report 0 blocks allocated (which is how du calculates
1504 # size). Sleeping for a second here is about the dirtiest thing possible,
1505 # but avoids reporting entirely bogus install sizes.
1506 sleep 1
1507 local size="$(@DUPATH@ -sk)"
1508 size="$(( ${size%%[^0-9]*} * 1024 ))"
1510 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1511 echo "# Generated by makepkg $makepkg_version"
1512 if (( INFAKEROOT )); then
1513 echo "# using $(fakeroot -v)"
1515 echo "# $(LC_ALL=C date -u)"
1516 printf "pkgname = %s\n" "$1"
1517 (( SPLITPKG )) && echo pkgbase = $pkgbase
1518 echo "pkgver = $(get_full_version)"
1519 printf "pkgdesc = %s\n" "$pkgdesc"
1520 printf "url = %s\n" "$url"
1521 printf "builddate = %s\n" "$builddate"
1522 printf "packager = %s\n" "$packager"
1523 printf "size = %s\n" "$size"
1524 printf "arch = %s\n" "$pkgarch"
1526 mapfile -t provides < <(find_libprovides)
1527 mapfile -t depends < <(find_libdepends)
1529 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1530 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1531 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1532 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1533 [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
1534 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1535 [[ $depends ]] && printf "depend = %s\n" "${depends[@]}"
1536 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1537 [[ $makedepends ]] && printf "makedepend = %s\n" "${makedepends[@]}"
1538 [[ $checkdepends ]] && printf "checkdepend = %s\n" "${checkdepends[@]}"
1540 local it
1541 for it in "${packaging_options[@]}"; do
1542 check_option "$it" "y"
1543 case $? in
1545 printf "makepkgopt = %s\n" "$it"
1548 printf "makepkgopt = %s\n" "!$it"
1550 esac
1551 done
1553 check_license
1556 check_package() {
1557 cd_safe "$pkgdir"
1559 # check existence of backup files
1560 local file
1561 for file in "${backup[@]}"; do
1562 if [[ ! -f $file ]]; then
1563 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1565 done
1567 # check for references to the build and package directory
1568 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1569 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1571 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1572 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1577 create_package() {
1578 if [[ ! -d $pkgdir ]]; then
1579 error "$(gettext "Missing %s directory.")" "pkg/"
1580 plain "$(gettext "Aborting...")"
1581 exit 1 # $E_MISSING_PKGDIR
1584 check_package
1586 cd_safe "$pkgdir"
1587 msg "$(gettext "Creating package...")"
1589 local nameofpkg
1590 if [[ -z $1 ]]; then
1591 nameofpkg="$pkgname"
1592 else
1593 nameofpkg="$1"
1596 pkgarch=$(get_pkg_arch)
1598 write_pkginfo $nameofpkg > .PKGINFO
1600 local comp_files=('.PKGINFO')
1602 # check for changelog/install files
1603 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1604 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1606 if [[ -n ${!orig} ]]; then
1607 msg2 "$(gettext "Adding %s file...")" "$orig"
1608 cp "$startdir/${!orig}" "$dest"
1609 chmod 644 "$dest"
1610 comp_files+=("$dest")
1612 done
1614 # tar it up
1615 msg2 "$(gettext "Compressing package...")"
1617 local fullver=$(get_full_version)
1618 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${pkgarch}${PKGEXT}"
1619 local ret=0
1621 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1622 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1624 # when fileglobbing, we want * in an empty directory to expand to
1625 # the null string rather than itself
1626 shopt -s nullglob
1627 # TODO: Maybe this can be set globally for robustness
1628 shopt -s -o pipefail
1629 # bsdtar's gzip compression always saves the time stamp, making one
1630 # archive created using the same command line distinct from another.
1631 # Disable bsdtar compression and use gzip -n for now.
1632 bsdtar -cf - "${comp_files[@]}" * |
1633 case "$PKGEXT" in
1634 *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;;
1635 *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;;
1636 *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;;
1637 *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;;
1638 *tar) cat ;;
1639 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1640 "$PKGEXT"; cat ;;
1641 esac > "${pkg_file}" || ret=$?
1643 shopt -u nullglob
1644 shopt -u -o pipefail
1646 if (( ret )); then
1647 error "$(gettext "Failed to create package file.")"
1648 exit 1 # TODO: error code
1651 create_signature "$pkg_file"
1653 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1654 rm -f "${pkg_file/$PKGDEST/$startdir}"
1655 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1656 ret=$?
1657 if [[ -f $pkg_file.sig ]]; then
1658 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1659 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1663 if (( ret )); then
1664 warning "$(gettext "Failed to create symlink to package file.")"
1668 create_signature() {
1669 if [[ $SIGNPKG != 'y' ]]; then
1670 return
1672 local ret=0
1673 local filename="$1"
1674 msg "$(gettext "Signing package...")"
1676 local SIGNWITHKEY=""
1677 if [[ -n $GPGKEY ]]; then
1678 SIGNWITHKEY="-u ${GPGKEY}"
1680 # The signature will be generated directly in ascii-friendly format
1681 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1684 if (( ! ret )); then
1685 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1686 else
1687 warning "$(gettext "Failed to sign package file.")"
1691 create_srcpackage() {
1692 local ret=0
1693 msg "$(gettext "Creating source package...")"
1694 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1695 mkdir "${srclinks}"/${pkgbase}
1697 check_license
1699 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1700 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1702 local file
1703 for file in "${source[@]}"; do
1704 if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then
1705 local absfile
1706 absfile=$(get_filepath "$file") || missing_source_file "$file"
1707 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1708 ln -s "$absfile" "$srclinks/$pkgbase"
1710 done
1712 local i
1713 for i in 'changelog' 'install'; do
1714 local file
1715 while read -r file; do
1716 # evaluate any bash variables used
1717 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1718 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1719 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1720 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1722 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1723 done
1725 local TAR_OPT
1726 case "$SRCEXT" in
1727 *tar.gz) TAR_OPT="z" ;;
1728 *tar.bz2) TAR_OPT="j" ;;
1729 *tar.xz) TAR_OPT="J" ;;
1730 *tar.Z) TAR_OPT="Z" ;;
1731 *tar) TAR_OPT="" ;;
1732 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1733 "$SRCEXT" ;;
1734 esac
1736 local fullver=$(get_full_version)
1737 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1739 # tar it up
1740 msg2 "$(gettext "Compressing source package...")"
1741 cd_safe "${srclinks}"
1742 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1743 error "$(gettext "Failed to create source package file.")"
1744 exit 1 # TODO: error code
1747 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1748 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1749 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1750 ret=$?
1753 if (( ret )); then
1754 warning "$(gettext "Failed to create symlink to source package file.")"
1757 cd_safe "${startdir}"
1758 rm -rf "${srclinks}"
1761 install_package() {
1762 (( ! INSTALL )) && return
1764 if (( ! SPLITPKG )); then
1765 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1766 else
1767 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1770 local fullver pkgarch pkg pkglist
1771 (( ASDEPS )) && pkglist+=('--asdeps')
1773 for pkg in ${pkgname[@]}; do
1774 fullver=$(get_full_version $pkg)
1775 pkgarch=$(get_pkg_arch $pkg)
1776 pkglist+=("$PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT}")
1777 done
1779 if ! run_pacman -U ${pkglist[@]}; then
1780 warning "$(gettext "Failed to install built package(s).")"
1781 return 0
1785 check_sanity() {
1786 # check for no-no's in the build script
1787 local i
1788 local ret=0
1789 for i in 'pkgname' 'pkgrel' 'pkgver'; do
1790 if [[ -z ${!i} ]]; then
1791 error "$(gettext "%s is not allowed to be empty.")" "$i"
1792 ret=1
1794 done
1796 for i in "${pkgname[@]}"; do
1797 if [[ ${i:0:1} = "-" ]]; then
1798 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1799 ret=1
1801 if [[ $i = *[^[:alnum:]+_.@-]* ]]; then
1802 error "$(gettext "%s contains invalid characters: '%s'")" \
1803 'pkgname' "${pkgname//[[:alnum:]+_.@-]}"
1804 ret=1
1806 done
1808 if [[ ${pkgbase:0:1} = "-" ]]; then
1809 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1810 ret=1
1813 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1814 while IFS='=' read -r _ i; do
1815 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1816 if [[ $i = *[[:space:]:-]* ]]; then
1817 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
1818 return 1
1820 done || ret=1
1822 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1823 while IFS='=' read -r _ i; do
1824 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1825 if [[ $i != +([0-9])?(.+([0-9])) ]]; then
1826 error "$(gettext "%s must be a decimal.")" "pkgrel"
1827 return 1
1829 done || ret=1
1831 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1832 while IFS='=' read -r _ i; do
1833 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1834 if [[ $i != *([[:digit:]]) ]]; then
1835 error "$(gettext "%s must be an integer.")" "epoch"
1836 return 1
1838 done || ret=1
1840 if [[ $arch != 'any' ]]; then
1841 if ! in_array $CARCH ${arch[@]}; then
1842 if (( ! IGNOREARCH )); then
1843 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1844 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1845 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1846 ret=1
1851 if (( ${#pkgname[@]} > 1 )); then
1852 for i in ${pkgname[@]}; do
1853 local arch_list=""
1854 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1855 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1856 if ! in_array $CARCH ${arch_list[@]}; then
1857 if (( ! IGNOREARCH )); then
1858 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1859 ret=1
1863 done
1866 local provides_list=()
1867 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1868 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1869 for i in ${provides_list[@]}; do
1870 if [[ $i == *['<>']* ]]; then
1871 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1872 ret=1
1874 done
1876 local backup_list=()
1877 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1878 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1879 for i in "${backup_list[@]}"; do
1880 if [[ ${i:0:1} = "/" ]]; then
1881 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1882 ret=1
1884 done
1886 local optdepends_list=()
1887 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1888 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1889 for i in "${optdepends_list[@]}"; do
1890 local pkg=${i%%:[[:space:]]*}
1891 # the '-' character _must_ be first or last in the character range
1892 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1893 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1894 ret=1
1896 done
1898 for i in 'changelog' 'install'; do
1899 local file
1900 while read -r file; do
1901 # evaluate any bash variables used
1902 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1903 if [[ $file && ! -f $file ]]; then
1904 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1905 ret=1
1907 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1908 done
1910 local valid_options=1
1911 local known kopt options_list
1912 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1913 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1914 for i in ${options_list[@]}; do
1915 known=0
1916 # check if option matches a known option or its inverse
1917 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1918 if [[ ${i} = "${kopt}" || ${i} = "!${kopt}" ]]; then
1919 known=1
1921 done
1922 if (( ! known )); then
1923 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1924 valid_options=0
1926 done
1927 if (( ! valid_options )); then
1928 ret=1
1931 if (( ${#pkgname[@]} > 1 )); then
1932 for i in ${pkgname[@]}; do
1933 if ! declare -f package_${i} >/dev/null; then
1934 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1935 ret=1
1937 done
1940 for i in ${PKGLIST[@]}; do
1941 if ! in_array $i ${pkgname[@]}; then
1942 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1943 ret=1
1945 done
1947 return $ret
1950 check_software() {
1951 # check for needed software
1952 local ret=0
1954 # check for sudo if we will need it during makepkg execution
1955 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1956 if ! type -p sudo >/dev/null; then
1957 warning "$(gettext "Cannot find the %s binary. Will use %s to acquire root privileges.")" "sudo" "su"
1961 # fakeroot - building as non-root user
1962 if check_buildenv "fakeroot" "y" && (( EUID > 0 )); then
1963 if ! type -p fakeroot >/dev/null; then
1964 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
1965 ret=1
1969 # gpg - package signing
1970 if [[ $SIGNPKG == 'y' ]] || { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; }; then
1971 if ! type -p gpg >/dev/null; then
1972 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
1973 ret=1
1977 # gpg - source verification
1978 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
1979 if ! type -p gpg >/dev/null; then
1980 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
1981 ret=1
1985 # openssl - checksum operations
1986 if (( ! SKIPCHECKSUMS )); then
1987 if ! type -p openssl >/dev/null; then
1988 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
1989 ret=1
1993 # upx - binary compression
1994 if check_option "upx" "y"; then
1995 if ! type -p upx >/dev/null; then
1996 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
1997 ret=1
2001 # distcc - compilation with distcc
2002 if check_buildenv "distcc" "y" && ! check_option "distcc" "n" ]]; then
2003 if ! type -p distcc >/dev/null; then
2004 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
2005 ret=1
2009 # ccache - compilation with ccache
2010 if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
2011 if ! type -p ccache >/dev/null; then
2012 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
2013 ret=1
2017 # strip - strip symbols from binaries/libraries
2018 if check_option "strip" "y"; then
2019 if ! type -p strip >/dev/null; then
2020 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
2021 ret=1
2025 # gzip - compressig man and info pages
2026 if check_option "zipman" "y"; then
2027 if ! type -p gzip >/dev/null; then
2028 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
2029 ret=1
2033 return $ret
2036 backup_package_variables() {
2037 local var
2038 for var in ${splitpkg_overrides[@]}; do
2039 local indirect="${var}_backup"
2040 eval "${indirect}=(\"\${$var[@]}\")"
2041 done
2044 restore_package_variables() {
2045 local var
2046 for var in ${splitpkg_overrides[@]}; do
2047 local indirect="${var}_backup"
2048 if [[ -n ${!indirect} ]]; then
2049 eval "${var}=(\"\${$indirect[@]}\")"
2050 else
2051 unset ${var}
2053 done
2056 run_split_packaging() {
2057 local pkgname_backup=${pkgname[@]}
2058 for pkgname in ${pkgname_backup[@]}; do
2059 pkgdir="$pkgdir/$pkgname"
2060 mkdir -p "$pkgdir"
2061 chmod a-s "$pkgdir"
2062 backup_package_variables
2063 run_package $pkgname
2064 tidy_install
2065 create_package $pkgname
2066 restore_package_variables
2067 pkgdir="${pkgdir%/*}"
2068 done
2069 pkgname=${pkgname_backup[@]}
2072 # Canonicalize a directory path if it exists
2073 canonicalize_path() {
2074 local path="$1";
2076 if [[ -d $path ]]; then
2078 cd_safe "$path"
2079 pwd -P
2081 else
2082 printf "%s\n" "$path"
2086 m4_include(library/parseopts.sh)
2088 usage() {
2089 printf "makepkg (pacman) %s\n" "$makepkg_version"
2090 echo
2091 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
2092 echo
2093 printf -- "$(gettext "Options:")\n"
2094 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
2095 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
2096 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
2097 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
2098 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
2099 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
2100 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
2101 printf -- "$(gettext " -i, --install Install package after successful build")\n"
2102 printf -- "$(gettext " -L, --log Log package build process")\n"
2103 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
2104 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
2105 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
2106 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
2107 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
2108 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
2109 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
2110 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
2111 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
2112 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
2113 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
2114 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
2115 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
2116 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
2117 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
2118 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
2119 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
2120 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
2121 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
2122 echo
2123 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
2124 echo
2125 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
2126 printf -- "$(gettext " --asdeps Install packages as non-explicitly installed")\n"
2127 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
2128 echo
2129 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
2130 echo
2133 version() {
2134 printf "makepkg (pacman) %s\n" "$makepkg_version"
2135 printf -- "$(gettext "\
2136 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
2137 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
2138 This is free software; see the source for copying conditions.\n\
2139 There is NO WARRANTY, to the extent permitted by law.\n")"
2142 # PROGRAM START
2144 # determine whether we have gettext; make it a no-op if we do not
2145 if ! type -p gettext >/dev/null; then
2146 gettext() {
2147 printf "%s\n" "$@"
2151 ARGLIST=("$@")
2153 # Parse Command Line Options.
2154 OPT_SHORT="AcdefFghiLmop:rRsSV"
2155 OPT_LONG=('allsource' 'asroot' 'check' 'clean' 'config:' 'force' 'geninteg'
2156 'help' 'ignorearch' 'install' 'key:' 'log' 'nobuild' 'nocolor'
2157 'nocheck' 'nodeps' 'noextract' 'nosign' 'pkg:' 'repackage' 'rmdeps'
2158 'skipchecksums' 'skipinteg' 'skippgpcheck' 'skippgpcheck' 'sign'
2159 'source' 'syncdeps' 'version')
2161 # Pacman Options
2162 OPT_LONG+=('asdeps' 'noconfirm' 'noprogressbar')
2164 if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
2165 exit 1 # E_INVALID_OPTION;
2167 set -- "${OPTRET[@]}"
2168 unset OPT_SHORT OPT_LONG OPTRET
2170 while true; do
2171 case "$1" in
2172 # Pacman Options
2173 --asdeps) ASDEPS=1;;
2174 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
2175 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
2177 # Makepkg Options
2178 --allsource) SOURCEONLY=2 ;;
2179 --asroot) ASROOT=1 ;;
2180 -A|--ignorearch) IGNOREARCH=1 ;;
2181 -c|--clean) CLEANUP=1 ;;
2182 --check) RUN_CHECK='y' ;;
2183 --config) shift; MAKEPKG_CONF=$1 ;;
2184 -d|--nodeps) NODEPS=1 ;;
2185 -e|--noextract) NOEXTRACT=1 ;;
2186 -f|--force) FORCE=1 ;;
2187 -F) INFAKEROOT=1 ;;
2188 -g|--geninteg) GENINTEG=1 ;;
2189 -i|--install) INSTALL=1 ;;
2190 --key) shift; GPGKEY=$1 ;;
2191 -L|--log) LOGGING=1 ;;
2192 -m|--nocolor) USE_COLOR='n' ;;
2193 --nocheck) RUN_CHECK='n' ;;
2194 --nosign) SIGNPKG='n' ;;
2195 -o|--nobuild) NOBUILD=1 ;;
2196 -p) shift; BUILDFILE=$1 ;;
2197 --pkg) shift; IFS=, read -ra p <<<"$1"; PKGLIST+=("${p[@]}"); unset p ;;
2198 -r|--rmdeps) RMDEPS=1 ;;
2199 -R|--repackage) REPKG=1 ;;
2200 --skipchecksums) SKIPCHECKSUMS=1 ;;
2201 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
2202 --skippgpcheck) SKIPPGPCHECK=1;;
2203 --sign) SIGNPKG='y' ;;
2204 -s|--syncdeps) DEP_BIN=1 ;;
2205 -S|--source) SOURCEONLY=1 ;;
2207 -h|--help) usage; exit 0 ;; # E_OK
2208 -V|--version) version; exit 0 ;; # E_OK
2210 --) OPT_IND=0; shift; break 2;;
2211 esac
2212 shift
2213 done
2215 # setup signal traps
2216 trap 'clean_up' 0
2217 for signal in TERM HUP QUIT; do
2218 trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
2219 done
2220 trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT
2221 trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR
2223 # preserve environment variables and canonicalize path
2224 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
2225 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
2226 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
2227 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
2228 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
2229 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
2230 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
2231 [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
2233 # default config is makepkg.conf
2234 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
2236 # Source the config file; fail if it is not found
2237 if [[ -r $MAKEPKG_CONF ]]; then
2238 source_safe "$MAKEPKG_CONF"
2239 else
2240 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
2241 plain "$(gettext "Aborting...")"
2242 exit 1 # $E_CONFIG_ERROR
2245 # Source user-specific makepkg.conf overrides, but only if no override config
2246 # file was specified
2247 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
2248 source_safe ~/.makepkg.conf
2251 # set pacman command if not already defined
2252 PACMAN=${PACMAN:-pacman}
2254 # check if messages are to be printed using color
2255 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2256 if [[ -t 2 && ! $USE_COLOR = "n" ]] && check_buildenv "color" "y"; then
2257 # prefer terminal safe colored and bold text when tput is supported
2258 if tput setaf 0 &>/dev/null; then
2259 ALL_OFF="$(tput sgr0)"
2260 BOLD="$(tput bold)"
2261 BLUE="${BOLD}$(tput setaf 4)"
2262 GREEN="${BOLD}$(tput setaf 2)"
2263 RED="${BOLD}$(tput setaf 1)"
2264 YELLOW="${BOLD}$(tput setaf 3)"
2265 else
2266 ALL_OFF="\e[1;0m"
2267 BOLD="\e[1;1m"
2268 BLUE="${BOLD}\e[1;34m"
2269 GREEN="${BOLD}\e[1;32m"
2270 RED="${BOLD}\e[1;31m"
2271 YELLOW="${BOLD}\e[1;33m"
2274 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2276 # override settings with an environment variable for batch processing
2277 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2278 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2279 if [[ ! -d $BUILDDIR ]]; then
2280 if ! mkdir -p "$BUILDDIR"; then
2281 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2282 plain "$(gettext "Aborting...")"
2283 exit 1
2285 chmod a-s "$BUILDDIR"
2287 if [[ ! -w $BUILDDIR ]]; then
2288 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2289 plain "$(gettext "Aborting...")"
2290 exit 1
2293 PKGDEST=${_PKGDEST:-$PKGDEST}
2294 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2295 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2296 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2297 plain "$(gettext "Aborting...")"
2298 exit 1
2301 SRCDEST=${_SRCDEST:-$SRCDEST}
2302 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2303 if [[ ! -w $SRCDEST ]] ; then
2304 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2305 plain "$(gettext "Aborting...")"
2306 exit 1
2309 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2310 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2311 if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then
2312 error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
2313 plain "$(gettext "Aborting...")"
2314 exit 1
2317 PKGEXT=${_PKGEXT:-$PKGEXT}
2318 SRCEXT=${_SRCEXT:-$SRCEXT}
2319 GPGKEY=${_GPGKEY:-$GPGKEY}
2320 PACKAGER=${_PACKAGER:-$PACKAGER}
2322 if (( ! INFAKEROOT )); then
2323 if (( EUID == 0 && ! ASROOT )); then
2324 # Warn those who like to live dangerously.
2325 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2326 catastrophic damage to your system. If you wish to run as root, please\n\
2327 use the %s option.")" "makepkg" "--asroot"
2328 exit 1 # $E_USER_ABORT
2329 elif (( EUID > 0 && ASROOT )); then
2330 # Warn those who try to use the --asroot option when they are not root
2331 error "$(gettext "The %s option is meant for the root user only. Please\n\
2332 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2333 exit 1 # $E_USER_ABORT
2334 elif (( EUID > 0 )) && ! check_buildenv "fakeroot" "y"; then
2335 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2336 ownership of the packaged files. Try using the %s environment by\n\
2337 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2338 sleep 1
2340 else
2341 if [[ -z $FAKEROOTKEY ]]; then
2342 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2343 exit 1 # TODO: error code
2347 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2348 unset md5sums replaces depends conflicts backup source install changelog build
2349 unset makedepends optdepends options noextract
2351 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2352 if [[ ! -f $BUILDFILE ]]; then
2353 if [[ -t 0 ]]; then
2354 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2355 exit 1
2356 else
2357 # PKGBUILD passed through a pipe
2358 BUILDFILE=/dev/stdin
2359 source_safe "$BUILDFILE"
2361 else
2362 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2363 if [[ -n $crlftest ]]; then
2364 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2365 exit 1
2368 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2369 BUILDFILE="$startdir/$BUILDFILE"
2371 source_safe "$BUILDFILE"
2374 # set defaults if they weren't specified in buildfile
2375 pkgbase=${pkgbase:-${pkgname[0]}}
2376 epoch=${epoch:-0}
2378 if [[ $BUILDDIR = "$startdir" ]]; then
2379 srcdir="$BUILDDIR/src"
2380 pkgdir="$BUILDDIR/pkg"
2381 else
2382 srcdir="$BUILDDIR/$pkgbase/src"
2383 pkgdir="$BUILDDIR/$pkgbase/pkg"
2386 if (( GENINTEG )); then
2387 mkdir -p "$srcdir"
2388 chmod a-s "$srcdir"
2389 cd_safe "$srcdir"
2390 download_sources fast
2391 generate_checksums
2392 exit 0 # $E_OK
2395 # check the PKGBUILD for some basic requirements
2396 check_sanity || exit 1
2398 # check we have the software required to process the PKGBUILD
2399 check_software || exit 1
2401 if (( ${#pkgname[@]} > 1 )); then
2402 SPLITPKG=1
2405 # test for available PKGBUILD functions
2406 if declare -f prepare >/dev/null; then
2407 PREPAREFUNC=1
2409 if declare -f build >/dev/null; then
2410 BUILDFUNC=1
2412 if declare -f check >/dev/null; then
2413 # "Hide" check() function if not going to be run
2414 if [[ $RUN_CHECK = 'y' ]] || { ! check_buildenv "check" "n" && [[ $RUN_CHECK != "n" ]]; }; then
2415 CHECKFUNC=1
2418 if declare -f package >/dev/null; then
2419 PKGFUNC=1
2420 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2421 SPLITPKG=1
2424 if [[ -n "${PKGLIST[@]}" ]]; then
2425 unset pkgname
2426 pkgname=("${PKGLIST[@]}")
2429 # check if gpg signature is to be created and if signing key is valid
2430 if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then
2431 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2432 if [[ ! -z $GPGKEY ]]; then
2433 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2434 else
2435 error "$(gettext "There is no key in your keyring.")"
2437 exit 1
2442 if (( ! SPLITPKG )); then
2443 fullver=$(get_full_version)
2444 pkgarch=$(get_pkg_arch)
2445 if [[ -f $PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT} ]] \
2446 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2447 if (( INSTALL )); then
2448 warning "$(gettext "A package has already been built, installing existing package...")"
2449 install_package
2450 exit $?
2451 else
2452 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2453 exit 1
2456 else
2457 allpkgbuilt=1
2458 somepkgbuilt=0
2459 for pkg in ${pkgname[@]}; do
2460 fullver=$(get_full_version $pkg)
2461 pkgarch=$(get_pkg_arch $pkg)
2462 if [[ -f $PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT} ]]; then
2463 somepkgbuilt=1
2464 else
2465 allpkgbuilt=0
2467 done
2468 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2469 if (( allpkgbuilt )); then
2470 if (( INSTALL )); then
2471 warning "$(gettext "The package group has already been built, installing existing packages...")"
2472 install_package
2473 exit $?
2474 else
2475 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2476 exit 1
2479 if (( somepkgbuilt )); then
2480 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2481 exit 1
2484 unset allpkgbuilt somepkgbuilt
2487 # Run the bare minimum in fakeroot
2488 if (( INFAKEROOT )); then
2489 if (( SOURCEONLY )); then
2490 create_srcpackage
2491 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2492 exit 0 # $E_OK
2495 if (( ! SPLITPKG )); then
2496 if (( ! PKGFUNC )); then
2497 if (( ! REPKG )); then
2498 if (( BUILDFUNC )); then
2499 run_build
2500 (( CHECKFUNC )) && run_check
2501 tidy_install
2503 else
2504 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2505 plain "$(gettext "File permissions may not be preserved.")"
2507 else
2508 run_package
2509 tidy_install
2511 create_package
2512 else
2513 run_split_packaging
2516 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2517 exit 0 # $E_OK
2520 fullver=$(get_full_version)
2521 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2523 # if we are creating a source-only package, go no further
2524 if (( SOURCEONLY )); then
2525 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2526 && (( ! FORCE )); then
2527 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2528 exit 1
2531 # Get back to our src directory so we can begin with sources.
2532 mkdir -p "$srcdir"
2533 chmod a-s "$srcdir"
2534 cd_safe "$srcdir"
2535 if (( SOURCEONLY == 2 )); then
2536 download_sources
2537 elif ( (( ! SKIPCHECKSUMS )) || \
2538 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ); then
2539 download_sources fast
2541 check_source_integrity
2542 cd_safe "$startdir"
2544 # if we are root or if fakeroot is not enabled, then we don't use it
2545 if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
2546 create_srcpackage
2547 else
2548 enter_fakeroot
2551 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2552 exit 0
2555 if (( NODEPS || (NOBUILD && !DEP_BIN ) )); then
2556 # no warning message needed for nobuild
2557 if (( NODEPS )); then
2558 warning "$(gettext "Skipping dependency checks.")"
2560 elif type -p "${PACMAN%% *}" >/dev/null; then
2561 if (( RMDEPS && ! INSTALL )); then
2562 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2564 deperr=0
2566 msg "$(gettext "Checking runtime dependencies...")"
2567 resolve_deps ${depends[@]} || deperr=1
2569 if (( RMDEPS && INSTALL )); then
2570 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2573 msg "$(gettext "Checking buildtime dependencies...")"
2574 resolve_deps ${makedepends[@]} || deperr=1
2576 if (( CHECKFUNC )); then
2577 resolve_deps ${checkdepends[@]} || deperr=1
2580 if (( RMDEPS )); then
2581 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2584 if (( deperr )); then
2585 error "$(gettext "Could not resolve all dependencies.")"
2586 exit 1
2588 else
2589 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2592 # ensure we have a sane umask set
2593 umask 0022
2595 # get back to our src directory so we can begin with sources
2596 mkdir -p "$srcdir"
2597 chmod a-s "$srcdir"
2598 cd_safe "$srcdir"
2600 if (( NOEXTRACT )); then
2601 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2602 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2603 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2605 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2606 error "$(gettext "The source directory is empty, there is nothing to build!")"
2607 plain "$(gettext "Aborting...")"
2608 exit 1
2610 elif (( REPKG )); then
2611 if (( ! PKGFUNC && ! SPLITPKG )) \
2612 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2613 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2614 plain "$(gettext "Aborting...")"
2615 exit 1
2617 else
2618 download_sources
2619 check_source_integrity
2620 extract_sources
2621 if (( PREPAREFUNC )); then
2622 run_prepare
2626 if (( NOBUILD )); then
2627 msg "$(gettext "Sources are ready.")"
2628 exit 0 #E_OK
2629 else
2630 # check for existing pkg directory; don't remove if we are repackaging
2631 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2632 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2633 rm -rf "$pkgdir"
2635 mkdir -p "$pkgdir"
2636 chmod a-s "$pkgdir"
2637 cd_safe "$startdir"
2639 # if we are root or if fakeroot is not enabled, then we don't use it
2640 if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
2641 if (( ! REPKG )); then
2642 (( BUILDFUNC )) && run_build
2643 (( CHECKFUNC )) && run_check
2645 if (( ! SPLITPKG )); then
2646 if (( PKGFUNC )); then
2647 run_package
2648 tidy_install
2649 else
2650 if (( ! REPKG )); then
2651 tidy_install
2652 else
2653 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2654 plain "$(gettext "File permissions may not be preserved.")"
2657 create_package
2658 else
2659 run_split_packaging
2661 else
2662 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2663 (( BUILDFUNC )) && run_build
2664 (( CHECKFUNC )) && run_check
2665 cd_safe "$startdir"
2668 enter_fakeroot
2672 fullver=$(get_full_version)
2673 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2675 install_package
2677 exit 0 #E_OK
2679 # vim: set ts=2 sw=2 noet: