makepkg: modify get_filepath to handle VCS sources
[pacman-ng.git] / scripts / makepkg.sh.in
blobd6f314acffdde0655cb878fe60767fca78dcb8ef
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 myver='@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*)
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*)
238 filename=${netfile##*/}
239 filename=${filename%%#*}
240 filename=${filename%%.git*}
243 # if it is just an URL, we only keep the last component
244 filename="${netfile##*/}"
246 esac
247 printf "%s\n" "${filename}"
250 # extract the URL from a source entry
251 get_url() {
252 # strip an eventual filename
253 printf "%s\n" "${1#*::}"
256 # extract the protocol from a source entry - return "local" for local sources
257 get_protocol() {
258 if [[ $1 = *://* ]]; then
259 # strip leading filename
260 local proto="${1##*::}"
261 printf "%s\n" "${proto%%://*}"
262 else
263 printf "%s\n" local
267 get_downloadclient() {
268 local proto=$1
270 # loop through DOWNLOAD_AGENTS variable looking for protocol
271 local i
272 for i in "${DLAGENTS[@]}"; do
273 local handler="${i%%::*}"
274 if [[ $proto = "$handler" ]]; then
275 local agent="${i##*::}"
276 break
278 done
280 # if we didn't find an agent, return an error
281 if [[ -z $agent ]]; then
282 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
283 plain "$(gettext "Aborting...")"
284 exit 1 # $E_CONFIG_ERROR
287 # ensure specified program is installed
288 local program="${agent%% *}"
289 if [[ ! -x $program ]]; then
290 local baseprog="${program##*/}"
291 error "$(gettext "The download program %s is not installed.")" "$baseprog"
292 plain "$(gettext "Aborting...")"
293 exit 1 # $E_MISSING_PROGRAM
296 printf "%s\n" "$agent"
299 download_local() {
300 local netfile=$1
301 local filepath=$(get_filepath "$netfile")
303 if [[ -n "$filepath" ]]; then
304 msg2 "$(gettext "Found %s")" "${filepath##*/}"
305 rm -f "$srcdir/${filepath##*/}"
306 ln -s "$filepath" "$srcdir/"
307 continue
308 else
309 local filename=$(get_filename "$netfile")
310 error "$(gettext "%s was not found in the build directory and is not a URL.")" "$filename"
311 exit 1 # $E_MISSING_FILE
315 download_file() {
316 local netfile=$1
318 local filepath=$(get_filepath "$netfile")
319 if [[ -n "$filepath" ]]; then
320 msg2 "$(gettext "Found %s")" "${filepath##*/}"
321 rm -f "$srcdir/${filepath##*/}"
322 ln -s "$filepath" "$srcdir/"
323 return
326 local proto=$(get_protocol "$netfile")
328 # find the client we should use for this URL
329 local dlcmd
330 dlcmd=$(get_downloadclient "$proto") || exit $?
332 local filename=$(get_filename "$netfile")
333 local url=$(get_url "$netfile")
335 if [[ $proto = "scp" ]]; then
336 # scp downloads should not pass the protocol in the url
337 url="${url##*://}"
340 msg2 "$(gettext "Downloading %s...")" "$filename"
342 # temporary download file, default to last component of the URL
343 local dlfile="${url##*/}"
345 # replace %o by the temporary dlfile if it exists
346 if [[ $dlcmd = *%o* ]]; then
347 dlcmd=${dlcmd//\%o/\"$filename.part\"}
348 dlfile="$filename.part"
350 # add the URL, either in place of %u or at the end
351 if [[ $dlcmd = *%u* ]]; then
352 dlcmd=${dlcmd//\%u/\"$url\"}
353 else
354 dlcmd="$dlcmd \"$url\""
357 local ret=0
358 eval "$dlcmd || ret=\$?"
359 if (( ret )); then
360 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
361 error "$(gettext "Failure while downloading %s")" "$filename"
362 plain "$(gettext "Aborting...")"
363 exit 1
366 # rename the temporary download file to the final destination
367 if [[ $dlfile != "$filename" ]]; then
368 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$filename"
371 rm -f "$srcdir/$filename"
372 ln -s "$SRCDEST/$filename" "$srcdir/"
375 download_git() {
376 local netfile=$1
378 local fragment=${netfile##*#}
379 if [[ $fragment = "$netfile" ]]; then
380 unset fragment
383 local dir=$(get_filepath "$netfile")
384 [[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"
386 local repo=${netfile##*/}
387 repo=${repo%%#*}
388 repo=${repo%%.git*}
390 local url=$(get_url "$netfile")
391 url=${url##*git+}
392 url=${url%%#*}
394 if [[ ! -d "$dir" ]]; then
395 msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git"
396 if ! git clone --mirror "$url" "$dir"; then
397 error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "git"
398 plain "$(gettext "Aborting...")"
399 exit 1
401 else
402 msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "git"
403 cd_safe "$dir"
404 if ! git fetch --all -p; then
405 # only warn on failure to allow offline builds
406 warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "git"
410 msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "git"
411 pushd "$srcdir" &>/dev/null
412 rm -rf "${dir##*/}"
414 if ! git clone "$dir"; then
415 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
416 plain "$(gettext "Aborting...")"
417 exit 1
420 cd_safe "${dir##*/}"
422 local ref
423 if [[ -n $fragment ]]; then
424 case ${fragment%%=*} in
425 commit|tag)
426 ref=${fragment##*=}
428 branch)
429 ref=origin/${fragment##*=}
432 error "$(gettext "Unrecognized reference: %s")" "${fragment}"
433 plain "$(gettext "Aborting...")"
434 exit 1
435 esac
438 if [[ -n $ref ]]; then
439 if ! git checkout -b makepkg $ref; then
440 error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
441 plain "$(gettext "Aborting...")"
442 exit 1
446 popd &>/dev/null
449 download_sources() {
450 msg "$(gettext "Retrieving Sources...")"
452 pushd "$SRCDEST" &>/dev/null
454 local netfile
455 for netfile in "${source[@]}"; do
456 local proto=$(get_protocol "$netfile")
458 case "$proto" in
459 local)
460 download_local "$netfile"
462 ftp|http|https|rsync|scp)
463 download_file "$netfile"
465 git*)
466 download_git "$netfile"
469 error "$(gettext "Unknown download protocol: %s")" "$proto"
470 plain "$(gettext "Aborting...")"
471 exit 1
473 esac
474 done
476 popd &>/dev/null
479 # Print 'source not found' error message and exit makepkg
480 missing_source_file() {
481 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
482 plain "$(gettext "Aborting...")"
483 exit 1 # $E_MISSING_FILE
487 # usage : get_full_version( [$pkgname] )
488 # return : full version spec, including epoch (if necessary), pkgver, pkgrel
490 get_full_version() {
491 if [[ -z $1 ]]; then
492 if [[ $epoch ]] && (( ! $epoch )); then
493 printf "%s\n" "$pkgver-$pkgrel"
494 else
495 printf "%s\n" "$epoch:$pkgver-$pkgrel"
497 else
498 for i in pkgver pkgrel epoch; do
499 local indirect="${i}_override"
500 eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
501 [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
502 done
503 if (( ! $epoch_override )); then
504 printf "%s\n" "$pkgver_override-$pkgrel_override"
505 else
506 printf "%s\n" "$epoch_override:$pkgver_override-$pkgrel_override"
512 # usage : get_pkg_arch( [$pkgname] )
513 # return : architecture of the package
515 get_pkg_arch() {
516 if [[ -z $1 ]]; then
517 if [[ $arch = "any" ]]; then
518 printf "%s\n" "any"
519 else
520 printf "%s\n" "$CARCH"
522 else
523 local arch_override
524 eval $(declare -f package_$1 | sed -n 's/\(^[[:space:]]*arch=\)/arch_override=/p')
525 (( ${#arch_override[@]} == 0 )) && arch_override=("${arch[@]}")
526 if [[ $arch_override = "any" ]]; then
527 printf "%s\n" "any"
528 else
529 printf "%s\n" "$CARCH"
535 # Checks to see if options are present in makepkg.conf or PKGBUILD;
536 # PKGBUILD options always take precedence.
538 # usage : check_option( $option, $expected_val )
539 # return : 0 - matches expected
540 # 1 - does not match expected
541 # 127 - not found
543 check_option() {
544 in_opt_array "$1" ${options[@]}
545 case $? in
546 0) # assert enabled
547 [[ $2 = y ]]
548 return ;;
549 1) # assert disabled
550 [[ $2 = n ]]
551 return
552 esac
554 # fall back to makepkg.conf options
555 in_opt_array "$1" ${OPTIONS[@]}
556 case $? in
557 0) # assert enabled
558 [[ $2 = y ]]
559 return ;;
560 1) # assert disabled
561 [[ $2 = n ]]
562 return
563 esac
565 # not found
566 return 127
571 # Check if option is present in BUILDENV
573 # usage : check_buildenv( $option, $expected_val )
574 # return : 0 - matches expected
575 # 1 - does not match expected
576 # 127 - not found
578 check_buildenv() {
579 in_opt_array "$1" ${BUILDENV[@]}
580 case $? in
581 0) # assert enabled
582 [[ $2 = "y" ]]
583 return ;;
584 1) # assert disabled
585 [[ $2 = "n" ]]
586 return ;;
587 esac
589 # not found
590 return 127
595 # usage : in_opt_array( $needle, $haystack )
596 # return : 0 - enabled
597 # 1 - disabled
598 # 127 - not found
600 in_opt_array() {
601 local needle=$1; shift
603 local opt
604 for opt in "$@"; do
605 if [[ $opt = "$needle" ]]; then
606 # enabled
607 return 0
608 elif [[ $opt = "!$needle" ]]; then
609 # disabled
610 return 1
612 done
614 # not found
615 return 127
620 # usage : in_array( $needle, $haystack )
621 # return : 0 - found
622 # 1 - not found
624 in_array() {
625 local needle=$1; shift
626 local item
627 for item in "$@"; do
628 [[ $item = "$needle" ]] && return 0 # Found
629 done
630 return 1 # Not Found
633 source_has_signatures() {
634 local file
635 for file in "${source[@]}"; do
636 if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
637 return 0
639 done
640 return 1
643 run_pacman() {
644 local cmd
645 if [[ ! $1 = -@(T|Qq) ]]; then
646 cmd=("$PACMAN" $PACMAN_OPTS "$@")
647 else
648 cmd=("$PACMAN" "$@")
650 if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then
651 if type -p sudo >/dev/null; then
652 cmd=(sudo "${cmd[@]}")
653 else
654 cmd=(su root -c "$(printf '%q ' "${cmd[@]}")")
657 "${cmd[@]}"
660 check_deps() {
661 (( $# > 0 )) || return 0
663 local ret=0
664 local pmout
665 pmout=$(run_pacman -T "$@")
666 ret=$?
668 if (( ret == 127 )); then #unresolved deps
669 printf "%s\n" "$pmout"
670 elif (( ret )); then
671 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
672 return "$ret"
676 handle_deps() {
677 local R_DEPS_SATISFIED=0
678 local R_DEPS_MISSING=1
680 (( $# == 0 )) && return $R_DEPS_SATISFIED
682 local deplist="$*"
684 if (( ! DEP_BIN )); then
685 return $R_DEPS_MISSING
688 if (( DEP_BIN )); then
689 # install missing deps from binary packages (using pacman -S)
690 msg "$(gettext "Installing missing dependencies...")"
692 if ! run_pacman -S --asdeps $deplist; then
693 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
694 exit 1 # TODO: error code
698 # we might need the new system environment
699 # save our shell options and turn off extglob
700 local shellopts=$(shopt -p)
701 shopt -u extglob
702 source /etc/profile &>/dev/null
703 eval "$shellopts"
705 return $R_DEPS_SATISFIED
708 resolve_deps() {
709 local R_DEPS_SATISFIED=0
710 local R_DEPS_MISSING=1
712 # deplist cannot be declared like this: local deplist=$(foo)
713 # Otherwise, the return value will depend on the assignment.
714 local deplist
715 deplist="$(set +E; check_deps $*)" || exit 1
716 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
718 if handle_deps $deplist; then
719 # check deps again to make sure they were resolved
720 deplist="$(set +E; check_deps $*)" || exit 1
721 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
724 msg "$(gettext "Missing Dependencies:")"
725 local dep
726 for dep in $deplist; do
727 msg2 "$dep"
728 done
730 return $R_DEPS_MISSING
733 remove_deps() {
734 (( ! RMDEPS )) && return
736 # check for packages removed during dependency install (e.g. due to conflicts)
737 # removing all installed packages is risky in this case
738 if [[ -n $(grep -xvFf <(printf '%s\n' "${current_packagelist[@]}") \
739 <(printf '%s\n' "${original_packagelist[@]}") || true) ]]; then
740 warning "$(gettext "Failed to remove installed dependencies.")"
741 return 0
744 local deplist
745 deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \
746 <(printf "%s\n" "${current_pkglist[@]}") || true))
747 if [[ -z $deplist ]]; then
748 return
751 msg "Removing installed dependencies..."
752 # exit cleanly on failure to remove deps as package has been built successfully
753 if ! run_pacman -Rn ${deplist[@]}; then
754 warning "$(gettext "Failed to remove installed dependencies.")"
755 return 0
759 get_integlist() {
760 local integ
761 local integlist=()
763 for integ in md5 sha1 sha256 sha384 sha512; do
764 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
765 if [[ -n "$integrity_sums" ]]; then
766 integlist=(${integlist[@]} $integ)
768 done
770 if (( ${#integlist[@]} > 0 )); then
771 printf "%s\n" "${integlist[@]}"
772 else
773 printf "%s\n" "${INTEGRITY_CHECK[@]}"
777 generate_checksums() {
778 msg "$(gettext "Generating checksums for source files...")"
780 if ! type -p openssl >/dev/null; then
781 error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
782 exit 1 # $E_MISSING_PROGRAM
785 local integlist
786 if (( $# == 0 )); then
787 integlist=$(get_integlist)
788 else
789 integlist=$@
792 local integ
793 for integ in ${integlist[@]}; do
794 case "$integ" in
795 md5|sha1|sha256|sha384|sha512) : ;;
797 error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
798 exit 1;; # $E_CONFIG_ERROR
799 esac
801 local ct=0
802 local numsrc=${#source[@]}
803 printf "%s" "${integ}sums=("
805 local i
806 local indent=''
807 for (( i = 0; i < ${#integ} + 6; i++ )); do
808 indent="$indent "
809 done
811 local netfile
812 for netfile in "${source[@]}"; do
813 local proto sum
814 proto="$(get_protocol "$netfile")"
816 case $proto in
817 git*)
818 sum="SKIP"
821 local file
822 file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
823 sum="$(openssl dgst -${integ} "$file")"
824 sum=${sum##* }
826 esac
828 (( ct )) && printf "%s" "$indent"
829 printf "%s" "'$sum'"
830 ct=$(($ct+1))
831 (( $ct < $numsrc )) && echo
832 done
834 echo ")"
835 done
838 check_checksums() {
839 (( SKIPCHECKSUMS )) && return 0
840 (( ! ${#source[@]} )) && return 0
842 local correlation=0
843 local integ required
844 for integ in md5 sha1 sha256 sha384 sha512; do
845 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
846 if (( ${#integrity_sums[@]} == ${#source[@]} )); then
847 msg "$(gettext "Validating source files with %s...")" "${integ}sums"
848 correlation=1
849 local errors=0
850 local idx=0
851 local file
852 for file in "${source[@]}"; do
853 local found=1
854 file="$(get_filename "$file")"
855 printf "%s" " $file ... " >&2
857 if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then
858 echo "$(gettext "Skipped")" >&2
859 idx=$((idx + 1))
860 continue
863 if ! file="$(get_filepath "$file")"; then
864 printf -- "$(gettext "NOT FOUND")\n" >&2
865 errors=1
866 found=0
869 if (( $found )) ; then
870 local expectedsum="${integrity_sums[idx],,}"
871 local realsum="$(openssl dgst -${integ} "$file")"
872 realsum="${realsum##* }"
873 if [[ $expectedsum = "$realsum" ]]; then
874 printf -- "$(gettext "Passed")\n" >&2
875 else
876 printf -- "$(gettext "FAILED")\n" >&2
877 errors=1
881 idx=$((idx + 1))
882 done
884 if (( errors )); then
885 error "$(gettext "One or more files did not pass the validity check!")"
886 exit 1 # TODO: error code
888 elif (( ${#integrity_sums[@]} )); then
889 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
890 exit 1 # TODO: error code
892 done
894 if (( ! correlation )); then
895 error "$(gettext "Integrity checks are missing.")"
896 exit 1 # TODO: error code
900 check_pgpsigs() {
901 (( SKIPPGPCHECK )) && return 0
902 ! source_has_signatures && return 0
904 msg "$(gettext "Verifying source file signatures with %s...")" "gpg"
906 local file pubkey
907 local warning=0
908 local errors=0
909 local statusfile=$(mktemp)
911 for file in "${source[@]}"; do
912 file="$(get_filename "$file")"
913 if [[ ! $file = *.@(sig?(n)|asc) ]]; then
914 continue
917 printf " %s ... " "${file%.*}" >&2
919 if ! file="$(get_filepath "$file")"; then
920 printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
921 errors=1
922 continue
925 if ! sourcefile="$(get_filepath "${file%.*}")"; then
926 printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
927 errors=1
928 continue
931 if ! gpg --quiet --batch --status-file "$statusfile" --verify "$file" "$sourcefile" 2> /dev/null; then
932 printf '%s' "$(gettext "FAILED")" >&2
933 if ! pubkey=$(awk '/NO_PUBKEY/ { print $3; exit 1; }' "$statusfile"); then
934 printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
935 warnings=1
936 else
937 errors=1
939 printf '\n' >&2
940 else
941 if grep -q "REVKEYSIG" "$statusfile"; then
942 printf '%s (%s)' "$(gettext "FAILED")" "$(gettext "the key has been revoked.")" >&2
943 errors=1
944 else
945 printf '%s' "$(gettext "Passed")" >&2
946 if grep -q "EXPSIG" "$statusfile"; then
947 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
948 warnings=1
949 elif grep -q "EXPKEYSIG" "$statusfile"; then
950 printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
951 warnings=1
954 printf '\n' >&2
956 done
958 rm -f "$statusfile"
960 if (( errors )); then
961 error "$(gettext "One or more PGP signatures could not be verified!")"
962 exit 1
965 if (( warnings )); then
966 warning "$(gettext "Warnings have occurred while verifying the signatures.")"
967 plain "$(gettext "Please make sure you really trust them.")"
971 check_source_integrity() {
972 if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
973 warning "$(gettext "Skipping all source file integrity checks.")"
974 elif (( SKIPCHECKSUMS )); then
975 warning "$(gettext "Skipping verification of source file checksums.")"
976 check_pgpsigs
977 elif (( SKIPPGPCHECK )); then
978 warning "$(gettext "Skipping verification of source file PGP signatures.")"
979 check_checksums
980 else
981 check_checksums
982 check_pgpsigs
986 extract_sources() {
987 msg "$(gettext "Extracting Sources...")"
988 local netfile
989 for netfile in "${source[@]}"; do
990 local file=$(get_filename "$netfile")
991 if in_array "$file" "${noextract[@]}"; then
992 #skip source files in the noextract=() array
993 # these are marked explicitly to NOT be extracted
994 continue
998 # fix flyspray #6246
999 local file_type=$(file -bizL "$file")
1000 local ext=${file##*.}
1001 local cmd=''
1002 case "$file_type" in
1003 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
1004 cmd="bsdtar" ;;
1005 *application/x-gzip*)
1006 case "$ext" in
1007 gz|z|Z) cmd="gzip" ;;
1008 *) continue;;
1009 esac ;;
1010 *application/x-bzip*)
1011 case "$ext" in
1012 bz2|bz) cmd="bzip2" ;;
1013 *) continue;;
1014 esac ;;
1015 *application/x-xz*)
1016 case "$ext" in
1017 xz) cmd="xz" ;;
1018 *) continue;;
1019 esac ;;
1021 # See if bsdtar can recognize the file
1022 if bsdtar -tf "$file" -q '*' &>/dev/null; then
1023 cmd="bsdtar"
1024 else
1025 continue
1026 fi ;;
1027 esac
1029 local ret=0
1030 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
1031 if [[ $cmd = "bsdtar" ]]; then
1032 $cmd -xf "$file" || ret=$?
1033 else
1034 rm -f -- "${file%.*}"
1035 $cmd -dcf "$file" > "${file%.*}" || ret=$?
1037 if (( ret )); then
1038 error "$(gettext "Failed to extract %s")" "$file"
1039 plain "$(gettext "Aborting...")"
1040 exit 1
1042 done
1044 if (( EUID == 0 )); then
1045 # change perms of all source files to root user & root group
1046 chown -R 0:0 "$srcdir"
1050 error_function() {
1051 if [[ -p $logpipe ]]; then
1052 rm "$logpipe"
1054 # first exit all subshells, then print the error
1055 if (( ! BASH_SUBSHELL )); then
1056 error "$(gettext "A failure occurred in %s().")" "$1"
1057 plain "$(gettext "Aborting...")"
1058 remove_deps
1060 exit 2 # $E_BUILD_FAILED
1063 cd_safe() {
1064 if ! cd "$1"; then
1065 error "$(gettext "Failed to change to directory %s")" "$1"
1066 plain "$(gettext "Aborting...")"
1067 exit 1
1071 source_safe() {
1072 shopt -u extglob
1073 if ! source "$@"; then
1074 error "$(gettext "Failed to source %s")" "$1"
1075 exit 1
1077 shopt -s extglob
1080 run_function_safe() {
1081 local restoretrap
1083 set -e
1084 set -E
1086 restoretrap=$(trap -p ERR)
1087 trap 'error_function $pkgfunc' ERR
1089 run_function "$1"
1091 eval $restoretrap
1093 set +E
1094 set +e
1097 run_function() {
1098 if [[ -z $1 ]]; then
1099 return 1
1101 local pkgfunc="$1"
1103 # clear user-specified buildflags if requested
1104 if check_option "buildflags" "n"; then
1105 unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
1108 # clear user-specified makeflags if requested
1109 if check_option "makeflags" "n"; then
1110 unset MAKEFLAGS
1113 msg "$(gettext "Starting %s()...")" "$pkgfunc"
1114 cd_safe "$srcdir"
1116 # ensure all necessary build variables are exported
1117 export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
1118 # save our shell options so pkgfunc() can't override what we need
1119 local shellopts=$(shopt -p)
1121 local ret=0
1122 if (( LOGGING )); then
1123 local fullver=$(get_full_version)
1124 local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
1125 if [[ -f $BUILDLOG ]]; then
1126 local i=1
1127 while true; do
1128 if [[ -f $BUILDLOG.$i ]]; then
1129 i=$(($i +1))
1130 else
1131 break
1133 done
1134 mv "$BUILDLOG" "$BUILDLOG.$i"
1137 # ensure overridden package variables survive tee with split packages
1138 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
1139 mkfifo "$logpipe"
1140 tee "$BUILDLOG" < "$logpipe" &
1141 local teepid=$!
1143 $pkgfunc &>"$logpipe"
1145 wait $teepid
1146 rm "$logpipe"
1147 else
1148 $pkgfunc 2>&1
1150 # reset our shell options
1151 eval "$shellopts"
1154 run_prepare() {
1155 run_function_safe "prepare"
1158 run_build() {
1159 # use distcc if it is requested (check buildenv and PKGBUILD opts)
1160 if check_buildenv "distcc" "y" && ! check_option "distc" "n"; then
1161 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
1162 export DISTCC_HOSTS
1165 # use ccache if it is requested (check buildenv and PKGBUILD opts)
1166 if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
1167 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
1170 run_function_safe "build"
1173 run_check() {
1174 run_function_safe "check"
1177 run_package() {
1178 local pkgfunc
1179 if [[ -z $1 ]]; then
1180 pkgfunc="package"
1181 else
1182 pkgfunc="package_$1"
1185 run_function_safe "$pkgfunc"
1188 tidy_install() {
1189 cd_safe "$pkgdir"
1190 msg "$(gettext "Tidying install...")"
1192 if check_option "docs" "n" && [[ -n ${DOC_DIRS[*]} ]]; then
1193 msg2 "$(gettext "Removing doc files...")"
1194 rm -rf -- ${DOC_DIRS[@]}
1197 if check_option "purge" "y" && [[ -n ${PURGE_TARGETS[*]} ]]; then
1198 msg2 "$(gettext "Purging unwanted files...")"
1199 local pt
1200 for pt in "${PURGE_TARGETS[@]}"; do
1201 if [[ ${pt} = "${pt//\/}" ]]; then
1202 find . ! -type d -name "${pt}" -exec rm -f -- '{}' \;
1203 else
1204 rm -f ${pt}
1206 done
1209 if check_option "zipman" "y" && [[ -n ${MAN_DIRS[*]} ]]; then
1210 msg2 "$(gettext "Compressing man and info pages...")"
1211 local file files inode link
1212 while read -rd ' ' inode; do
1213 read file
1214 find ${MAN_DIRS[@]} -type l 2>/dev/null |
1215 while read link ; do
1216 if [[ "${file}" -ef "${link}" ]] ; then
1217 rm -f "$link" "${link}.gz"
1218 if [[ ${file%/*} = ${link%/*} ]]; then
1219 ln -s -- "${file##*/}.gz" "${link}.gz"
1220 else
1221 ln -s -- "/${file}.gz" "${link}.gz"
1224 done
1225 if [[ -z ${files[$inode]} ]]; then
1226 files[$inode]=$file
1227 gzip -9 -f "$file"
1228 else
1229 rm -f "$file"
1230 ln "${files[$inode]}.gz" "${file}.gz"
1231 chmod 644 "${file}.gz"
1233 done < <(find ${MAN_DIRS[@]} -type f \! -name "*.gz" \! -name "*.bz2" \
1234 -exec @INODECMD@ '{}' + 2>/dev/null)
1237 if check_option "strip" "y"; then
1238 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
1239 # make sure library stripping variables are defined to prevent excess stripping
1240 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
1241 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
1242 local binary
1243 find . -type f -perm -u+w -print0 2>/dev/null | while read -d '' binary ; do
1244 case "$(file -bi "$binary")" in
1245 *application/x-sharedlib*) # Libraries (.so)
1246 strip $STRIP_SHARED "$binary";;
1247 *application/x-archive*) # Libraries (.a)
1248 strip $STRIP_STATIC "$binary";;
1249 *application/x-executable*) # Binaries
1250 strip $STRIP_BINARIES "$binary";;
1251 esac
1252 done
1255 if check_option "libtool" "n"; then
1256 msg2 "$(gettext "Removing "%s" files...")" "libtool"
1257 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
1260 if check_option "emptydirs" "n"; then
1261 msg2 "$(gettext "Removing empty directories...")"
1262 find . -depth -type d -exec rmdir '{}' + 2>/dev/null
1265 if check_option "upx" "y"; then
1266 msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
1267 local binary
1268 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
1269 if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then
1270 upx $UPXFLAGS "$binary" &>/dev/null ||
1271 warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}"
1273 done
1277 find_libdepends() {
1278 local d sodepends;
1280 sodepends=0;
1281 for d in "${depends[@]}"; do
1282 if [[ $d = *.so ]]; then
1283 sodepends=1;
1284 break;
1286 done
1288 if (( sodepends == 0 )); then
1289 printf '%s\n' "${depends[@]}"
1290 return;
1293 local libdeps filename soarch sofile soname soversion;
1294 declare -A libdeps;
1296 while read filename; do
1297 # get architecture of the file; if soarch is empty it's not an ELF binary
1298 soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1299 [[ -n "$soarch" ]] || continue
1301 # process all libraries needed by the binary
1302 for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
1304 # extract the library name: libfoo.so
1305 soname="${sofile%.so?(+(.+([0-9])))}".so
1306 # extract the major version: 1
1307 soversion="${sofile##*\.so\.}"
1309 if [[ ${libdeps[$soname]} ]]; then
1310 if [[ ${libdeps[$soname]} != *${soversion}-${soarch}* ]]; then
1311 libdeps[$soname]+=" ${soversion}-${soarch}"
1313 else
1314 libdeps[$soname]="${soversion}-${soarch}"
1316 done
1317 done < <(find "$pkgdir" -type f -perm -u+x)
1319 local libdepends v
1320 for d in "${depends[@]}"; do
1321 case "$d" in
1322 *.so)
1323 if [[ ${libdeps[$d]} ]]; then
1324 for v in ${libdeps[$d]}; do
1325 libdepends+=("$d=$v")
1326 done
1327 else
1328 warning "$(gettext "Library listed in %s is not required by any files: %s")" "'depends'" "$d"
1329 libdepends+=("$d")
1333 libdepends+=("$d")
1335 esac
1336 done
1338 printf '%s\n' "${libdepends[@]}"
1342 find_libprovides() {
1343 local p libprovides missing
1344 for p in "${provides[@]}"; do
1345 missing=0
1346 case "$p" in
1347 *.so)
1348 mapfile -t filename < <(find "$pkgdir" -type f -name $p\*)
1349 if [[ $filename ]]; then
1350 # packages may provide multiple versions of the same library
1351 for fn in "${filename[@]}"; do
1352 # check if we really have a shared object
1353 if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
1354 # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1)
1355 local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
1356 if [[ -z "$sofile" ]]; then
1357 warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p"
1358 libprovides+=("$p")
1359 continue
1362 # get the library architecture (32 or 64 bit)
1363 local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
1365 # extract the library major version
1366 local soversion="${sofile##*\.so\.}"
1368 libprovides+=("${p}=${soversion}-${soarch}")
1369 else
1370 warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p"
1371 libprovides+=("$p")
1373 done
1374 else
1375 libprovides+=("$p")
1376 missing=1
1380 libprovides+=("$p")
1382 esac
1384 if (( missing )); then
1385 warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p"
1387 done
1389 printf '%s\n' "${libprovides[@]}"
1392 check_license() {
1393 # TODO maybe remove this at some point
1394 # warn if license array is not present or empty
1395 if [[ -z $license ]]; then
1396 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
1397 plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
1401 write_pkginfo() {
1402 local builddate=$(date -u "+%s")
1403 if [[ -n $PACKAGER ]]; then
1404 local packager="$PACKAGER"
1405 else
1406 local packager="Unknown Packager"
1409 # btrfs's delayed allocation causes the stat buffers from the kernel to "lie"
1410 # to us momentarily and report 0 blocks allocated (which is how du calculates
1411 # size). Sleeping for a second here is about the dirtiest thing possible,
1412 # but avoids reporting entirely bogus install sizes.
1413 sleep 1
1414 local size="$(@DUPATH@ -sk)"
1415 size="$(( ${size%%[^0-9]*} * 1024 ))"
1417 msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
1418 echo "# Generated by makepkg $myver"
1419 if (( INFAKEROOT )); then
1420 echo "# using $(fakeroot -v)"
1422 echo "# $(LC_ALL=C date -u)"
1423 printf "pkgname = %s\n" "$1"
1424 (( SPLITPKG )) && echo pkgbase = $pkgbase
1425 echo "pkgver = $(get_full_version)"
1426 printf "pkgdesc = %s\n" "$pkgdesc"
1427 printf "url = %s\n" "$url"
1428 printf "builddate = %s\n" "$builddate"
1429 printf "packager = %s\n" "$packager"
1430 printf "size = %s\n" "$size"
1431 printf "arch = %s\n" "$pkgarch"
1433 mapfile -t provides < <(find_libprovides)
1434 mapfile -t depends < <(find_libdepends)
1436 [[ $license ]] && printf "license = %s\n" "${license[@]}"
1437 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
1438 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
1439 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
1440 [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
1441 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
1442 [[ $depends ]] && printf "depend = %s\n" "${depends[@]}"
1443 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
1444 [[ $makedepends ]] && printf "makedepend = %s\n" "${makedepends[@]}"
1445 [[ $checkdepends ]] && printf "checkdepend = %s\n" "${checkdepends[@]}"
1447 local it
1448 for it in "${packaging_options[@]}"; do
1449 check_option "$it" "y"
1450 case $? in
1452 printf "makepkgopt = %s\n" "$it"
1455 printf "makepkgopt = %s\n" "!$it"
1457 esac
1458 done
1460 check_license
1463 check_package() {
1464 cd_safe "$pkgdir"
1466 # check existence of backup files
1467 local file
1468 for file in "${backup[@]}"; do
1469 if [[ ! -f $file ]]; then
1470 warning "$(gettext "%s entry file not in package : %s")" "backup" "$file"
1472 done
1474 # check for references to the build and package directory
1475 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then
1476 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
1478 if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then
1479 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
1484 create_package() {
1485 if [[ ! -d $pkgdir ]]; then
1486 error "$(gettext "Missing %s directory.")" "pkg/"
1487 plain "$(gettext "Aborting...")"
1488 exit 1 # $E_MISSING_PKGDIR
1491 check_package
1493 cd_safe "$pkgdir"
1494 msg "$(gettext "Creating package...")"
1496 local nameofpkg
1497 if [[ -z $1 ]]; then
1498 nameofpkg="$pkgname"
1499 else
1500 nameofpkg="$1"
1503 pkgarch=$(get_pkg_arch)
1505 write_pkginfo $nameofpkg > .PKGINFO
1507 local comp_files=('.PKGINFO')
1509 # check for changelog/install files
1510 for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
1511 IFS='/' read -r orig dest < <(printf '%s\n' "$i")
1513 if [[ -n ${!orig} ]]; then
1514 msg2 "$(gettext "Adding %s file...")" "$orig"
1515 cp "$startdir/${!orig}" "$dest"
1516 chmod 644 "$dest"
1517 comp_files+=("$dest")
1519 done
1521 # tar it up
1522 msg2 "$(gettext "Compressing package...")"
1524 local fullver=$(get_full_version)
1525 local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${pkgarch}${PKGEXT}"
1526 local ret=0
1528 [[ -f $pkg_file ]] && rm -f "$pkg_file"
1529 [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
1531 # when fileglobbing, we want * in an empty directory to expand to
1532 # the null string rather than itself
1533 shopt -s nullglob
1534 # TODO: Maybe this can be set globally for robustness
1535 shopt -s -o pipefail
1536 # bsdtar's gzip compression always saves the time stamp, making one
1537 # archive created using the same command line distinct from another.
1538 # Disable bsdtar compression and use gzip -n for now.
1539 bsdtar -cf - "${comp_files[@]}" * |
1540 case "$PKGEXT" in
1541 *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;;
1542 *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;;
1543 *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;;
1544 *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;;
1545 *tar) cat ;;
1546 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1547 "$PKGEXT"; cat ;;
1548 esac > "${pkg_file}" || ret=$?
1550 shopt -u nullglob
1551 shopt -u -o pipefail
1553 if (( ret )); then
1554 error "$(gettext "Failed to create package file.")"
1555 exit 1 # TODO: error code
1558 create_signature "$pkg_file"
1560 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1561 rm -f "${pkg_file/$PKGDEST/$startdir}"
1562 ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1563 ret=$?
1564 if [[ -f $pkg_file.sig ]]; then
1565 rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
1566 ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
1570 if (( ret )); then
1571 warning "$(gettext "Failed to create symlink to package file.")"
1575 create_signature() {
1576 if [[ $SIGNPKG != 'y' ]]; then
1577 return
1579 local ret=0
1580 local filename="$1"
1581 msg "$(gettext "Signing package...")"
1583 local SIGNWITHKEY=""
1584 if [[ -n $GPGKEY ]]; then
1585 SIGNWITHKEY="-u ${GPGKEY}"
1587 # The signature will be generated directly in ascii-friendly format
1588 gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$?
1591 if (( ! ret )); then
1592 msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
1593 else
1594 warning "$(gettext "Failed to sign package file.")"
1598 create_srcpackage() {
1599 local ret=0
1600 msg "$(gettext "Creating source package...")"
1601 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1602 mkdir "${srclinks}"/${pkgbase}
1604 check_license
1606 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1607 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1609 local file
1610 for file in "${source[@]}"; do
1611 if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then
1612 local absfile
1613 absfile=$(get_filepath "$file") || missing_source_file "$file"
1614 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1615 ln -s "$absfile" "$srclinks/$pkgbase"
1617 done
1619 local i
1620 for i in 'changelog' 'install'; do
1621 local file
1622 while read -r file; do
1623 # evaluate any bash variables used
1624 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1625 if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1626 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1627 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1629 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1630 done
1632 local TAR_OPT
1633 case "$SRCEXT" in
1634 *tar.gz) TAR_OPT="z" ;;
1635 *tar.bz2) TAR_OPT="j" ;;
1636 *tar.xz) TAR_OPT="J" ;;
1637 *tar.Z) TAR_OPT="Z" ;;
1638 *tar) TAR_OPT="" ;;
1639 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1640 "$SRCEXT" ;;
1641 esac
1643 local fullver=$(get_full_version)
1644 local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"
1646 # tar it up
1647 msg2 "$(gettext "Compressing source package...")"
1648 cd_safe "${srclinks}"
1649 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1650 error "$(gettext "Failed to create source package file.")"
1651 exit 1 # TODO: error code
1654 if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1655 rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
1656 ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1657 ret=$?
1660 if (( ret )); then
1661 warning "$(gettext "Failed to create symlink to source package file.")"
1664 cd_safe "${startdir}"
1665 rm -rf "${srclinks}"
1668 install_package() {
1669 (( ! INSTALL )) && return
1671 if (( ! SPLITPKG )); then
1672 msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
1673 else
1674 msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
1677 local fullver pkgarch pkg pkglist
1678 (( ASDEPS )) && pkglist+=('--asdeps')
1680 for pkg in ${pkgname[@]}; do
1681 fullver=$(get_full_version $pkg)
1682 pkgarch=$(get_pkg_arch $pkg)
1683 pkglist+=("$PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT}")
1684 done
1686 if ! run_pacman -U ${pkglist[@]}; then
1687 warning "$(gettext "Failed to install built package(s).")"
1688 return 0
1692 check_sanity() {
1693 # check for no-no's in the build script
1694 local i
1695 local ret=0
1696 for i in 'pkgname' 'pkgrel' 'pkgver'; do
1697 if [[ -z ${!i} ]]; then
1698 error "$(gettext "%s is not allowed to be empty.")" "$i"
1699 ret=1
1701 done
1703 for i in "${pkgname[@]}"; do
1704 if [[ ${i:0:1} = "-" ]]; then
1705 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1706 ret=1
1708 if [[ $i = *[^[:alnum:]+_.@-]* ]]; then
1709 error "$(gettext "%s contains invalid characters: '%s'")" \
1710 'pkgname' "${pkgname//[[:alnum:]+_.@-]}"
1711 ret=1
1713 done
1715 if [[ ${pkgbase:0:1} = "-" ]]; then
1716 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1717 ret=1
1720 awk -F'=' '$1 ~ /^[[:space:]]*pkgver$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1721 while IFS='=' read -r _ i; do
1722 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1723 if [[ $i = *[[:space:]:-]* ]]; then
1724 error "$(gettext "%s is not allowed to contain colons, hyphens or whitespace.")" "pkgver"
1725 return 1
1727 done || ret=1
1729 awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
1730 while IFS='=' read -r _ i; do
1731 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1732 if [[ $i != +([0-9])?(.+([0-9])) ]]; then
1733 error "$(gettext "%s must be a decimal.")" "pkgrel"
1734 return 1
1736 done || ret=1
1738 awk -F'=' '$1 ~ /^[[:space:]]*epoch$/' "$BUILDFILE" |
1739 while IFS='=' read -r _ i; do
1740 eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
1741 if [[ $i != *([[:digit:]]) ]]; then
1742 error "$(gettext "%s must be an integer.")" "epoch"
1743 return 1
1745 done || ret=1
1747 if [[ $arch != 'any' ]]; then
1748 if ! in_array $CARCH ${arch[@]}; then
1749 if (( ! IGNOREARCH )); then
1750 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1751 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1752 plain "$(gettext "such as %s.")" "arch=('$CARCH')"
1753 ret=1
1758 if (( ${#pkgname[@]} > 1 )); then
1759 for i in ${pkgname[@]}; do
1760 local arch_list=""
1761 eval $(declare -f package_${i} | sed -n 's/\(^[[:space:]]*arch=\)/arch_list=/p')
1762 if [[ ${arch_list[@]} && ${arch_list} != 'any' ]]; then
1763 if ! in_array $CARCH ${arch_list[@]}; then
1764 if (( ! IGNOREARCH )); then
1765 error "$(gettext "%s is not available for the '%s' architecture.")" "$i" "$CARCH"
1766 ret=1
1770 done
1773 local provides_list=()
1774 eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | \
1775 sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//')
1776 for i in ${provides_list[@]}; do
1777 if [[ $i == *['<>']* ]]; then
1778 error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides"
1779 ret=1
1781 done
1783 local backup_list=()
1784 eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | \
1785 sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//')
1786 for i in "${backup_list[@]}"; do
1787 if [[ ${i:0:1} = "/" ]]; then
1788 error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i"
1789 ret=1
1791 done
1793 local optdepends_list=()
1794 eval $(awk '/^[[:space:]]*optdepends=\(/,/\)[[:space:]]*(#.*)?$/' "$BUILDFILE" | \
1795 sed -e "s/optdepends=/optdepends_list+=/" -e "s/#.*//" -e 's/\\$//')
1796 for i in "${optdepends_list[@]}"; do
1797 local pkg=${i%%:[[:space:]]*}
1798 # the '-' character _must_ be first or last in the character range
1799 if [[ $pkg != +([-[:alnum:]><=.+_:]) ]]; then
1800 error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i"
1801 ret=1
1803 done
1805 for i in 'changelog' 'install'; do
1806 local file
1807 while read -r file; do
1808 # evaluate any bash variables used
1809 eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
1810 if [[ $file && ! -f $file ]]; then
1811 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1812 ret=1
1814 done < <(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1815 done
1817 local valid_options=1
1818 local known kopt options_list
1819 eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | \
1820 sed -e "s/options=/options_list+=/" -e "s/#.*//" -e 's/\\$//')
1821 for i in ${options_list[@]}; do
1822 known=0
1823 # check if option matches a known option or its inverse
1824 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1825 if [[ ${i} = "${kopt}" || ${i} = "!${kopt}" ]]; then
1826 known=1
1828 done
1829 if (( ! known )); then
1830 error "$(gettext "%s array contains unknown option '%s'")" "options" "$i"
1831 valid_options=0
1833 done
1834 if (( ! valid_options )); then
1835 ret=1
1838 if (( ${#pkgname[@]} > 1 )); then
1839 for i in ${pkgname[@]}; do
1840 if ! declare -f package_${i} >/dev/null; then
1841 error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i"
1842 ret=1
1844 done
1847 for i in ${PKGLIST[@]}; do
1848 if ! in_array $i ${pkgname[@]}; then
1849 error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1850 ret=1
1852 done
1854 return $ret
1857 check_software() {
1858 # check for needed software
1859 local ret=0
1861 # check for sudo if we will need it during makepkg execution
1862 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1863 if ! type -p sudo >/dev/null; then
1864 warning "$(gettext "Cannot find the %s binary. Will use %s to acquire root privileges.")" "sudo" "su"
1868 # fakeroot - building as non-root user
1869 if check_buildenv "fakeroot" "y" && (( EUID > 0 )); then
1870 if ! type -p fakeroot >/dev/null; then
1871 error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
1872 ret=1
1876 # gpg - package signing
1877 if [[ $SIGNPKG == 'y' ]] || { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; }; then
1878 if ! type -p gpg >/dev/null; then
1879 error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
1880 ret=1
1884 # gpg - source verification
1885 if (( ! SKIPPGPCHECK )) && source_has_signatures; then
1886 if ! type -p gpg >/dev/null; then
1887 error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
1888 ret=1
1892 # openssl - checksum operations
1893 if (( ! SKIPCHECKSUMS )); then
1894 if ! type -p openssl >/dev/null; then
1895 error "$(gettext "Cannot find the %s binary required for validating sourcefile checksums.")" "openssl"
1896 ret=1
1900 # upx - binary compression
1901 if check_option "upx" "y"; then
1902 if ! type -p upx >/dev/null; then
1903 error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
1904 ret=1
1908 # distcc - compilation with distcc
1909 if check_buildenv "distcc" "y" && ! check_option "distcc" "n" ]]; then
1910 if ! type -p distcc >/dev/null; then
1911 error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
1912 ret=1
1916 # ccache - compilation with ccache
1917 if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
1918 if ! type -p ccache >/dev/null; then
1919 error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
1920 ret=1
1924 # strip - strip symbols from binaries/libraries
1925 if check_option "strip" "y"; then
1926 if ! type -p strip >/dev/null; then
1927 error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
1928 ret=1
1932 # gzip - compressig man and info pages
1933 if check_option "zipman" "y"; then
1934 if ! type -p gzip >/dev/null; then
1935 error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
1936 ret=1
1940 return $ret
1943 backup_package_variables() {
1944 local var
1945 for var in ${splitpkg_overrides[@]}; do
1946 local indirect="${var}_backup"
1947 eval "${indirect}=(\"\${$var[@]}\")"
1948 done
1951 restore_package_variables() {
1952 local var
1953 for var in ${splitpkg_overrides[@]}; do
1954 local indirect="${var}_backup"
1955 if [[ -n ${!indirect} ]]; then
1956 eval "${var}=(\"\${$indirect[@]}\")"
1957 else
1958 unset ${var}
1960 done
1963 run_split_packaging() {
1964 local pkgname_backup=${pkgname[@]}
1965 for pkgname in ${pkgname_backup[@]}; do
1966 pkgdir="$pkgdir/$pkgname"
1967 mkdir -p "$pkgdir"
1968 chmod a-s "$pkgdir"
1969 backup_package_variables
1970 run_package $pkgname
1971 tidy_install
1972 create_package $pkgname
1973 restore_package_variables
1974 pkgdir="${pkgdir%/*}"
1975 done
1976 pkgname=${pkgname_backup[@]}
1979 # Canonicalize a directory path if it exists
1980 canonicalize_path() {
1981 local path="$1";
1983 if [[ -d $path ]]; then
1985 cd_safe "$path"
1986 pwd -P
1988 else
1989 printf "%s\n" "$path"
1993 m4_include(library/parseopts.sh)
1995 usage() {
1996 printf "makepkg (pacman) %s\n" "$myver"
1997 echo
1998 printf -- "$(gettext "Usage: %s [options]")\n" "$0"
1999 echo
2000 printf -- "$(gettext "Options:")\n"
2001 printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
2002 printf -- "$(gettext " -c, --clean Clean up work files after build")\n"
2003 printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n"
2004 printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/"
2005 printf -- "$(gettext " -f, --force Overwrite existing package")\n"
2006 printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n"
2007 printf -- "$(gettext " -h, --help Show this help message and exit")\n"
2008 printf -- "$(gettext " -i, --install Install package after successful build")\n"
2009 printf -- "$(gettext " -L, --log Log package build process")\n"
2010 printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n"
2011 printf -- "$(gettext " -o, --nobuild Download and extract files only")\n"
2012 printf -- "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
2013 printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n"
2014 printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n"
2015 printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "pacman"
2016 printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n"
2017 printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n"
2018 printf -- "$(gettext " --asroot Allow %s to run as root user")\n" "makepkg"
2019 printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
2020 printf -- "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
2021 printf -- "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg"
2022 printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
2023 printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
2024 printf -- "$(gettext " --pkg <list> Only build listed packages from a split package")\n"
2025 printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
2026 printf -- "$(gettext " --skipchecksums Do not verify checksums of the source files")\n"
2027 printf -- "$(gettext " --skipinteg Do not perform any verification checks on source files")\n"
2028 printf -- "$(gettext " --skippgpcheck Do not verify source files with PGP signatures")\n"
2029 echo
2030 printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
2031 echo
2032 printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n"
2033 printf -- "$(gettext " --asdeps Install packages as non-explicitly installed")\n"
2034 printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n"
2035 echo
2036 printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
2037 echo
2040 version() {
2041 printf "makepkg (pacman) %s\n" "$myver"
2042 printf -- "$(gettext "\
2043 Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>.\n\
2044 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
2045 This is free software; see the source for copying conditions.\n\
2046 There is NO WARRANTY, to the extent permitted by law.\n")"
2049 # PROGRAM START
2051 # determine whether we have gettext; make it a no-op if we do not
2052 if ! type -p gettext >/dev/null; then
2053 gettext() {
2054 printf "%s\n" "$@"
2058 ARGLIST=("$@")
2060 # Parse Command Line Options.
2061 OPT_SHORT="AcdefFghiLmop:rRsSV"
2062 OPT_LONG=('allsource' 'asroot' 'check' 'clean' 'config:' 'force' 'geninteg'
2063 'help' 'ignorearch' 'install' 'key:' 'log' 'nobuild' 'nocolor'
2064 'nocheck' 'nodeps' 'noextract' 'nosign' 'pkg:' 'repackage' 'rmdeps'
2065 'skipchecksums' 'skipinteg' 'skippgpcheck' 'skippgpcheck' 'sign'
2066 'source' 'syncdeps' 'version')
2068 # Pacman Options
2069 OPT_LONG+=('asdeps' 'noconfirm' 'noprogressbar')
2071 if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
2072 exit 1 # E_INVALID_OPTION;
2074 set -- "${OPTRET[@]}"
2075 unset OPT_SHORT OPT_LONG OPTRET
2077 while true; do
2078 case "$1" in
2079 # Pacman Options
2080 --asdeps) ASDEPS=1;;
2081 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
2082 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
2084 # Makepkg Options
2085 --allsource) SOURCEONLY=2 ;;
2086 --asroot) ASROOT=1 ;;
2087 -A|--ignorearch) IGNOREARCH=1 ;;
2088 -c|--clean) CLEANUP=1 ;;
2089 --check) RUN_CHECK='y' ;;
2090 --config) shift; MAKEPKG_CONF=$1 ;;
2091 -d|--nodeps) NODEPS=1 ;;
2092 -e|--noextract) NOEXTRACT=1 ;;
2093 -f|--force) FORCE=1 ;;
2094 -F) INFAKEROOT=1 ;;
2095 -g|--geninteg) GENINTEG=1 ;;
2096 -i|--install) INSTALL=1 ;;
2097 --key) shift; GPGKEY=$1 ;;
2098 -L|--log) LOGGING=1 ;;
2099 -m|--nocolor) USE_COLOR='n' ;;
2100 --nocheck) RUN_CHECK='n' ;;
2101 --nosign) SIGNPKG='n' ;;
2102 -o|--nobuild) NOBUILD=1 ;;
2103 -p) shift; BUILDFILE=$1 ;;
2104 --pkg) shift; IFS=, read -ra p <<<"$1"; PKGLIST+=("${p[@]}"); unset p ;;
2105 -r|--rmdeps) RMDEPS=1 ;;
2106 -R|--repackage) REPKG=1 ;;
2107 --skipchecksums) SKIPCHECKSUMS=1 ;;
2108 --skipinteg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
2109 --skippgpcheck) SKIPPGPCHECK=1;;
2110 --sign) SIGNPKG='y' ;;
2111 -s|--syncdeps) DEP_BIN=1 ;;
2112 -S|--source) SOURCEONLY=1 ;;
2114 -h|--help) usage; exit 0 ;; # E_OK
2115 -V|--version) version; exit 0 ;; # E_OK
2117 --) OPT_IND=0; shift; break 2;;
2118 esac
2119 shift
2120 done
2122 # setup signal traps
2123 trap 'clean_up' 0
2124 for signal in TERM HUP QUIT; do
2125 trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
2126 done
2127 trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT
2128 trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR
2130 # preserve environment variables and canonicalize path
2131 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
2132 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
2133 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
2134 [[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
2135 [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
2136 [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
2137 [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
2138 [[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
2140 # default config is makepkg.conf
2141 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
2143 # Source the config file; fail if it is not found
2144 if [[ -r $MAKEPKG_CONF ]]; then
2145 source_safe "$MAKEPKG_CONF"
2146 else
2147 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
2148 plain "$(gettext "Aborting...")"
2149 exit 1 # $E_CONFIG_ERROR
2152 # Source user-specific makepkg.conf overrides, but only if no override config
2153 # file was specified
2154 if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
2155 source_safe ~/.makepkg.conf
2158 # set pacman command if not already defined
2159 PACMAN=${PACMAN:-pacman}
2161 # check if messages are to be printed using color
2162 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
2163 if [[ -t 2 && ! $USE_COLOR = "n" ]] && check_buildenv "color" "y"; then
2164 # prefer terminal safe colored and bold text when tput is supported
2165 if tput setaf 0 &>/dev/null; then
2166 ALL_OFF="$(tput sgr0)"
2167 BOLD="$(tput bold)"
2168 BLUE="${BOLD}$(tput setaf 4)"
2169 GREEN="${BOLD}$(tput setaf 2)"
2170 RED="${BOLD}$(tput setaf 1)"
2171 YELLOW="${BOLD}$(tput setaf 3)"
2172 else
2173 ALL_OFF="\e[1;0m"
2174 BOLD="\e[1;1m"
2175 BLUE="${BOLD}\e[1;34m"
2176 GREEN="${BOLD}\e[1;32m"
2177 RED="${BOLD}\e[1;31m"
2178 YELLOW="${BOLD}\e[1;33m"
2181 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
2183 # override settings with an environment variable for batch processing
2184 BUILDDIR=${_BUILDDIR:-$BUILDDIR}
2185 BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
2186 if [[ ! -d $BUILDDIR ]]; then
2187 if ! mkdir -p "$BUILDDIR"; then
2188 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2189 plain "$(gettext "Aborting...")"
2190 exit 1
2192 chmod a-s "$BUILDDIR"
2194 if [[ ! -w $BUILDDIR ]]; then
2195 error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
2196 plain "$(gettext "Aborting...")"
2197 exit 1
2200 PKGDEST=${_PKGDEST:-$PKGDEST}
2201 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
2202 if (( ! (NOBUILD || GENINTEG) )) && [[ ! -w $PKGDEST ]]; then
2203 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
2204 plain "$(gettext "Aborting...")"
2205 exit 1
2208 SRCDEST=${_SRCDEST:-$SRCDEST}
2209 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
2210 if [[ ! -w $SRCDEST ]] ; then
2211 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
2212 plain "$(gettext "Aborting...")"
2213 exit 1
2216 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
2217 SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined
2218 if (( SOURCEONLY )) && [[ ! -w $SRCPKGDEST ]]; then
2219 error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
2220 plain "$(gettext "Aborting...")"
2221 exit 1
2224 PKGEXT=${_PKGEXT:-$PKGEXT}
2225 SRCEXT=${_SRCEXT:-$SRCEXT}
2226 GPGKEY=${_GPGKEY:-$GPGKEY}
2227 PACKAGER=${_PACKAGER:-$PACKAGER}
2229 if (( ! INFAKEROOT )); then
2230 if (( EUID == 0 && ! ASROOT )); then
2231 # Warn those who like to live dangerously.
2232 error "$(gettext "Running %s as root is a BAD idea and can cause permanent,\n\
2233 catastrophic damage to your system. If you wish to run as root, please\n\
2234 use the %s option.")" "makepkg" "--asroot"
2235 exit 1 # $E_USER_ABORT
2236 elif (( EUID > 0 && ASROOT )); then
2237 # Warn those who try to use the --asroot option when they are not root
2238 error "$(gettext "The %s option is meant for the root user only. Please\n\
2239 rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
2240 exit 1 # $E_USER_ABORT
2241 elif (( EUID > 0 )) && ! check_buildenv "fakeroot" "y"; then
2242 warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
2243 ownership of the packaged files. Try using the %s environment by\n\
2244 placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
2245 sleep 1
2247 else
2248 if [[ -z $FAKEROOTKEY ]]; then
2249 error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg"
2250 exit 1 # TODO: error code
2254 unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
2255 unset md5sums replaces depends conflicts backup source install changelog build
2256 unset makedepends optdepends options noextract
2258 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
2259 if [[ ! -f $BUILDFILE ]]; then
2260 if [[ -t 0 ]]; then
2261 error "$(gettext "%s does not exist.")" "$BUILDFILE"
2262 exit 1
2263 else
2264 # PKGBUILD passed through a pipe
2265 BUILDFILE=/dev/stdin
2266 source_safe "$BUILDFILE"
2268 else
2269 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
2270 if [[ -n $crlftest ]]; then
2271 error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
2272 exit 1
2275 if [[ ${BUILDFILE:0:1} != "/" ]]; then
2276 BUILDFILE="$startdir/$BUILDFILE"
2278 source_safe "$BUILDFILE"
2281 # set defaults if they weren't specified in buildfile
2282 pkgbase=${pkgbase:-${pkgname[0]}}
2283 epoch=${epoch:-0}
2285 if [[ $BUILDDIR = "$startdir" ]]; then
2286 srcdir="$BUILDDIR/src"
2287 pkgdir="$BUILDDIR/pkg"
2288 else
2289 srcdir="$BUILDDIR/$pkgbase/src"
2290 pkgdir="$BUILDDIR/$pkgbase/pkg"
2293 if (( GENINTEG )); then
2294 mkdir -p "$srcdir"
2295 chmod a-s "$srcdir"
2296 cd_safe "$srcdir"
2297 download_sources
2298 generate_checksums
2299 exit 0 # $E_OK
2302 # check the PKGBUILD for some basic requirements
2303 check_sanity || exit 1
2305 # check we have the software required to process the PKGBUILD
2306 check_software || exit 1
2308 if (( ${#pkgname[@]} > 1 )); then
2309 SPLITPKG=1
2312 # test for available PKGBUILD functions
2313 if declare -f prepare >/dev/null; then
2314 PREPAREFUNC=1
2316 if declare -f build >/dev/null; then
2317 BUILDFUNC=1
2319 if declare -f check >/dev/null; then
2320 # "Hide" check() function if not going to be run
2321 if [[ $RUN_CHECK = 'y' ]] || { ! check_buildenv "check" "n" && [[ $RUN_CHECK != "n" ]]; }; then
2322 CHECKFUNC=1
2325 if declare -f package >/dev/null; then
2326 PKGFUNC=1
2327 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
2328 SPLITPKG=1
2331 if [[ -n "${PKGLIST[@]}" ]]; then
2332 unset pkgname
2333 pkgname=("${PKGLIST[@]}")
2336 # check if gpg signature is to be created and if signing key is valid
2337 if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then
2338 if ! gpg --list-key ${GPGKEY} &>/dev/null; then
2339 if [[ ! -z $GPGKEY ]]; then
2340 error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
2341 else
2342 error "$(gettext "There is no key in your keyring.")"
2344 exit 1
2349 if (( ! SPLITPKG )); then
2350 fullver=$(get_full_version)
2351 pkgarch=$(get_pkg_arch)
2352 if [[ -f $PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT} ]] \
2353 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
2354 if (( INSTALL )); then
2355 warning "$(gettext "A package has already been built, installing existing package...")"
2356 install_package
2357 exit $?
2358 else
2359 error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
2360 exit 1
2363 else
2364 allpkgbuilt=1
2365 somepkgbuilt=0
2366 for pkg in ${pkgname[@]}; do
2367 fullver=$(get_full_version $pkg)
2368 pkgarch=$(get_pkg_arch $pkg)
2369 if [[ -f $PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT} ]]; then
2370 somepkgbuilt=1
2371 else
2372 allpkgbuilt=0
2374 done
2375 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
2376 if (( allpkgbuilt )); then
2377 if (( INSTALL )); then
2378 warning "$(gettext "The package group has already been built, installing existing packages...")"
2379 install_package
2380 exit $?
2381 else
2382 error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
2383 exit 1
2386 if (( somepkgbuilt )); then
2387 error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
2388 exit 1
2391 unset allpkgbuilt somepkgbuilt
2394 # Run the bare minimum in fakeroot
2395 if (( INFAKEROOT )); then
2396 if (( SOURCEONLY )); then
2397 create_srcpackage
2398 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2399 exit 0 # $E_OK
2402 if (( ! SPLITPKG )); then
2403 if (( ! PKGFUNC )); then
2404 if (( ! REPKG )); then
2405 if (( BUILDFUNC )); then
2406 run_build
2407 (( CHECKFUNC )) && run_check
2408 tidy_install
2410 else
2411 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2412 plain "$(gettext "File permissions may not be preserved.")"
2414 else
2415 run_package
2416 tidy_install
2418 create_package
2419 else
2420 run_split_packaging
2423 msg "$(gettext "Leaving %s environment.")" "fakeroot"
2424 exit 0 # $E_OK
2427 fullver=$(get_full_version)
2428 msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))"
2430 # if we are creating a source-only package, go no further
2431 if (( SOURCEONLY )); then
2432 if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \
2433 && (( ! FORCE )); then
2434 error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
2435 exit 1
2438 # Get back to our src directory so we can begin with sources.
2439 mkdir -p "$srcdir"
2440 chmod a-s "$srcdir"
2441 cd_safe "$srcdir"
2442 if ( (( ! SKIPCHECKSUMS )) || \
2443 ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \
2444 (( SOURCEONLY == 2 )); then
2445 download_sources
2447 check_source_integrity
2448 cd_safe "$startdir"
2450 # if we are root or if fakeroot is not enabled, then we don't use it
2451 if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
2452 create_srcpackage
2453 else
2454 enter_fakeroot
2457 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
2458 exit 0
2461 if (( NODEPS || (NOBUILD && !DEP_BIN ) )); then
2462 # no warning message needed for nobuild
2463 if (( NODEPS )); then
2464 warning "$(gettext "Skipping dependency checks.")"
2466 elif type -p "${PACMAN%% *}" >/dev/null; then
2467 if (( RMDEPS && ! INSTALL )); then
2468 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2470 deperr=0
2472 msg "$(gettext "Checking runtime dependencies...")"
2473 resolve_deps ${depends[@]} || deperr=1
2475 if (( RMDEPS && INSTALL )); then
2476 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
2479 msg "$(gettext "Checking buildtime dependencies...")"
2480 resolve_deps ${makedepends[@]} || deperr=1
2482 if (( CHECKFUNC )); then
2483 resolve_deps ${checkdepends[@]} || deperr=1
2486 if (( RMDEPS )); then
2487 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
2490 if (( deperr )); then
2491 error "$(gettext "Could not resolve all dependencies.")"
2492 exit 1
2494 else
2495 warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH"
2498 # ensure we have a sane umask set
2499 umask 0022
2501 # get back to our src directory so we can begin with sources
2502 mkdir -p "$srcdir"
2503 chmod a-s "$srcdir"
2504 cd_safe "$srcdir"
2506 if (( NOEXTRACT )); then
2507 warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
2508 warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/"
2509 warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/"
2511 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
2512 error "$(gettext "The source directory is empty, there is nothing to build!")"
2513 plain "$(gettext "Aborting...")"
2514 exit 1
2516 elif (( REPKG )); then
2517 if (( ! PKGFUNC && ! SPLITPKG )) \
2518 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
2519 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
2520 plain "$(gettext "Aborting...")"
2521 exit 1
2523 else
2524 download_sources
2525 check_source_integrity
2526 extract_sources
2527 if (( PREPAREFUNC )); then
2528 run_prepare
2532 if (( NOBUILD )); then
2533 msg "$(gettext "Sources are ready.")"
2534 exit 0 #E_OK
2535 else
2536 # check for existing pkg directory; don't remove if we are repackaging
2537 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
2538 msg "$(gettext "Removing existing %s directory...")" "pkg/"
2539 rm -rf "$pkgdir"
2541 mkdir -p "$pkgdir"
2542 chmod a-s "$pkgdir"
2543 cd_safe "$startdir"
2545 # if we are root or if fakeroot is not enabled, then we don't use it
2546 if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
2547 if (( ! REPKG )); then
2548 (( BUILDFUNC )) && run_build
2549 (( CHECKFUNC )) && run_check
2551 if (( ! SPLITPKG )); then
2552 if (( PKGFUNC )); then
2553 run_package
2554 tidy_install
2555 else
2556 if (( ! REPKG )); then
2557 tidy_install
2558 else
2559 warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()"
2560 plain "$(gettext "File permissions may not be preserved.")"
2563 create_package
2564 else
2565 run_split_packaging
2567 else
2568 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2569 (( BUILDFUNC )) && run_build
2570 (( CHECKFUNC )) && run_check
2571 cd_safe "$startdir"
2574 enter_fakeroot
2578 fullver=$(get_full_version)
2579 msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))"
2581 install_package
2583 exit 0 #E_OK
2585 # vim: set ts=2 sw=2 noet: