Move important information up in -Si output
[pacman-ng.git] / scripts / makepkg.sh.in
blobdd4066bf8f88eaf58a113cf53f0d91791848c240
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 PKGVERFUNC=0
79 SPLITPKG=0
80 PKGLIST=()
81 SIGNPKG=''
83 # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call
84 # when dealing with svn/cvs/etc PKGBUILDs.
85 FORCE_VER=""
87 PACMAN_OPTS=
89 shopt -s extglob
91 ### SUBROUTINES ###
93 plain() {
94 local mesg=$1; shift
95 printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
98 msg() {
99 local mesg=$1; shift
100 printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
103 msg2() {
104 local mesg=$1; shift
105 printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
108 warning() {
109 local mesg=$1; shift
110 printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
113 error() {
114 local mesg=$1; shift
115 printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
120 # Special exit call for traps, Don't print any error messages when inside,
121 # the fakeroot call, the error message will be printed by the main call.
123 trap_exit() {
124 local signal=$1; shift
126 if (( ! INFAKEROOT )); then
127 echo
128 error "$@"
130 [[ -n $srclinks ]] && rm -rf "$srclinks"
132 # unset the trap for this signal, and then call the default handler
133 trap -- "$signal"
134 kill "-$signal" "$$"
139 # Clean up function. Called automatically when the script exits.
141 clean_up() {
142 local EXIT_CODE=$?
144 if (( INFAKEROOT )); then
145 # Don't clean up when leaving fakeroot, we're not done yet.
146 return
149 if (( ! EXIT_CODE && CLEANUP )); then
150 local pkg file
152 # If it's a clean exit and -c/--clean has been passed...
153 msg "$(gettext "Cleaning up...")"
154 rm -rf "$pkgdir" "$srcdir"
155 if [[ -n $pkgbase ]]; then
156 local fullver=$(get_full_version)
157 # Can't do this unless the BUILDSCRIPT has been sourced.
158 if (( BUILDFUNC )); then
159 rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"*
161 if (( CHECKFUNC )); then
162 rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
164 if (( PKGFUNC )); then
165 rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
166 elif (( SPLITPKG )); then
167 for pkg in ${pkgname[@]}; do
168 rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"*
169 done
172 # clean up dangling symlinks to packages
173 for pkg in ${pkgname[@]}; do
174 for file in ${pkg}-*-*-*{${PKGEXT},${SRCEXT}}; do
175 if [[ -h $file && ! -e $file ]]; then
176 rm -f "$file"
178 done
179 done
183 remove_deps
187 enter_fakeroot() {
188 msg "$(gettext "Entering %s environment...")" "fakeroot"
189 fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
193 # a source entry can have two forms :
194 # 1) "filename::http://path/to/file"
195 # 2) "http://path/to/file"
197 # Return the absolute filename of a source entry
198 get_filepath() {
199 local file="$(get_filename "$1")"
200 local proto="$(get_protocol "$1")"
202 case $proto in
203 git*|hg*|svn*)
204 if [[ -d "$startdir/$file" ]]; then
205 file="$startdir/$file"
206 elif [[ -d "$SRCDEST/$file" ]]; then
207 file="$SRCDEST/$file"
208 else
209 return 1
213 if [[ -f "$startdir/$file" ]]; then
214 file="$startdir/$file"
215 elif [[ -f "$SRCDEST/$file" ]]; then
216 file="$SRCDEST/$file"
217 else
218 return 1
221 esac
223 printf "%s\n" "$file"
226 # extract the filename from a source entry
227 get_filename() {
228 local netfile=$1
230 # if a filename is specified, use it
231 if [[ $netfile = *::* ]]; then
232 printf "%s\n" ${netfile%%::*}
233 return
236 local proto=$(get_protocol "$netfile")
238 case $proto in
239 git*|hg*|svn*)
240 filename=${netfile##*/}
241 filename=${filename%%#*}
242 # fall-through
244 git*)
245 filename=${filename%%.git*}
248 # if it is just an URL, we only keep the last component
249 filename="${netfile##*/}"
251 esac
252 printf "%s\n" "${filename}"
255 # extract the URL from a source entry
256 get_url() {
257 # strip an eventual filename
258 printf "%s\n" "${1#*::}"
261 # extract the protocol from a source entry - return "local" for local sources
262 get_protocol() {
263 if [[ $1 = *://* ]]; then
264 # strip leading filename
265 local proto="${1##*::}"
266 printf "%s\n" "${proto%%://*}"
267 else
268 printf "%s\n" local
272 get_downloadclient() {
273 local proto=$1
275 # loop through DOWNLOAD_AGENTS variable looking for protocol
276 local i
277 for i in "${DLAGENTS[@]}"; do
278 local handler="${i%%::*}"
279 if [[ $proto = "$handler" ]]; then
280 local agent="${i##*::}"
281 break
283 done
285 # if we didn't find an agent, return an error
286 if [[ -z $agent ]]; then
287 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
288 plain "$(gettext "Aborting...")"
289 exit 1 # $E_CONFIG_ERROR
292 # ensure specified program is installed
293 local program="${agent%% *}"
294 if [[ ! -x $program ]]; then
295 local baseprog="${program##*/}"
296 error "$(gettext "The download program %s is not installed.")" "$baseprog"
297 plain "$(gettext "Aborting...")"
298 exit 1 # $E_MISSING_PROGRAM
301 printf "%s\n" "$agent"
304 download_local() {
305 local netfile=$1
306 local filepath=$(get_filepath "$netfile")
308 if [[ -n "$filepath" ]]; then
309 msg2 "$(gettext "Found %s")" "${filepath##*/}"
310 rm -f "$srcdir/${filepath##*/}"
311 ln -s "$filepath" "$srcdir/"
312 continue
313 else
314 local filename=$(get_filename "$netfile")
315 error "$(gettext "%s was not found in the build directory and is not a URL.")" "$filename"
316 exit 1 # $E_MISSING_FILE
320 download_file() {
321 local netfile=$1
323 local filepath=$(get_filepath "$netfile")
324 if [[ -n "$filepath" ]]; then
325 msg2 "$(gettext "Found %s")" "${filepath##*/}"
326 rm -f "$srcdir/${filepath##*/}"
327 ln -s "$filepath" "$srcdir/"
328 return
331 local proto=$(get_protocol "$netfile")
333 # find the client we should use for this URL
334 local dlcmd
335 dlcmd=$(get_downloadclient "$proto") || exit $?
337 local filename=$(get_filename "$netfile")
338 local url=$(get_url "$netfile")
340 if [[ $proto = "scp" ]]; then
341 # scp downloads should not pass the protocol in the url
342 url="${url##*://}"
345 msg2 "$(gettext "Downloading %s...")" "$filename"
347 # temporary download file, default to last component of the URL
348 local dlfile="${url##*/}"
350 # replace %o by the temporary dlfile if it exists
351 if [[ $dlcmd = *%o* ]]; then
352 dlcmd=${dlcmd//\%o/\"$filename.part\"}
353 dlfile="$filename.part"
355 # add the URL, either in place of %u or at the end
356 if [[ $dlcmd = *%u* ]]; then
357 dlcmd=${dlcmd//\%u/\"$url\"}
358 else
359 dlcmd="$dlcmd \"$url\""
362 local ret=0
363 eval "$dlcmd || ret=\$?"
364 if (( ret )); then
365 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
366 error "$(gettext "Failure while downloading %s")" "$filename"
367 plain "$(gettext "Aborting...")"
368 exit 1
371 # rename the temporary download file to the final destination
372 if [[ $dlfile != "$filename" ]]; then
373 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$filename"
376 rm -f "$srcdir/$filename"
377 ln -s "$SRCDEST/$filename" "$srcdir/"
380 download_git() {
381 local netfile=$1
383 local fragment=${netfile##*#}
384 if [[ $fragment = "$netfile" ]]; then
385 unset fragment
388 local dir=$(get_filepath "$netfile")
389 [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"
391 local repo=${netfile##*/}
392 repo=${repo%%#*}
393 repo=${repo%%.git*}
395 local url=$(get_url "$netfile")
396 url=${url##*git+}
397 url=${url%%#*}
399 if [[ ! -d "$dir" ]]; then
400 msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git"
401 if ! git clone --mirror "$url" "$dir"; then
402 error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "git"
403 plain "$(gettext "Aborting...")"
404 exit 1
406 elif (( ! HOLDVER )); then
407 msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "git"
408 cd_safe "$dir"
409 if ! git fetch --all -p; then
410 # only warn on failure to allow offline builds
411 warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "git"
415 msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "git"
416 pushd "$srcdir" &>/dev/null
417 rm -rf "${dir##*/}"
419 if ! git clone "$dir"; then
420 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
421 plain "$(gettext "Aborting...")"
422 exit 1
425 cd_safe "${dir##*/}"
427 local ref
428 if [[ -n $fragment ]]; then
429 case ${fragment%%=*} in
430 commit|tag)
431 ref=${fragment##*=}
433 branch)
434 ref=origin/${fragment##*=}
437 error "$(gettext "Unrecognized reference: %s")" "${fragment}"
438 plain "$(gettext "Aborting...")"
439 exit 1
440 esac
443 if [[ -n $ref ]]; then
444 if ! git checkout -b makepkg $ref; then
445 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
446 plain "$(gettext "Aborting...")"
447 exit 1
451 popd &>/dev/null
454 download_hg() {
455 local netfile=$1
457 local fragment=${netfile##*#}
458 if [[ $fragment = "$netfile" ]]; then
459 unset fragment
462 local dir=$(get_filepath "$netfile")
463 [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"
465 local repo=${netfile##*/}
466 repo=${repo%%#*}
468 local url=$(get_url "$netfile")
469 url=${url##*hg+}
470 url=${url%%#*}
472 if [[ ! -d "$dir" ]]; then
473 msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "hg"
474 if ! hg clone "$url" "$dir"; then
475 error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "hg"
476 plain "$(gettext "Aborting...")"
477 exit 1
479 elif (( ! HOLDVER )); then
480 msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "hg"
481 cd_safe "$dir"
482 if ! hg pull -u; then
483 # only warn on failure to allow offline builds
484 warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "hg"
488 msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "hg"
489 pushd "$srcdir" &>/dev/null
490 rm -rf "${dir##*/}"
492 local ref
493 if [[ -n $fragment ]]; then
494 case ${fragment%%=*} in
495 branch|revision|tag)
496 ref=('-u' "${fragment##*=}")
499 error "$(gettext "Unrecognized reference: %s")" "${fragment}"
500 plain "$(gettext "Aborting...")"
501 exit 1
502 esac
505 if ! hg clone "${ref[@]}" "$dir" "${dir##*/}"; then
506 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "hg"
507 plain "$(gettext "Aborting...")"
508 exit 1
511 popd &>/dev/null
514 download_svn() {
515 local netfile=$1
517 local fragment=${netfile##*#}
518 if [[ $fragment = "$netfile" ]]; then
519 unset fragment
522 local dir=$(get_filepath "$netfile")
523 [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"
525 local repo=${netfile##*/}
526 repo=${repo%%#*}
528 local url=$(get_url "$netfile")
529 if [[ $url != svn+ssh* ]]; then
530 url=${url##*svn+}
532 url=${url%%#*}
534 if [[ ! -d "$dir" ]]; then
535 msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "svn"
536 if ! svn checkout --config-dir "$dir" "$url" "$dir"; then
537 error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "svn"
538 plain "$(gettext "Aborting...")"
539 exit 1
541 elif (( ! HOLDVER )); then
542 msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "svn"
543 cd_safe "$dir"
544 if ! svn update; then
545 # only warn on failure to allow offline builds
546 warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "svn"
550 msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "svn"
551 pushd "$srcdir" &>/dev/null
552 rm -rf "${dir##*/}"
554 local ref
555 if [[ -n $fragment ]]; then
556 case ${fragment%%=*} in
557 revision)
558 ref=('-r' "${fragment##*=}")
561 error "$(gettext "Unrecognized reference: %s")" "${fragment}"
562 plain "$(gettext "Aborting...")"
563 exit 1
564 esac
567 if ! svn export $(ref[@]) "$dir"; then
568 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "svn"
569 plain "$(gettext "Aborting...")"
572 popd &>/dev/null
575 download_sources() {
576 msg "$(gettext "Retrieving Sources...")"
578 local GET_VCS=1
579 if [[ $1 == "fast" ]]; then
580 GET_VCS=0
583 pushd "$SRCDEST" &>/dev/null
585 local netfile
586 for netfile in "${source[@]}"; do
587 local proto=$(get_protocol "$netfile")
589 case "$proto" in
590 local)
591 download_local "$netfile"
593 ftp|http|https|rsync|scp)
594 download_file "$netfile"
596 git*)
597 (( GET_VCS )) && download_git "$netfile"
599 hg*)
600 (( GET_VCS )) && download_hg "$netfile"
602 svn*)
603 (( GET_VCS )) && download_svn "$netfile"
606 error "$(gettext "Unknown download protocol: %s")" "$proto"
607 plain "$(gettext "Aborting...")"
608 exit 1
610 esac
611 done
613 if (( PKGVERFUNC && GET_VCS )); then
614 update_pkgver
615 check_pkgver || exit 1
616 check_build_status
619 popd &>/dev/null
622 # Automatically update pkgver variable if a pkgver() function is provided
623 # Re-sources the PKGBUILD afterwards to allow for other variables that use $pkgver
624 update_pkgver() {
625 newpkgver=$(run_function_safe pkgver)
627 if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then
628 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
629 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
630 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
631 source "$BUILDFILE"
632 else
633 warning "$(gettext "%s is not writeable -- pkgver will not be updated")" \
634 "$BUILDFILE"
639 # Print 'source not found' error message and exit makepkg
640 missing_source_file() {
641 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
642 plain "$(gettext "Aborting...")"
643 exit 1 # $E_MISSING_FILE
647 # usage : get_full_version( [$pkgname] )
648 # return : full version spec, including epoch (if necessary), pkgver, pkgrel
650 get_full_version() {
651 if [[ -z $1 ]]; then
652 if [[ $epoch ]] && (( ! $epoch )); then
653 printf "%s\n" "$pkgver-$pkgrel"
654 else
655 printf "%s\n" "$epoch:$pkgver-$pkgrel"
657 else
658 for i in pkgver pkgrel epoch; do
659 local indirect="${i}_override"
660 eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
661 [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
662 done
663 if (( ! $epoch_override )); then
664 printf "%s\n" "$pkgver_override-$pkgrel_override"
665 else
666 printf "%s\n" "$epoch_override:$pkgver_override-$pkgrel_override"
672 # usage : get_pkg_arch( [$pkgname] )
673 # return : architecture of the package
675 get_pkg_arch() {
676 if [[ -z $1 ]]; then
677 if [[ $arch = "any" ]]; then
678 printf "%s\n" "any"
679 else
680 printf "%s\n" "$CARCH"
682 else
683 local arch_override
684 eval $(declare -f package_$1 | sed -n 's/\(^[[:space:]]*arch=\)/arch_override=/p')
685 (( ${#arch_override[@]} == 0 )) && arch_override=("${arch[@]}")
686 if [[ $arch_override = "any" ]]; then
687 printf "%s\n" "any"
688 else
689 printf "%s\n" "$CARCH"
695 # Checks to see if options are present in makepkg.conf or PKGBUILD;
696 # PKGBUILD options always take precedence.
698 # usage : check_option( $option, $expected_val )
699 # return : 0 - matches expected
700 # 1 - does not match expected
701 # 127 - not found
703 check_option() {
704 in_opt_array "$1" ${options[@]}
705 case $? in
706 0) # assert enabled
707 [[ $2 = y ]]
708 return ;;
709 1) # assert disabled
710 [[ $2 = n ]]
711 return
712 esac
714 # fall back to makepkg.conf options
715 in_opt_array "$1" ${OPTIONS[@]}
716 case $? in
717 0) # assert enabled
718 [[ $2 = y ]]
719 return ;;
720 1) # assert disabled
721 [[ $2 = n ]]
722 return
723 esac
725 # not found
726 return 127
731 # Check if option is present in BUILDENV
733 # usage : check_buildenv( $option, $expected_val )
734 # return : 0 - matches expected
735 # 1 - does not match expected
736 # 127 - not found
738 check_buildenv() {
739 in_opt_array "$1" ${BUILDENV[@]}
740 case $? in
741 0) # assert enabled
742 [[ $2 = "y" ]]
743 return ;;
744 1) # assert disabled
745 [[ $2 = "n" ]]
746 return ;;
747 esac
749 # not found
750 return 127
755 # usage : in_opt_array( $needle, $haystack )
756 # return : 0 - enabled
757 # 1 - disabled
758 # 127 - not found
760 in_opt_array() {
761 local needle=$1; shift
763 local opt
764 for opt in "$@"; do
765 if [[ $opt = "$needle" ]]; then
766 # enabled
767 return 0
768 elif [[ $opt = "!$needle" ]]; then
769 # disabled
770 return 1
772 done
774 # not found
775 return 127
780 # usage : in_array( $needle, $haystack )
781 # return : 0 - found
782 # 1 - not found
784 in_array() {
785 local needle=$1; shift
786 local item
787 for item in "$@"; do
788 [[ $item = "$needle" ]] && return 0 # Found
789 done
790 return 1 # Not Found
793 source_has_signatures() {
794 local file
795 for file in "${source[@]}"; do
796 if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
797 return 0
799 done
800 return 1
803 run_pacman() {
804 local cmd
805 if [[ ! $1 = -@(T|Qq) ]]; then
806 cmd=("$PACMAN" $PACMAN_OPTS "$@")
807 else
808 cmd=("$PACMAN" "$@")
810 if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then
811 if type -p sudo >/dev/null; then
812 cmd=(sudo "${cmd[@]}")
813 else
814 cmd=(su root -c "$(printf '%q ' "${cmd[@]}")")
817 "${cmd[@]}"
820 check_deps() {
821 (( $# > 0 )) || return 0
823 local ret=0
824 local pmout
825 pmout=$(run_pacman -T "$@")
826 ret=$?
828 if (( ret == 127 )); then #unresolved deps
829 printf "%s\n" "$pmout"
830 elif (( ret )); then
831 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
832 return "$ret"
836 handle_deps() {
837 local R_DEPS_SATISFIED=0
838 local R_DEPS_MISSING=1
840 (( $# == 0 )) && return $R_DEPS_SATISFIED
842 local deplist="$*"
844 if (( ! DEP_BIN )); then
845 return $R_DEPS_MISSING
848 if (( DEP_BIN )); then
849 # install missing deps from binary packages (using pacman -S)
850 msg "$(gettext "Installing missing dependencies...")"
852 if ! run_pacman -S --asdeps $deplist; then
853 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
854 exit 1 # TODO: error code
858 # we might need the new system environment
859 # save our shell options and turn off extglob
860 local shellopts=$(shopt -p)
861 shopt -u extglob
862 source /etc/profile &>/dev/null
863 eval "$shellopts"
865 return $R_DEPS_SATISFIED
868 resolve_deps() {
869 local R_DEPS_SATISFIED=0
870 local R_DEPS_MISSING=1
872 # deplist cannot be declared like this: local deplist=$(foo)
873 # Otherwise, the return value will depend on the assignment.
874 local deplist
875 deplist="$(set +E; check_deps $*)" || exit 1
876 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
878 if handle_deps $deplist; then
879 # check deps again to make sure they were resolved
880 deplist="$(set +E; check_deps $*)" || exit 1
881 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
884 msg "$(gettext "Missing Dependencies:")"
885 local dep
886 for dep in $deplist; do
887 msg2 "$dep"
888 done
890 return $R_DEPS_MISSING
893 remove_deps() {
894 (( ! RMDEPS )) && return
896 # check for packages removed during dependency install (e.g. due to conflicts)
897 # removing all installed packages is risky in this case
898 if [[ -n $(grep -xvFf <(printf '%s\n' "${current_packagelist[@]}") \
899 <(printf '%s\n' "${original_packagelist[@]}") || true) ]]; then
900 warning "$(gettext "Failed to remove installed dependencies.")"
901 return 0
904 local deplist
905 deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \
906 <(printf "%s\n" "${current_pkglist[@]}") || true))
907 if [[ -z $deplist ]]; then
908 return
911 msg "Removing installed dependencies..."
912 # exit cleanly on failure to remove deps as package has been built successfully
913 if ! run_pacman -Rn ${deplist[@]}; then
914 warning "$(gettext "Failed to remove installed dependencies.")"
915 return 0
919 get_integlist() {
920 local integ
921 local integlist=()
923 for integ in md5 sha1 sha256 sha384 sha512; do
924 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
925 if [[ -n "$integrity_sums" ]]; then
926 integlist=(${integlist[@]} $integ)
928 done
930 if (( ${#integlist[@]} > 0 )); then
931 printf "%s\n" "${integlist[@]}"
932 else
933 printf "%s\n" "${INTEGRITY_CHECK[@]}"
937 generate_checksums() {
938 msg "$(gettext "Generating checksums for source files...")"
940 if ! type -p openssl >/dev/null; then
941 error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
942 exit 1 # $E_MISSING_PROGRAM
945 local integlist
946 if (( $# == 0 )); then
947 integlist=$(get_integlist)
948 else
949 integlist=$@
952 local integ
953 for integ in ${integlist[@]}; do
954 case "$integ" in
955 md5|sha1|sha256|sha384|sha512) : ;;
957 error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
958 exit 1;; # $E_CONFIG_ERROR
959 esac
961 local ct=0
962 local numsrc=${#source[@]}
963 printf "%s" "${integ}sums=("
965 local i
966 local indent=''
967 for (( i = 0; i < ${#integ} + 6; i++ )); do
968 indent="$indent "
969 done
971 local netfile
972 for netfile in "${source[@]}"; do
973 local proto sum
974 proto="$(get_protocol "$netfile")"
976 case $proto in
977 git*|hg*|svn*)
978 sum="SKIP"
981 local file
982 file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
983 sum="$(openssl dgst -${integ} "$file")"
984 sum=${sum##* }
986 esac
988 (( ct )) && printf "%s" "$indent"
989 printf "%s" "'$sum'"
990 ct=$(($ct+1))
991 (( $ct < $numsrc )) && echo
992 done
994 echo ")"
995 done
998 check_checksums() {
999 (( SKIPCHECKSUMS )) && return 0
1000 (( ! ${#source[@]} )) && return 0
1002 local correlation=0
1003 local integ required
1004 for integ in md5 sha1 sha256 sha384 sha512; do
1005 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
1006 if (( ${#integrity_sums[@]} == ${#source[@]} )); then
1007 msg "$(gettext "Validating source files with %s...")" "${integ}sums"
1008 correlation=1
1009 local errors=0
1010 local idx=0
1011 local file
1012 for file in "${source[@]}"; do
1013 local found=1
1014 file="$(get_filename "$file")"
1015 printf "%s" " $file ... " >&2
1017 if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then
1018 echo "$(gettext "Skipped")" >&2
1019 idx=$((idx + 1))
1020 continue
1023 if ! file="$(get_filepath "$file")"; then
1024 printf -- "$(gettext "NOT FOUND")\n" >&2
1025 errors=1
1026 found=0
1029 if (( $found )) ; then
1030 local expectedsum="${integrity_sums[idx],,}"
1031 local realsum="$(openssl dgst -${integ} "$file")"
1032 realsum="${realsum##* }"
1033 if [[ $expectedsum = "$realsum" ]]; then
1034 printf -- "$(gettext "Passed")\n" >&2
1035 else
1036 printf -- "$(gettext "FAILED")\n" >&2
1037 errors=1
1041 idx=$((idx + 1))
1042 done
1044 if (( errors )); then
1045 error "$(gettext "One or more files did not pass the validity check!")"
1046 exit 1 # TODO: error code
1048 elif (( ${#integrity_sums[@]} )); then
1049 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
1050 exit 1 # TODO: error code
1052 done
1054 if (( ! correlation )); then
1055 error "$(gettext "Integrity checks are missing.")"
1056 exit 1 # TODO: error code
1060 check_pgpsigs() {
1061 (( SKIPPGPCHECK )) && return 0
1062 ! source_has_signatures && return 0
1064 msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
1066 local file pubkey
1067 local warning=0
1068 local errors=0
1069 local statusfile=$(mktemp)
1071 for file in "${source[@]}"; do
1072 file="$(get_filename "$file")"
1073 if [[ ! $file = *.@(sig?(n)|asc) ]]; then
1074 continue
1077 printf " %s ... " "${file%.*}" >&2
1079 if ! file="$(get_filepath "$file")"; then
1080 printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
1081 errors=1
1082 continue
1085 if ! sourcefile="$(get_filepath "${file%.*}")"; then
1086 printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
1087 errors=1
1088 continue
1091 if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
1092 printf '%s' "$(gettext "FAILED")" >&2
1093 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then
1094 printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
1095 warnings=1
1096 else
1097 errors=1
1099 printf '\n' >&2
1100 else
1101 if grep -q "REVKEYSIG" "$statusfile"; then
1102 printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2
1103 errors=1
1104 else
1105 printf '%s' "$(gettext "Passed")" >&2
1106 if grep -q "EXPSIG" "$statusfile"; then
1107 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
1108 warnings=1
1109 elif grep -q "EXPKEYSIG" "$statusfile"; then
1110 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
1111 warnings=1
1114 printf '\n' >&2
1116 done
1118 rm -f "$statusfile"
1120 if (( errors )); then
1121 error "$(gettext "One or more PGP signatures could not be verified!")"
1122 exit 1
1125 if (( warnings )); then
1126 warning "$(gettext "Warnings have occurred while verifying the signatures.")"
1127 plain "$(gettext "Please make sure you really trust them.")"
1131 check_source_integrity() {
1132 if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
1133 warning "$(gettext "Skipping all source file integrity checks.")"
1134 elif (( SKIPCHECKSUMS )); then
1135 warning "$(gettext "Skipping verification of source file checksums.")"
1136 check_pgpsigs
1137 elif (( SKIPPGPCHECK )); then
1138 warning "$(gettext "Skipping verification of source file PGP signatures.")"
1139 check_checksums
1140 else
1141 check_checksums
1142 check_pgpsigs
1146 extract_sources() {
1147 msg "$(gettext "Extracting Sources...")"
1148 local netfile
1149 for netfile in "${source[@]}"; do
1150 local file=$(get_filename "$netfile")
1151 if in_array "$file" "${noextract[@]}"; then
1152 #skip source files in the noextract=() array
1153 # these are marked explicitly to NOT be extracted
1154 continue
1158 # fix flyspray #6246
1159 local file_type=$(file -bizL "$file")
1160 local ext=${file##*.}
1161 local cmd=''
1162 case "$file_type" in
1163 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
1164 cmd="bsdtar" ;;
1165 *application/x-gzip*)
1166 case "$ext" in
1167 gz|z|Z) cmd="gzip" ;;
1168 *) continue;;
1169 esac ;;
1170 *application/x-bzip*)
1171 case "$ext" in
1172 bz2|bz) cmd="bzip2" ;;
1173 *) continue;;
1174 esac ;;
1175 *application/x-xz*)
1176 case "$ext" in
1177 xz) cmd="xz" ;;
1178 *) continue;;
1179 esac ;;
1181 # See if bsdtar can recognize the file
1182 if bsdtar -tf "$file" -q '*' &>/dev/null; then
1183 cmd="bsdtar"
1184 else
1185 continue
1186 fi ;;
1187 esac
1189 local ret=0
1190 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
1191 if [[ $cmd = "bsdtar" ]]; then
1192 $cmd -xf "$file" || ret=$?
1193 else
1194 rm -f -- "${file%.*}"
1195 $cmd -dcf "$file" > "${file%.*}" || ret=$?
1197 if (( ret )); then
1198 error "$(gettext "Failed to extract %s")" "$file"
1199 plain "$(gettext "Aborting...")"
1200 exit 1
1202 done
1204 if (( EUID == 0 )); then
1205 # change perms of all source files to root user & root group
1206 chown -R 0:0 "$srcdir"
1210 error_function() {
1211 if [[ -p $logpipe ]]; then
1212 rm "$logpipe"
1214 # first exit all subshells, then print the error
1215 if (( ! BASH_SUBSHELL )); then
1216 error "$(gettext "A failure occurred in %s().")" "$1"
1217 plain "$(gettext "Aborting...")"
1218 remove_deps
1220 exit 2 # $E_BUILD_FAILED
1223 cd_safe() {
1224 if ! cd "$1"; then
1225 error "$(gettext "Failed to change to directory %s")" "$1"
1226 plain "$(gettext "Aborting...")"
1227 exit 1
1231 source_safe() {
1232 shopt -u extglob
1233 if ! source "$@"; then
1234 error "$(gettext "Failed to source %s")" "$1"
1235 exit 1
1237 shopt -s extglob
1240 run_function_safe() {
1241 local restoretrap
1243 set -e
1244 set -E
1246 restoretrap=$(trap -p ERR)
1247 trap 'error_function $pkgfunc' ERR
1249 run_function "$1"
1251 eval $restoretrap
1253 set +E
1254 set +e
1257 run_function() {
1258 if [[ -z $1 ]]; then
1259 return 1
1261 local pkgfunc="$1"
1263 # clear user-specified buildflags if requested
1264 if check_option "buildflags" "n"; then
1265 unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
1268 # clear user-specified makeflags if requested
1269 if check_option "makeflags" "n"; then
1270 unset MAKEFLAGS
1273 msg "$(gettext "Starting %s()...")" "$pkgfunc"
1274 cd_safe "$srcdir"
1276 # ensure all necessary build variables are exported
1277 export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
1278 # save our shell options so pkgfunc() can't override what we need
1279 local shellopts=$(shopt -p)
1281 local ret=0
1282 if (( LOGGING )); then
1283 local fullver=$(get_full_version)
1284 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
1285 if [[ -f $BUILDLOG ]]; then
1286 local i=1
1287 while true; do
1288 if [[ -f $BUILDLOG.$i ]]; then
1289 i=$(($i +1))
1290 else
1291 break
1293 done
1294 mv "$BUILDLOG" "$BUILDLOG.$i"
1297 # ensure overridden package variables survive tee with split packages
1298 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
1299 mkfifo "$logpipe"
1300 tee "$BUILDLOG" < "$logpipe" &
1301 local teepid=$!
1303 $pkgfunc &>"$logpipe"
1305 wait $teepid
1306 rm "$logpipe"
1307 else
1308 $pkgfunc 2>&1
1310 # reset our shell options
1311 eval "$shellopts"
1314 run_prepare() {
1315 run_function_safe "prepare"
1318 run_build() {
1319 # use distcc if it is requested (check buildenv and PKGBUILD opts)
1320 if check_buildenv "distcc" "y" && ! check_option "distc" "n"; then
1321 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
1322 export DISTCC_HOSTS
1325 # use ccache if it is requested (check buildenv and PKGBUILD opts)
1326 if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
1327 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
1330 run_function_safe "build"
1333 run_check() {
1334 run_function_safe "check"
1337 run_package() {
1338 local pkgfunc
1339 if [[ -z $1 ]]; then
1340 pkgfunc="package"
1341 else
1342 pkgfunc="package_$1"
1345 run_function_safe "$pkgfunc"
1348 tidy_install() {
1349 cd_safe "$pkgdir"
1350 msg "$(gettext "Tidying install...")"
1352 if check_option "docs" "n" && [[ -n ${DOC_DIRS[*]} ]]; then
1353 msg2 "$(gettext "Removing doc files...")"
1354 rm -rf -- ${DOC_DIRS[@]}
1357 if check_option "purge" "y" && [[ -n ${PURGE_TARGETS[*]} ]]; then
1358 msg2 "$(gettext "Purging unwanted files...")"
1359 local pt
1360 for pt in "${PURGE_TARGETS[@]}"; do
1361 if [[ ${pt} = "${pt//\/}" ]]; then
1362 find . ! -type d -name "${pt}" -exec rm -f -- '{}' \;
1363 else
1364 rm -f ${pt}
1366 done
1369 if check_option "zipman" "y" && [[ -n ${MAN_DIRS[*]} ]]; then
1370 msg2 "$(gettext "Compressing man and info pages...")"
1371 local file files inode link
1372 while read -rd ' ' inode; do
1373 read file
1374 find ${MAN_DIRS[@]} -type l 2>/dev/null |
1375 while read link ; do
1376 if [[ "${file}" -ef "${link}" ]] ; then
1377 rm -f "$link" "${link}.gz"
1378 if [[ ${file%/*} = ${link%/*} ]]; then
1379 ln -s -- "${file##*/}.gz" "${link}.gz"
1380 else
1381 ln -s -- "/${file}.gz" "${link}.gz"
1384 done
1385 if [[ -z ${files[$inode]} ]]; then
1386 files[$inode]=$file
1387 gzip -9 -f "$file"
1388 else
1389 rm -f "$file"
1390 ln "${files[$inode]}.gz" "${file}.gz"
1391 chmod 644 "${file}.gz"
1393 done < <(find ${MAN_DIRS[@]} -type f \! -name "*.gz" \! -name "*.bz2" \
1394 -exec @INODECMD@ '{}' + 2>/dev/null)
1397 if check_option "strip" "y"; then
1398 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1399 # make sure library stripping variables are defined to prevent excess stripping
1400 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1401 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1402 local binary
1403 find . -type f -perm -u+w -print0 2>/dev/null | while read -d '' binary ; do
1404 case "$(file -bi "$binary")" in
1405 *application/x-sharedlib*) # Libraries (.so)
1406 strip $STRIP_SHARED "$binary";;
1407 *application/x-archive*) # Libraries (.a)
1408 strip $STRIP_STATIC "$binary";;
1409 *application/x-executable*) # Binaries
1410 strip $STRIP_BINARIES "$binary";;
1411 esac
1412 done
1415 if check_option "libtool" "n"; then
1416 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1417 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1420 if check_option "emptydirs" "n"; then
1421 msg2 "$(gettext "Removing empty directories...")"
1422 find . -depth -type d -exec rmdir '{}' + 2>/dev/null
1425 if check_option "upx" "y"; then
1426 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1427 local binary
1428 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1429 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1430 upx $UPXFLAGS "$binary" &>/dev/null ||
1431 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1433 done
1437 find_libdepends() {
1438 local d sodepends;
1440 sodepends=0;
1441 for d in "${depends[@]}"; do
1442 if [[ $d = *.so ]]; then
1443 sodepends=1;
1444 break;
1446 done
1448 if (( sodepends == 0 )); then
1449 printf '%s\n' "${depends[@]}"
1450 return;
1453 local libdeps filename soarch sofile soname soversion;
1454 declare -A libdeps;
1456 while read filename; do
1457 # get architecture of the file; if soarch is empty it's not an ELF binary
1458 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1459 [[ -n "$soarch" ]] || continue
1461 # process all libraries needed by the binary
1462 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1464 # extract the library name: libfoo.so
1465 soname="${sofile%.so?(+(.+([0-9])))}".so
1466 # extract the major version: 1
1467 soversion="${sofile##*\.so\.}"
1469 if [[ ${libdeps[$soname]} ]]; then
1470 if [[ ${libdeps[$soname]} != *${soversion}-${soarch}* ]]; then
1471 libdeps[$soname]+=" ${soversion}-${soarch}"
1473 else
1474 libdeps[$soname]="${soversion}-${soarch}"
1476 done
1477 done < <(find "$pkgdir" -type f -perm -u+x)
1479 local libdepends v
1480 for d in "${depends[@]}"; do
1481 case "$d" in
1482 *.so)
1483 if [[ ${libdeps[$d]} ]]; then
1484 for v in ${libdeps[$d]}; do
1485 libdepends+=("$d=$v")
1486 done
1487 else
1488 warning "$(gettext "Library listed in %s is not required by any files: %s")" "'depends'" "$d"
1489 libdepends+=("$d")
1493 libdepends+=("$d")
1495 esac
1496 done
1498 printf '%s\n' "${libdepends[@]}"
1502 find_libprovides() {
1503 local p libprovides missing
1504 for p in "${provides[@]}"; do
1505 missing=0
1506 case "$p" in
1507 *.so)
1508 mapfile -t filename < <(find "$pkgdir" -type f -name $p\*)
1509 if [[ $filename ]]; then
1510 # packages may provide multiple versions of the same library
1511 for fn in "${filename[@]}"; do
1512 # check if we really have a shared object
1513 if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1514 # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1)
1515 local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1516 if [[ -z "$sofile" ]]; then
1517 warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p"
1518 libprovides+=("$p")
1519 continue
1522 # get the library architecture (32 or 64 bit)
1523 local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1525 # extract the library major version
1526 local soversion="${sofile##*\.so\.}"
1528 libprovides+=("${p}=${soversion}-${soarch}")
1529 else
1530 warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p"
1531 libprovides+=("$p")
1533 done
1534 else
1535 libprovides+=("$p")
1536 missing=1
1540 libprovides+=("$p")
1542 esac
1544 if (( missing )); then
1545 warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p"
1547 done
1549 printf '%s\n' "${libprovides[@]}"
1552 check_license() {
1553 # TODO maybe remove this at some point
1554 # warn if license array is not present or empty
1555 if [[ -z $license ]]; then
1556 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1557 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1561 write_pkginfo() {
1562 local builddate=$(date -u "+%s")
1563 if [[ -n $PACKAGER ]]; then
1564 local packager="$PACKAGER"
1565 else
1566 local packager="Unknown Packager"
1569 # btrfs's delayed allocation causes the stat buffers from the kernel to "lie"
1570 # to us momentarily and report 0 blocks allocated (which is how du calculates
1571 # size). Sleeping for a second here is about the dirtiest thing possible,
1572 # but avoids reporting entirely bogus install sizes.
1573 sleep 1
1574 local size="$(@DUPATH@ -sk)"
1575 size="$(( ${size%%[^0-9]*} * 1024 ))"
1577 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1578 echo "# Generated by makepkg $makepkg_version"
1579 if (( INFAKEROOT )); then
1580 echo "# using $(fakeroot -v)"
1582 echo "# $(LC_ALL=C date -u)"
1583 printf "pkgname = %s\n" "$1"
1584 (( SPLITPKG )) && echo pkgbase = $pkgbase
1585 echo "pkgver = $(get_full_version)"
1586 printf "pkgdesc = %s\n" "$pkgdesc"
1587 printf "url = %s\n" "$url"
1588 printf "builddate = %s\n" "$builddate"
1589 printf "packager = %s\n" "$packager"
1590 printf "size = %s\n" "$size"
1591 printf "arch = %s\n" "$pkgarch"
1593 mapfile -t provides < <(find_libprovides)
1594 mapfile -t depends < <(find_libdepends)
1596 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1597 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1598 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1599 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1600 [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
1601 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1602 [[ $depends ]] && printf "depend = %s\n" "${depends[@]}"
1603 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1604 [[ $makedepends ]] && printf "makedepend = %s\n" "${makedepends[@]}"
1605 [[ $checkdepends ]] && printf "checkdepend = %s\n" "${checkdepends[@]}"
1607 local it
1608 for it in "${packaging_options[@]}"; do
1609 check_option "$it" "y"
1610 case $? in
1612 printf "makepkgopt = %s\n" "$it"
1615 printf "makepkgopt = %s\n" "!$it"
1617 esac
1618 done
1620 check_license
1623 check_package() {
1624 cd_safe "$pkgdir"
1626 # check existence of backup files
1627 local file
1628 for file in "${backup[@]}"; do
1629 if [[ ! -f $file ]]; then
1630 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1632 done
1634 # check for references to the build and package directory
1635 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1636 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1638 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1639 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1644 create_package() {
1645 if [[ ! -d $pkgdir ]]; then
1646 error "$(gettext "Missing %s directory.")" "pkg/"
1647 plain "$(gettext "Aborting...")"
1648 exit 1 # $E_MISSING_PKGDIR
1651 check_package
1653 cd_safe "$pkgdir"
1654 msg "$(gettext "Creating package...")"
1656 local nameofpkg
1657 if [[ -z $1 ]]; then
1658 nameofpkg="$pkgname"
1659 else
1660 nameofpkg="$1"
1663 pkgarch=$(get_pkg_arch)
1665 write_pkginfo $nameofpkg > .PKGINFO
1667 local comp_files=('.PKGINFO')
1669 # check for changelog/install files
1670 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1671 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1673 if [[ -n ${!orig} ]]; then
1674 msg2 "$(gettext "Adding %s file...")" "$orig"
1675 cp "$startdir/${!orig}" "$dest"
1676 chmod 644 "$dest"
1677 comp_files+=("$dest")
1679 done
1681 # tar it up
1682 msg2 "$(gettext "Compressing package...")"
1684 local fullver=$(get_full_version)
1685 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${pkgarch}${PKGEXT}"
1686 local ret=0
1688 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1689 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1691 # when fileglobbing, we want * in an empty directory to expand to
1692 # the null string rather than itself
1693 shopt -s nullglob
1694 # TODO: Maybe this can be set globally for robustness
1695 shopt -s -o pipefail
1696 # bsdtar's gzip compression always saves the time stamp, making one
1697 # archive created using the same command line distinct from another.
1698 # Disable bsdtar compression and use gzip -n for now.
1699 bsdtar -cf - "${comp_files[@]}" * |
1700 case "$PKGEXT" in
1701 *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;;
1702 *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;;
1703 *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;;
1704 *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;;
1705 *tar) cat ;;
1706 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1707 "$PKGEXT"; cat ;;
1708 esac > "${pkg_file}" || ret=$?
1710 shopt -u nullglob
1711 shopt -u -o pipefail
1713 if (( ret )); then
1714 error "$(gettext "Failed to create package file.")"
1715 exit 1 # TODO: error code
1718 create_signature "$pkg_file"
1720 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1721 rm -f "${pkg_file/$PKGDEST/$startdir}"
1722 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1723 ret=$?
1724 if [[ -f $pkg_file.sig ]]; then
1725 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1726 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1730 if (( ret )); then
1731 warning "$(gettext "Failed to create symlink to package file.")"
1735 create_signature() {
1736 if [[ $SIGNPKG != 'y' ]]; then
1737 return
1739 local ret=0
1740 local filename="$1"
1741 msg "$(gettext "Signing package...")"
1743 local SIGNWITHKEY=""
1744 if [[ -n $GPGKEY ]]; then
1745 SIGNWITHKEY="-u ${GPGKEY}"
1747 # The signature will be generated directly in ascii-friendly format
1748 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1751 if (( ! ret )); then
1752 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1753 else
1754 warning "$(gettext "Failed to sign package file.")"
1758 create_srcpackage() {
1759 local ret=0
1760 msg "$(gettext "Creating source package...")"
1761 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1762 mkdir "${srclinks}"/${pkgbase}
1764 check_license
1766 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1767 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1769 local file
1770 for file in "${source[@]}"; do
1771 if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then
1772 local absfile
1773 absfile=$(get_filepath "$file") || missing_source_file "$file"
1774 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1775 ln -s "$absfile" "$srclinks/$pkgbase"
1777 done
1779 local i
1780 for i in 'changelog' 'install'; do
1781 local file
1782 while read -r file; do
1783 # evaluate any bash variables used
1784 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1785 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1786 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1787 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1789 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1790 done
1792 local TAR_OPT
1793 case "$SRCEXT" in
1794 *tar.gz) TAR_OPT="z" ;;
1795 *tar.bz2) TAR_OPT="j" ;;
1796 *tar.xz) TAR_OPT="J" ;;
1797 *tar.Z) TAR_OPT="Z" ;;
1798 *tar) TAR_OPT="" ;;
1799 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1800 "$SRCEXT" ;;
1801 esac
1803 local fullver=$(get_full_version)
1804 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1806 # tar it up
1807 msg2 "$(gettext "Compressing source package...")"
1808 cd_safe "${srclinks}"
1809 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1810 error "$(gettext "Failed to create source package file.")"
1811 exit 1 # TODO: error code
1814 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1815 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1816 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1817 ret=$?
1820 if (( ret )); then
1821 warning "$(gettext "Failed to create symlink to source package file.")"
1824 cd_safe "${startdir}"
1825 rm -rf "${srclinks}"
1828 install_package() {
1829 (( ! INSTALL )) && return
1831 if (( ! SPLITPKG )); then
1832 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1833 else
1834 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1837 local fullver pkgarch pkg pkglist
1838 (( ASDEPS )) && pkglist+=('--asdeps')
1840 for pkg in ${pkgname[@]}; do
1841 fullver=$(get_full_version $pkg)
1842 pkgarch=$(get_pkg_arch $pkg)
1843 pkglist+=("$PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT}")
1844 done
1846 if ! run_pacman -U ${pkglist[@]}; then
1847 warning "$(gettext "Failed to install built package(s).")"
1848 return 0
1852 check_sanity() {
1853 # check for no-no's in the build script
1854 local i
1855 local ret=0
1856 for i in 'pkgname' 'pkgrel'; do
1857 if [[ -z ${!i} ]]; then
1858 error "$(gettext "%s is not allowed to be empty.")" "$i"
1859 ret=1
1861 done
1863 for i in "${pkgname[@]}"; do
1864 if [[ ${i:0:1} = "-" ]]; then
1865 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1866 ret=1
1868 if [[ $i = *[^[:alnum:]+_.@-]* ]]; then
1869 error "$(gettext "%s contains invalid characters: '%s'")" \
1870 'pkgname' "${pkgname//[[:alnum:]+_.@-]}"
1871 ret=1
1873 done
1875 if [[ ${pkgbase:0:1} = "-" ]]; then
1876 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1877 ret=1
1880 if (( ! PKGVERFUNC )) ; then
1881 check_pkgver || ret=1
1884 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1885 while IFS='=' read -r _ i; do
1886 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1887 if [[ $i != +([0-9])?(.+([0-9])) ]]; then
1888 error "$(gettext "%s must be a decimal.")" "pkgrel"
1889 return 1
1891 done || ret=1
1893 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1894 while IFS='=' read -r _ i; do
1895 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1896 if [[ $i != *([[:digit:]]) ]]; then
1897 error "$(gettext "%s must be an integer.")" "epoch"
1898 return 1
1900 done || ret=1
1902 if [[ $arch != 'any' ]]; then
1903 if ! in_array $CARCH ${arch[@]}; then
1904 if (( ! IGNOREARCH )); then
1905 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1906 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1907 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1908 ret=1
1913 if (( ${#pkgname[@]} > 1 )); then
1914 for i in ${pkgname[@]}; do
1915 local arch_list=""
1916 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1917 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1918 if ! in_array $CARCH ${arch_list[@]}; then
1919 if (( ! IGNOREARCH )); then
1920 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1921 ret=1
1925 done
1928 local provides_list=()
1929 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1930 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1931 for i in ${provides_list[@]}; do
1932 if [[ $i == *['<>']* ]]; then
1933 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1934 ret=1
1936 done
1938 local backup_list=()
1939 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1940 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1941 for i in "${backup_list[@]}"; do
1942 if [[ ${i:0:1} = "/" ]]; then
1943 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1944 ret=1
1946 done
1948 local optdepends_list=()
1949 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1950 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1951 for i in "${optdepends_list[@]}"; do
1952 local pkg=${i%%:[[:space:]]*}
1953 # the '-' character _must_ be first or last in the character range
1954 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1955 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1956 ret=1
1958 done
1960 for i in 'changelog' 'install'; do
1961 local file
1962 while read -r file; do
1963 # evaluate any bash variables used
1964 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1965 if [[ $file && ! -f $file ]]; then
1966 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1967 ret=1
1969 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1970 done
1972 local valid_options=1
1973 local known kopt options_list
1974 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1975 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1976 for i in ${options_list[@]}; do
1977 known=0
1978 # check if option matches a known option or its inverse
1979 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1980 if [[ ${i} = "${kopt}" || ${i} = "!${kopt}" ]]; then
1981 known=1
1983 done
1984 if (( ! known )); then
1985 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1986 valid_options=0
1988 done
1989 if (( ! valid_options )); then
1990 ret=1
1993 if (( ${#pkgname[@]} > 1 )); then
1994 for i in ${pkgname[@]}; do
1995 if ! declare -f package_${i} >/dev/null; then
1996 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1997 ret=1
1999 done
2002 for i in ${PKGLIST[@]}; do
2003 if ! in_array $i ${pkgname[@]}; then
2004 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
2005 ret=1
2007 done
2009 return $ret
2012 check_pkgver() {
2013 local ret=0
2015 if [[ -z ${pkgver} ]]; then
2016 error "$(gettext "%s is not allowed to be empty.")" "pkgver"
2017 ret=1
2020 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
2021 while IFS='=' read -r _ i; do
2022 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
2023 if [[ $i = *[[:space:]:-]* ]]; then
2024 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
2025 return 1
2027 done || ret=1
2029 return $ret
2032 check_software() {
2033 # check for needed software
2034 local ret=0
2036 # check for sudo if we will need it during makepkg execution
2037 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
2038 if ! type -p sudo >/dev/null; then
2039 warning "$(gettext "Cannot find the %s binary. Will use %s to acquire root privileges.")" "sudo" "su"
2043 # fakeroot - building as non-root user
2044 if check_buildenv "fakeroot" "y" && (( EUID > 0 )); then
2045 if ! type -p fakeroot >/dev/null; then
2046 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
2047 ret=1
2051 # gpg - package signing
2052 if [[ $SIGNPKG == 'y' ]] || { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; }; then
2053 if ! type -p gpg >/dev/null; then
2054 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
2055 ret=1
2059 # gpg - source verification
2060 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
2061 if ! type -p gpg >/dev/null; then
2062 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
2063 ret=1
2067 # openssl - checksum operations
2068 if (( ! SKIPCHECKSUMS )); then
2069 if ! type -p openssl >/dev/null; then
2070 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
2071 ret=1
2075 # upx - binary compression
2076 if check_option "upx" "y"; then
2077 if ! type -p upx >/dev/null; then
2078 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
2079 ret=1
2083 # distcc - compilation with distcc
2084 if check_buildenv "distcc" "y" && ! check_option "distcc" "n" ]]; then
2085 if ! type -p distcc >/dev/null; then
2086 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
2087 ret=1
2091 # ccache - compilation with ccache
2092 if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
2093 if ! type -p ccache >/dev/null; then
2094 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
2095 ret=1
2099 # strip - strip symbols from binaries/libraries
2100 if check_option "strip" "y"; then
2101 if ! type -p strip >/dev/null; then
2102 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
2103 ret=1
2107 # gzip - compressig man and info pages
2108 if check_option "zipman" "y"; then
2109 if ! type -p gzip >/dev/null; then
2110 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
2111 ret=1
2115 return $ret
2118 check_build_status() {
2119 if (( ! SPLITPKG )); then
2120 fullver=$(get_full_version)
2121 pkgarch=$(get_pkg_arch)
2122 if [[ -f $PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT} ]] \
2123 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2124 if (( INSTALL )); then
2125 warning "$(gettext "A package has already been built, installing existing package...")"
2126 install_package
2127 exit $?
2128 else
2129 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2130 exit 1
2133 else
2134 allpkgbuilt=1
2135 somepkgbuilt=0
2136 for pkg in ${pkgname[@]}; do
2137 fullver=$(get_full_version $pkg)
2138 pkgarch=$(get_pkg_arch $pkg)
2139 if [[ -f $PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT} ]]; then
2140 somepkgbuilt=1
2141 else
2142 allpkgbuilt=0
2144 done
2145 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2146 if (( allpkgbuilt )); then
2147 if (( INSTALL )); then
2148 warning "$(gettext "The package group has already been built, installing existing packages...")"
2149 install_package
2150 exit $?
2151 else
2152 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2153 exit 1
2156 if (( somepkgbuilt && ! PKGVERFUNC )); then
2157 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2158 exit 1
2161 unset allpkgbuilt somepkgbuilt
2165 backup_package_variables() {
2166 local var
2167 for var in ${splitpkg_overrides[@]}; do
2168 local indirect="${var}_backup"
2169 eval "${indirect}=(\"\${$var[@]}\")"
2170 done
2173 restore_package_variables() {
2174 local var
2175 for var in ${splitpkg_overrides[@]}; do
2176 local indirect="${var}_backup"
2177 if [[ -n ${!indirect} ]]; then
2178 eval "${var}=(\"\${$indirect[@]}\")"
2179 else
2180 unset ${var}
2182 done
2185 run_split_packaging() {
2186 local pkgname_backup=${pkgname[@]}
2187 for pkgname in ${pkgname_backup[@]}; do
2188 pkgdir="$pkgdir/$pkgname"
2189 mkdir -p "$pkgdir"
2190 chmod a-s "$pkgdir"
2191 backup_package_variables
2192 run_package $pkgname
2193 tidy_install
2194 create_package $pkgname
2195 restore_package_variables
2196 pkgdir="${pkgdir%/*}"
2197 done
2198 pkgname=${pkgname_backup[@]}
2201 # Canonicalize a directory path if it exists
2202 canonicalize_path() {
2203 local path="$1";
2205 if [[ -d $path ]]; then
2207 cd_safe "$path"
2208 pwd -P
2210 else
2211 printf "%s\n" "$path"
2215 m4_include(library/parseopts.sh)
2217 usage() {
2218 printf "makepkg (pacman) %s\n" "$makepkg_version"
2219 echo
2220 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
2221 echo
2222 printf -- "$(gettext "Options:")\n"
2223 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
2224 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
2225 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
2226 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
2227 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
2228 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
2229 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
2230 printf -- "$(gettext " -i, --install Install package after successful build")\n"
2231 printf -- "$(gettext " -L, --log Log package build process")\n"
2232 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
2233 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
2234 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
2235 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
2236 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
2237 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
2238 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
2239 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
2240 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
2241 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
2242 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
2243 printf -- "$(gettext " --holdver Do not update VCS sources")\n"
2244 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
2245 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
2246 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
2247 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
2248 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
2249 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
2250 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
2251 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
2252 echo
2253 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
2254 echo
2255 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
2256 printf -- "$(gettext " --asdeps Install packages as non-explicitly installed")\n"
2257 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
2258 echo
2259 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
2260 echo
2263 version() {
2264 printf "makepkg (pacman) %s\n" "$makepkg_version"
2265 printf -- "$(gettext "\
2266 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
2267 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
2268 This is free software; see the source for copying conditions.\n\
2269 There is NO WARRANTY, to the extent permitted by law.\n")"
2272 # PROGRAM START
2274 # determine whether we have gettext; make it a no-op if we do not
2275 if ! type -p gettext >/dev/null; then
2276 gettext() {
2277 printf "%s\n" "$@"
2281 ARGLIST=("$@")
2283 # Parse Command Line Options.
2284 OPT_SHORT="AcdefFghiLmop:rRsSV"
2285 OPT_LONG=('allsource' 'asroot' 'check' 'clean' 'config:' 'force' 'geninteg'
2286 'help' 'holdver' 'ignorearch' 'install' 'key:' 'log' 'nobuild' 'nocolor'
2287 'nocheck' 'nodeps' 'noextract' 'nosign' 'pkg:' 'repackage' 'rmdeps'
2288 'skipchecksums' 'skipinteg' 'skippgpcheck' 'skippgpcheck' 'sign'
2289 'source' 'syncdeps' 'version')
2291 # Pacman Options
2292 OPT_LONG+=('asdeps' 'noconfirm' 'noprogressbar')
2294 if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
2295 exit 1 # E_INVALID_OPTION;
2297 set -- "${OPTRET[@]}"
2298 unset OPT_SHORT OPT_LONG OPTRET
2300 while true; do
2301 case "$1" in
2302 # Pacman Options
2303 --asdeps) ASDEPS=1;;
2304 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
2305 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
2307 # Makepkg Options
2308 --allsource) SOURCEONLY=2 ;;
2309 --asroot) ASROOT=1 ;;
2310 -A|--ignorearch) IGNOREARCH=1 ;;
2311 -c|--clean) CLEANUP=1 ;;
2312 --check) RUN_CHECK='y' ;;
2313 --config) shift; MAKEPKG_CONF=$1 ;;
2314 -d|--nodeps) NODEPS=1 ;;
2315 -e|--noextract) NOEXTRACT=1 ;;
2316 -f|--force) FORCE=1 ;;
2317 -F) INFAKEROOT=1 ;;
2318 -g|--geninteg) GENINTEG=1 ;;
2319 --holdver) HOLDVER=1 ;;
2320 -i|--install) INSTALL=1 ;;
2321 --key) shift; GPGKEY=$1 ;;
2322 -L|--log) LOGGING=1 ;;
2323 -m|--nocolor) USE_COLOR='n' ;;
2324 --nocheck) RUN_CHECK='n' ;;
2325 --nosign) SIGNPKG='n' ;;
2326 -o|--nobuild) NOBUILD=1 ;;
2327 -p) shift; BUILDFILE=$1 ;;
2328 --pkg) shift; IFS=, read -ra p <<<"$1"; PKGLIST+=("${p[@]}"); unset p ;;
2329 -r|--rmdeps) RMDEPS=1 ;;
2330 -R|--repackage) REPKG=1 ;;
2331 --skipchecksums) SKIPCHECKSUMS=1 ;;
2332 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
2333 --skippgpcheck) SKIPPGPCHECK=1;;
2334 --sign) SIGNPKG='y' ;;
2335 -s|--syncdeps) DEP_BIN=1 ;;
2336 -S|--source) SOURCEONLY=1 ;;
2338 -h|--help) usage; exit 0 ;; # E_OK
2339 -V|--version) version; exit 0 ;; # E_OK
2341 --) OPT_IND=0; shift; break 2;;
2342 esac
2343 shift
2344 done
2346 # setup signal traps
2347 trap 'clean_up' 0
2348 for signal in TERM HUP QUIT; do
2349 trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
2350 done
2351 trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT
2352 trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR
2354 # preserve environment variables and canonicalize path
2355 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
2356 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
2357 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
2358 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
2359 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
2360 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
2361 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
2362 [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
2364 # default config is makepkg.conf
2365 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
2367 # Source the config file; fail if it is not found
2368 if [[ -r $MAKEPKG_CONF ]]; then
2369 source_safe "$MAKEPKG_CONF"
2370 else
2371 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
2372 plain "$(gettext "Aborting...")"
2373 exit 1 # $E_CONFIG_ERROR
2376 # Source user-specific makepkg.conf overrides, but only if no override config
2377 # file was specified
2378 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
2379 source_safe ~/.makepkg.conf
2382 # set pacman command if not already defined
2383 PACMAN=${PACMAN:-pacman}
2385 # check if messages are to be printed using color
2386 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2387 if [[ -t 2 && ! $USE_COLOR = "n" ]] && check_buildenv "color" "y"; then
2388 # prefer terminal safe colored and bold text when tput is supported
2389 if tput setaf 0 &>/dev/null; then
2390 ALL_OFF="$(tput sgr0)"
2391 BOLD="$(tput bold)"
2392 BLUE="${BOLD}$(tput setaf 4)"
2393 GREEN="${BOLD}$(tput setaf 2)"
2394 RED="${BOLD}$(tput setaf 1)"
2395 YELLOW="${BOLD}$(tput setaf 3)"
2396 else
2397 ALL_OFF="\e[1;0m"
2398 BOLD="\e[1;1m"
2399 BLUE="${BOLD}\e[1;34m"
2400 GREEN="${BOLD}\e[1;32m"
2401 RED="${BOLD}\e[1;31m"
2402 YELLOW="${BOLD}\e[1;33m"
2405 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2407 # override settings with an environment variable for batch processing
2408 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2409 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2410 if [[ ! -d $BUILDDIR ]]; then
2411 if ! mkdir -p "$BUILDDIR"; then
2412 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2413 plain "$(gettext "Aborting...")"
2414 exit 1
2416 chmod a-s "$BUILDDIR"
2418 if [[ ! -w $BUILDDIR ]]; then
2419 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2420 plain "$(gettext "Aborting...")"
2421 exit 1
2424 PKGDEST=${_PKGDEST:-$PKGDEST}
2425 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2426 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2427 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2428 plain "$(gettext "Aborting...")"
2429 exit 1
2432 SRCDEST=${_SRCDEST:-$SRCDEST}
2433 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2434 if [[ ! -w $SRCDEST ]] ; then
2435 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2436 plain "$(gettext "Aborting...")"
2437 exit 1
2440 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2441 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2442 if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then
2443 error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
2444 plain "$(gettext "Aborting...")"
2445 exit 1
2448 PKGEXT=${_PKGEXT:-$PKGEXT}
2449 SRCEXT=${_SRCEXT:-$SRCEXT}
2450 GPGKEY=${_GPGKEY:-$GPGKEY}
2451 PACKAGER=${_PACKAGER:-$PACKAGER}
2453 if (( ! INFAKEROOT )); then
2454 if (( EUID == 0 && ! ASROOT )); then
2455 # Warn those who like to live dangerously.
2456 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2457 catastrophic damage to your system. If you wish to run as root, please\n\
2458 use the %s option.")" "makepkg" "--asroot"
2459 exit 1 # $E_USER_ABORT
2460 elif (( EUID > 0 && ASROOT )); then
2461 # Warn those who try to use the --asroot option when they are not root
2462 error "$(gettext "The %s option is meant for the root user only. Please\n\
2463 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2464 exit 1 # $E_USER_ABORT
2465 elif (( EUID > 0 )) && ! check_buildenv "fakeroot" "y"; then
2466 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2467 ownership of the packaged files. Try using the %s environment by\n\
2468 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2469 sleep 1
2471 else
2472 if [[ -z $FAKEROOTKEY ]]; then
2473 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2474 exit 1 # TODO: error code
2478 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2479 unset md5sums replaces depends conflicts backup source install changelog build
2480 unset makedepends optdepends options noextract
2482 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2483 if [[ ! -f $BUILDFILE ]]; then
2484 if [[ -t 0 ]]; then
2485 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2486 exit 1
2487 else
2488 # PKGBUILD passed through a pipe
2489 BUILDFILE=/dev/stdin
2490 source_safe "$BUILDFILE"
2492 else
2493 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2494 if [[ -n $crlftest ]]; then
2495 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2496 exit 1
2499 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2500 BUILDFILE="$startdir/$BUILDFILE"
2502 source_safe "$BUILDFILE"
2505 # set defaults if they weren't specified in buildfile
2506 pkgbase=${pkgbase:-${pkgname[0]}}
2507 epoch=${epoch:-0}
2509 if [[ $BUILDDIR = "$startdir" ]]; then
2510 srcdir="$BUILDDIR/src"
2511 pkgdir="$BUILDDIR/pkg"
2512 else
2513 srcdir="$BUILDDIR/$pkgbase/src"
2514 pkgdir="$BUILDDIR/$pkgbase/pkg"
2517 if (( GENINTEG )); then
2518 mkdir -p "$srcdir"
2519 chmod a-s "$srcdir"
2520 cd_safe "$srcdir"
2521 download_sources fast
2522 generate_checksums
2523 exit 0 # $E_OK
2526 if declare -f pkgver >/dev/null; then
2527 PKGVERFUNC=1
2530 # check the PKGBUILD for some basic requirements
2531 check_sanity || exit 1
2533 # check we have the software required to process the PKGBUILD
2534 check_software || exit 1
2536 if (( ${#pkgname[@]} > 1 )); then
2537 SPLITPKG=1
2540 # test for available PKGBUILD functions
2541 if declare -f prepare >/dev/null; then
2542 PREPAREFUNC=1
2544 if declare -f build >/dev/null; then
2545 BUILDFUNC=1
2547 if declare -f check >/dev/null; then
2548 # "Hide" check() function if not going to be run
2549 if [[ $RUN_CHECK = 'y' ]] || { ! check_buildenv "check" "n" && [[ $RUN_CHECK != "n" ]]; }; then
2550 CHECKFUNC=1
2553 if declare -f package >/dev/null; then
2554 PKGFUNC=1
2555 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2556 SPLITPKG=1
2559 if [[ -n "${PKGLIST[@]}" ]]; then
2560 unset pkgname
2561 pkgname=("${PKGLIST[@]}")
2564 # check if gpg signature is to be created and if signing key is valid
2565 if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then
2566 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2567 if [[ ! -z $GPGKEY ]]; then
2568 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2569 else
2570 error "$(gettext "There is no key in your keyring.")"
2572 exit 1
2576 if (( ! PKGVERFUNC )); then
2577 check_build_status
2580 # Run the bare minimum in fakeroot
2581 if (( INFAKEROOT )); then
2582 if (( SOURCEONLY )); then
2583 create_srcpackage
2584 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2585 exit 0 # $E_OK
2588 if (( ! SPLITPKG )); then
2589 if (( ! PKGFUNC )); then
2590 if (( ! REPKG )); then
2591 if (( BUILDFUNC )); then
2592 run_build
2593 (( CHECKFUNC )) && run_check
2594 tidy_install
2596 else
2597 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2598 plain "$(gettext "File permissions may not be preserved.")"
2600 else
2601 run_package
2602 tidy_install
2604 create_package
2605 else
2606 run_split_packaging
2609 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2610 exit 0 # $E_OK
2613 fullver=$(get_full_version)
2614 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2616 # if we are creating a source-only package, go no further
2617 if (( SOURCEONLY )); then
2618 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2619 && (( ! FORCE )); then
2620 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2621 exit 1
2624 # Get back to our src directory so we can begin with sources.
2625 mkdir -p "$srcdir"
2626 chmod a-s "$srcdir"
2627 cd_safe "$srcdir"
2628 if (( SOURCEONLY == 2 )); then
2629 download_sources
2630 elif ( (( ! SKIPCHECKSUMS )) || \
2631 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ); then
2632 download_sources fast
2634 check_source_integrity
2635 cd_safe "$startdir"
2637 # if we are root or if fakeroot is not enabled, then we don't use it
2638 if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
2639 create_srcpackage
2640 else
2641 enter_fakeroot
2644 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2645 exit 0
2648 if (( NODEPS || (NOBUILD && !DEP_BIN ) )); then
2649 # no warning message needed for nobuild
2650 if (( NODEPS )); then
2651 warning "$(gettext "Skipping dependency checks.")"
2653 elif type -p "${PACMAN%% *}" >/dev/null; then
2654 if (( RMDEPS && ! INSTALL )); then
2655 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2657 deperr=0
2659 msg "$(gettext "Checking runtime dependencies...")"
2660 resolve_deps ${depends[@]} || deperr=1
2662 if (( RMDEPS && INSTALL )); then
2663 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2666 msg "$(gettext "Checking buildtime dependencies...")"
2667 resolve_deps ${makedepends[@]} || deperr=1
2669 if (( CHECKFUNC )); then
2670 resolve_deps ${checkdepends[@]} || deperr=1
2673 if (( RMDEPS )); then
2674 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2677 if (( deperr )); then
2678 error "$(gettext "Could not resolve all dependencies.")"
2679 exit 1
2681 else
2682 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2685 # ensure we have a sane umask set
2686 umask 0022
2688 # get back to our src directory so we can begin with sources
2689 mkdir -p "$srcdir"
2690 chmod a-s "$srcdir"
2691 cd_safe "$srcdir"
2693 if (( NOEXTRACT )); then
2694 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2695 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2696 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2698 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2699 error "$(gettext "The source directory is empty, there is nothing to build!")"
2700 plain "$(gettext "Aborting...")"
2701 exit 1
2703 elif (( REPKG )); then
2704 if (( ! PKGFUNC && ! SPLITPKG )) \
2705 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2706 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2707 plain "$(gettext "Aborting...")"
2708 exit 1
2710 else
2711 download_sources
2712 check_source_integrity
2713 extract_sources
2714 if (( PREPAREFUNC )); then
2715 run_prepare
2719 if (( NOBUILD )); then
2720 msg "$(gettext "Sources are ready.")"
2721 exit 0 #E_OK
2722 else
2723 # check for existing pkg directory; don't remove if we are repackaging
2724 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2725 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2726 rm -rf "$pkgdir"
2728 mkdir -p "$pkgdir"
2729 chmod a-s "$pkgdir"
2730 cd_safe "$startdir"
2732 # if we are root or if fakeroot is not enabled, then we don't use it
2733 if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
2734 if (( ! REPKG )); then
2735 (( BUILDFUNC )) && run_build
2736 (( CHECKFUNC )) && run_check
2738 if (( ! SPLITPKG )); then
2739 if (( PKGFUNC )); then
2740 run_package
2741 tidy_install
2742 else
2743 if (( ! REPKG )); then
2744 tidy_install
2745 else
2746 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2747 plain "$(gettext "File permissions may not be preserved.")"
2750 create_package
2751 else
2752 run_split_packaging
2754 else
2755 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2756 (( BUILDFUNC )) && run_build
2757 (( CHECKFUNC )) && run_check
2758 cd_safe "$startdir"
2761 enter_fakeroot
2765 fullver=$(get_full_version)
2766 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2768 install_package
2770 exit 0 #E_OK
2772 # vim: set ts=2 sw=2 noet: