contrib/ follow-up work
[pacman-ng.git] / scripts / makepkg.sh.in
blobafedc3144abbf70f5c7a79c4fc1a55e9eff07c39
1 #!@BASH@ -e
3 # makepkg - make packages compatible for use with pacman
4 # @configure_input@
6 # Copyright (c) 2006-2010 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 # bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils),
31 # gettext, grep, gzip, openssl, sed, tput (ncurses), xz
33 # gettext initialization
34 export TEXTDOMAIN='pacman'
35 export TEXTDOMAINDIR='@localedir@'
37 # file -i does not work on Mac OSX unless legacy mode is set
38 export COMMAND_MODE='legacy'
40 myver='@PACKAGE_VERSION@'
41 confdir='@sysconfdir@'
42 BUILDSCRIPT='@BUILDSCRIPT@'
43 startdir="$PWD"
44 srcdir="$startdir/src"
45 pkgdir="$startdir/pkg"
47 packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge')
48 other_options=('ccache' 'distcc' 'makeflags' 'force')
49 splitpkg_overrides=('pkgver' 'pkgrel' 'pkgdesc' 'arch' 'license' 'groups' \
50 'depends' 'optdepends' 'provides' 'conflicts' 'replaces' \
51 'backup' 'options' 'install' 'changelog')
52 readonly -a packaging_options other_options splitpkg_overrides
54 # Options
55 ASROOT=0
56 CLEANUP=0
57 CLEANCACHE=0
58 DEP_BIN=0
59 FORCE=0
60 INFAKEROOT=0
61 GENINTEG=0
62 SKIPINTEG=0
63 INSTALL=0
64 NOBUILD=0
65 NODEPS=0
66 NOEXTRACT=0
67 RMDEPS=0
68 REPKG=0
69 LOGGING=0
70 SOURCEONLY=0
71 IGNOREARCH=0
72 HOLDVER=0
73 BUILDFUNC=0
74 PKGFUNC=0
75 SPLITPKG=0
76 PKGLIST=()
78 # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call
79 # when dealing with svn/cvs/etc PKGBUILDs.
80 FORCE_VER=""
82 PACMAN_OPTS=
84 ### SUBROUTINES ###
86 plain() {
87 local mesg=$1; shift
88 printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
91 msg() {
92 local mesg=$1; shift
93 printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
96 msg2() {
97 local mesg=$1; shift
98 printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
101 warning() {
102 local mesg=$1; shift
103 printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
106 error() {
107 local mesg=$1; shift
108 printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
113 # Special exit call for traps, Don't print any error messages when inside,
114 # the fakeroot call, the error message will be printed by the main call.
116 trap_exit() {
117 if (( ! INFAKEROOT )); then
118 echo
119 error "$@"
121 [[ -n $srclinks ]] && rm -rf "$srclinks"
122 exit 1
127 # Clean up function. Called automatically when the script exits.
129 clean_up() {
130 local EXIT_CODE=$?
132 if (( INFAKEROOT )); then
133 # Don't clean up when leaving fakeroot, we're not done yet.
134 return
137 if (( ! EXIT_CODE && CLEANUP )); then
138 local pkg file
140 # If it's a clean exit and -c/--clean has been passed...
141 msg "$(gettext "Cleaning up...")"
142 rm -rf "$pkgdir" "$srcdir"
143 if [[ -n $pkgbase ]]; then
144 # Can't do this unless the BUILDSCRIPT has been sourced.
145 if (( BUILDFUNC )); then
146 rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.log"*
148 if (( PKGFUNC )); then
149 rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-package.log"*
150 elif (( SPLITPKG )); then
151 for pkg in ${pkgname[@]}; do
152 rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-package_${pkg}.log"*
153 done
156 # clean up dangling symlinks to packages
157 for pkg in ${pkgname[@]}; do
158 for file in ${pkg}-*-*-${CARCH}{${PKGEXT},${SRCEXT}}; do
159 if [[ -h $file && ! -e $file ]]; then
160 rm -f $file
162 done
163 done
167 remove_deps
172 # Signal Traps
174 set -E
175 trap 'clean_up' 0
176 trap 'trap_exit "$(gettext "TERM signal caught. Exiting...")"' TERM HUP QUIT
177 trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT
178 trap 'trap_exit "$(gettext "An unknown error has occurred. Exiting...")"' ERR
180 # a source entry can have two forms :
181 # 1) "filename::http://path/to/file"
182 # 2) "http://path/to/file"
184 # Return the absolute filename of a source entry
186 # This function accepts a source entry or the already extracted filename of a
187 # source entry as input
188 get_filepath() {
189 local file="$(get_filename "$1")"
191 if [[ -f "$startdir/$file" ]]; then
192 file="$startdir/$file"
193 elif [[ -f "$SRCDEST/$file" ]]; then
194 file="$SRCDEST/$file"
195 else
196 return 1
199 echo "$file"
202 # Print 'source not found' error message and exit makepkg
203 missing_source_file() {
204 error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
205 plain "$(gettext "Aborting...")"
206 exit 1 # $E_MISSING_FILE
209 # extract the filename from a source entry
210 get_filename() {
211 # if a filename is specified, use it
212 local filename="${1%%::*}"
213 # if it is just an URL, we only keep the last component
214 echo "${filename##*/}"
217 # extract the URL from a source entry
218 get_url() {
219 # strip an eventual filename
220 echo "${1#*::}"
224 # Checks to see if options are present in makepkg.conf or PKGBUILD;
225 # PKGBUILD options always take precedence.
227 # usage : check_option( $option )
228 # return : y - enabled
229 # n - disabled
230 # ? - not found
232 check_option() {
233 local ret=$(in_opt_array "$1" ${options[@]})
234 if [[ $ret != '?' ]]; then
235 echo $ret
236 return
239 # fall back to makepkg.conf options
240 ret=$(in_opt_array "$1" ${OPTIONS[@]})
241 if [[ $ret != '?' ]]; then
242 echo $ret
243 return
246 echo '?' # Not Found
251 # Check if option is present in BUILDENV
253 # usage : check_buildenv( $option )
254 # return : y - enabled
255 # n - disabled
256 # ? - not found
258 check_buildenv() {
259 echo $(in_opt_array "$1" ${BUILDENV[@]})
264 # usage : in_opt_array( $needle, $haystack )
265 # return : y - enabled
266 # n - disabled
267 # ? - not found
269 in_opt_array() {
270 local needle=$(tr '[:upper:]' '[:lower:]' <<< $1); shift
272 local opt
273 for opt in "$@"; do
274 opt=$(tr '[:upper:]' '[:lower:]' <<< $opt)
275 if [[ $opt = $needle ]]; then
276 echo 'y' # Enabled
277 return
278 elif [[ $opt = "!$needle" ]]; then
279 echo 'n' # Disabled
280 return
282 done
284 echo '?' # Not Found
289 # usage : in_array( $needle, $haystack )
290 # return : 0 - found
291 # 1 - not found
293 in_array() {
294 local needle=$1; shift
295 [[ -z $1 ]] && return 1 # Not Found
296 local item
297 for item in "$@"; do
298 [[ $item = $needle ]] && return 0 # Found
299 done
300 return 1 # Not Found
303 get_downloadclient() {
304 # $1 = URL with valid protocol prefix
305 local url=$1
306 local proto="${url%%://*}"
308 # loop through DOWNLOAD_AGENTS variable looking for protocol
309 local i
310 for i in "${DLAGENTS[@]}"; do
311 local handler="${i%%::*}"
312 if [[ $proto = $handler ]]; then
313 local agent="${i##*::}"
314 break
316 done
318 # if we didn't find an agent, return an error
319 if [[ -z $agent ]]; then
320 error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF"
321 plain "$(gettext "Aborting...")"
322 exit 1 # $E_CONFIG_ERROR
325 # ensure specified program is installed
326 local program="${agent%% *}"
327 if [[ ! -x $program ]]; then
328 local baseprog="${program##*/}"
329 error "$(gettext "The download program %s is not installed.")" "$baseprog"
330 plain "$(gettext "Aborting...")"
331 exit 1 # $E_MISSING_PROGRAM
334 echo "$agent"
337 download_file() {
338 # download command
339 local dlcmd=$1
340 # URL of the file
341 local url=$2
342 # destination file
343 local file=$3
344 # temporary download file, default to last component of the URL
345 local dlfile="${url##*/}"
347 # replace %o by the temporary dlfile if it exists
348 if [[ $dlcmd = *%o* ]]; then
349 dlcmd=${dlcmd//\%o/\"$file.part\"}
350 dlfile="$file.part"
352 # add the URL, either in place of %u or at the end
353 if [[ $dlcmd = *%u* ]]; then
354 dlcmd=${dlcmd//\%u/\"$url\"}
355 else
356 dlcmd="$dlcmd \"$url\""
359 local ret=0
360 eval "$dlcmd || ret=\$?"
361 if (( ret )); then
362 [[ ! -s $dlfile ]] && rm -f -- "$dlfile"
363 return $ret
366 # rename the temporary download file to the final destination
367 if [[ $dlfile != $file ]]; then
368 mv -f "$SRCDEST/$dlfile" "$SRCDEST/$file"
372 run_pacman() {
373 local cmd
374 printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@"
375 if (( ! ASROOT )) && [[ ! $1 =~ ^-(T|Qq)$ ]]; then
376 if [ "$(type -p sudo)" ]; then
377 cmd="sudo $cmd"
378 else
379 cmd="su -c '$cmd'"
382 eval "$cmd"
385 check_deps() {
386 (( $# > 0 )) || return 0
388 # Disable error trap in pacman subshell call as this breaks bash-3.2 compatibility
389 # Also, a non-zero return value is not unexpected and we are manually dealing them
390 set +E
391 local ret=0
392 local pmout
393 pmout=$(run_pacman -T "$@") || ret=$?
394 set -E
396 if (( ret == 127 )); then #unresolved deps
397 echo "$pmout"
398 elif (( ret )); then
399 error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
400 exit 1
404 handle_deps() {
405 local R_DEPS_SATISFIED=0
406 local R_DEPS_MISSING=1
408 (( $# == 0 )) && return $R_DEPS_SATISFIED
410 local deplist="$*"
412 if (( ! DEP_BIN )); then
413 return $R_DEPS_MISSING
416 if (( DEP_BIN )); then
417 # install missing deps from binary packages (using pacman -S)
418 msg "$(gettext "Installing missing dependencies...")"
420 if ! run_pacman -S --asdeps $deplist; then
421 error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN"
422 exit 1 # TODO: error code
426 # we might need the new system environment
427 # avoid triggering the ERR trap
428 local restoretrap=$(trap -p ERR)
429 trap - ERR
430 source /etc/profile &>/dev/null
431 eval $restoretrap
433 return $R_DEPS_SATISFIED
436 resolve_deps() {
437 local R_DEPS_SATISFIED=0
438 local R_DEPS_MISSING=1
440 local deplist="$(check_deps $*)"
441 if [[ -z $deplist ]]; then
442 return $R_DEPS_SATISFIED
445 if handle_deps $deplist; then
446 # check deps again to make sure they were resolved
447 deplist="$(check_deps $*)"
448 [[ -z $deplist ]] && return $R_DEPS_SATISFIED
449 elif (( DEP_BIN )); then
450 error "$(gettext "Failed to install all missing dependencies.")"
453 msg "$(gettext "Missing Dependencies:")"
454 local dep
455 for dep in $deplist; do
456 msg2 "$dep"
457 done
459 return $R_DEPS_MISSING
462 remove_deps() {
463 (( ! RMDEPS )) && return
465 # check for packages removed during dependency install (e.g. due to conflicts)
466 # removing all installed packages is risky in this case
467 if [[ -n $(comm -23 <(printf "%s\n" "${original_pkglist[@]}") \
468 <(printf "%s\n" "${current_pkglist[@]}")) ]]; then
469 warning "$(gettext "Failed to remove installed dependencies.")"
470 return 0
473 local deplist=($(comm -13 <(printf "%s\n" "${original_pkglist[@]}") \
474 <(printf "%s\n" "${current_pkglist[@]}")))
475 (( ${#deplist[@]} == 0 )) && return
477 msg "Removing installed dependencies..."
478 # exit cleanly on failure to remove deps as package has been built successfully
479 if ! run_pacman -Rn ${deplist[@]}; then
480 warning "$(gettext "Failed to remove installed dependencies.")"
481 return 0
485 download_sources() {
486 msg "$(gettext "Retrieving Sources...")"
488 pushd "$SRCDEST" &>/dev/null
490 local netfile
491 for netfile in "${source[@]}"; do
492 local file
493 if file=$(get_filepath "$netfile"); then
494 msg2 "$(gettext "Found %s")" "${file##*/}"
495 ln -sf "$file" "$srcdir/"
496 continue
499 file=$(get_filename "$netfile")
500 local url=$(get_url "$netfile")
502 # if we get here, check to make sure it was a URL, else fail
503 if [[ $file = $url ]]; then
504 error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file"
505 exit 1 # $E_MISSING_FILE
508 # find the client we should use for this URL
509 local dlclient=$(get_downloadclient "$url") || exit $?
511 msg2 "$(gettext "Downloading %s...")" "$file"
512 # fix flyspray bug #3289
513 local ret=0
514 download_file "$dlclient" "$url" "$file" || ret=$?
515 if (( ret )); then
516 error "$(gettext "Failure while downloading %s")" "$file"
517 plain "$(gettext "Aborting...")"
518 exit 1
520 rm -f "$srcdir/$file"
521 ln -s "$SRCDEST/$file" "$srcdir/"
522 done
524 popd &>/dev/null
527 get_integlist() {
528 local integ
529 local integlist=()
531 for integ in md5 sha1 sha256 sha384 sha512; do
532 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
533 if [[ -n "$integrity_sums" ]]; then
534 integlist=(${integlist[@]} $integ)
536 done
538 if (( ${#integlist[@]} > 0 )); then
539 echo ${integlist[@]}
540 else
541 echo ${INTEGRITY_CHECK[@]}
545 generate_checksums() {
546 msg "$(gettext "Generating checksums for source files...")"
547 plain ""
549 if ! type -p openssl >/dev/null; then
550 error "$(gettext "Cannot find openssl.")"
551 exit 1 # $E_MISSING_PROGRAM
554 local integlist
555 if (( $# == 0 )); then
556 integlist=$(get_integlist)
557 else
558 integlist=$@
561 local integ
562 for integ in ${integlist[@]}; do
563 integ=$(tr '[:upper:]' '[:lower:]' <<< "$integ")
564 case "$integ" in
565 md5|sha1|sha256|sha384|sha512) : ;;
567 error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
568 exit 1;; # $E_CONFIG_ERROR
569 esac
571 local ct=0
572 local numsrc=${#source[@]}
573 echo -n "${integ}sums=("
575 local i
576 local indent=''
577 for (( i = 0; i < ${#integ} + 6; i++ )); do
578 indent="$indent "
579 done
581 local netfile
582 for netfile in "${source[@]}"; do
583 local file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
584 local sum="$(openssl dgst -${integ} "$file")"
585 sum=${sum##* }
586 (( ct )) && echo -n "$indent"
587 echo -n "'$sum'"
588 ct=$(($ct+1))
589 (( $ct < $numsrc )) && echo
590 done
592 echo ")"
593 done
596 check_checksums() {
597 (( ! ${#source[@]} )) && return 0
599 if ! type -p openssl >/dev/null; then
600 error "$(gettext "Cannot find openssl.")"
601 exit 1 # $E_MISSING_PROGRAM
604 local correlation=0
605 local integ required
606 for integ in md5 sha1 sha256 sha384 sha512; do
607 local integrity_sums=($(eval echo "\${${integ}sums[@]}"))
608 if (( ${#integrity_sums[@]} == ${#source[@]} )); then
609 msg "$(gettext "Validating source files with %s...")" "${integ}sums"
610 correlation=1
611 local errors=0
612 local idx=0
613 local file
614 for file in "${source[@]}"; do
615 local found=1
616 file="$(get_filename "$file")"
617 echo -n " $file ... " >&2
619 if ! file="$(get_filepath "$file")"; then
620 echo "$(gettext "NOT FOUND")" >&2
621 errors=1
622 found=0
625 if (( $found )) ; then
626 local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}")
627 local realsum="$(openssl dgst -${integ} "$file")"
628 realsum="${realsum##* }"
629 if [[ $expectedsum = $realsum ]]; then
630 echo "$(gettext "Passed")" >&2
631 else
632 echo "$(gettext "FAILED")" >&2
633 errors=1
637 idx=$((idx + 1))
638 done
640 if (( errors )); then
641 error "$(gettext "One or more files did not pass the validity check!")"
642 exit 1 # TODO: error code
644 elif (( ${#integrity_sums[@]} )); then
645 error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ"
646 exit 1 # TODO: error code
648 done
650 if (( ! correlation )); then
651 error "$(gettext "Integrity checks are missing.")"
652 exit 1 # TODO: error code
656 extract_sources() {
657 msg "$(gettext "Extracting Sources...")"
658 local netfile
659 for netfile in "${source[@]}"; do
660 local file=$(get_filename "$netfile")
661 if in_array "$file" ${noextract[@]}; then
662 #skip source files in the noextract=() array
663 # these are marked explicitly to NOT be extracted
664 continue
668 # fix flyspray #6246
669 local file_type=$(file -bizL "$file")
670 local ext=${file##*.}
671 local cmd=''
672 case "$file_type" in
673 *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
674 cmd="bsdtar" ;;
675 *application/x-gzip*)
676 case "$ext" in
677 gz|z|Z) cmd="gzip" ;;
678 *) continue;;
679 esac ;;
680 *application/x-bzip*)
681 case "$ext" in
682 bz2|bz) cmd="bzip2" ;;
683 *) continue;;
684 esac ;;
685 *application/x-xz*)
686 case "$ext" in
687 xz) cmd="xz" ;;
688 *) continue;;
689 esac ;;
691 # See if bsdtar can recognize the file
692 if bsdtar -tf "$file" -q '*' &>/dev/null; then
693 cmd="bsdtar"
694 else
695 continue
696 fi ;;
697 esac
699 local ret=0
700 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
701 if [[ $cmd = bsdtar ]]; then
702 $cmd -xf "$file" || ret=$?
703 else
704 rm -f "${file%.*}"
705 $cmd -dcf "$file" > "${file%.*}" || ret=$?
707 if (( ret )); then
708 error "$(gettext "Failed to extract %s")" "$file"
709 plain "$(gettext "Aborting...")"
710 exit 1
712 done
714 if (( EUID == 0 )); then
715 # change perms of all source files to root user & root group
716 chown -R 0:0 "$srcdir"
720 error_function() {
721 if [[ -p $logpipe ]]; then
722 rm "$logpipe"
724 # first exit all subshells, then print the error
725 if (( ! BASH_SUBSHELL )); then
726 error "$(gettext "A failure occurred in %s().")" "$1"
727 plain "$(gettext "Aborting...")"
728 remove_deps
730 exit 2 # $E_BUILD_FAILED
733 run_function() {
734 if [[ -z $1 ]]; then
735 return 1
737 local pkgfunc="$1"
739 # clear user-specified makeflags if requested
740 if [[ $(check_option makeflags) = "n" ]]; then
741 MAKEFLAGS=""
744 msg "$(gettext "Starting %s()...")" "$pkgfunc"
745 cd "$srcdir"
747 # ensure all necessary build variables are exported
748 export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
749 # save our shell options so pkgfunc() can't override what we need
750 local shellopts=$(shopt -p)
752 local ret=0
753 local restoretrap
754 if (( LOGGING )); then
755 local BUILDLOG="${startdir}/${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-$pkgfunc.log"
756 if [[ -f $BUILDLOG ]]; then
757 local i=1
758 while true; do
759 if [[ -f $BUILDLOG.$i ]]; then
760 i=$(($i +1))
761 else
762 break
764 done
765 mv "$BUILDLOG" "$BUILDLOG.$i"
768 # ensure overridden package variables survive tee with split packages
769 logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX")
770 mkfifo "$logpipe"
771 exec 3>&1
772 tee "$BUILDLOG" < "$logpipe" &
773 exec 1>"$logpipe" 2>"$logpipe"
774 restoretrap=$(trap -p ERR)
775 trap 'error_function $pkgfunc' ERR
776 $pkgfunc 2>&1
777 eval $restoretrap
778 sync
779 exec 1>&3 2>&3 3>&-
780 rm "$logpipe"
781 else
782 restoretrap=$(trap -p ERR)
783 trap 'error_function $pkgfunc' ERR
784 $pkgfunc 2>&1
785 eval $restoretrap
787 # reset our shell options
788 eval "$shellopts"
791 run_build() {
792 # use distcc if it is requested (check buildenv and PKGBUILD opts)
793 if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
794 [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
795 export DISTCC_HOSTS
796 elif [[ $(check_option distcc) = "n" ]]; then
797 # if it is not wanted, clear the makeflags too
798 MAKEFLAGS=""
801 # use ccache if it is requested (check buildenv and PKGBUILD opts)
802 if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
803 [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
806 run_function "build"
809 run_package() {
810 local pkgfunc
811 if [[ -z $1 ]]; then
812 pkgfunc="package"
813 else
814 pkgfunc="package_$1"
817 run_function "$pkgfunc"
820 tidy_install() {
821 cd "$pkgdir"
822 msg "$(gettext "Tidying install...")"
824 if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then
825 msg2 "$(gettext "Removing doc files...")"
826 rm -rf ${DOC_DIRS[@]}
829 if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then
830 msg2 "$(gettext "Purging other files...")"
831 local pt
832 for pt in "${PURGE_TARGETS[@]}"; do
833 if [[ ${pt} = ${pt//\/} ]]; then
834 find . -type f -name "${pt}" -exec rm -f -- '{}' \;
835 else
836 rm -f ${pt}
838 done
841 if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then
842 msg2 "$(gettext "Compressing man and info pages...")"
843 local manpage ext file link hardlinks hl
844 find ${MAN_DIRS[@]} -type f 2>/dev/null |
845 while read manpage ; do
846 ext="${manpage##*.}"
847 file="${manpage##*/}"
848 if [[ $ext != gz && $ext != bz2 ]]; then
849 # update symlinks to this manpage
850 find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null |
851 while read link ; do
852 rm -f "$link"
853 ln -sf "${file}.gz" "${link}.gz"
854 done
856 # check file still exists (potentially already compressed due to hardlink)
857 if [[ -f ${manpage} ]]; then
858 # find hard links and remove them
859 # the '|| true' part keeps the script from bailing if find returned an
860 # error, such as when one of the man directories doesn't exist
861 hardlinks="$(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" 2>/dev/null)" || true
862 for hl in ${hardlinks}; do
863 rm -f "${hl}";
864 done
865 # compress the original
866 gzip -9 "$manpage"
867 # recreate hard links removed earlier
868 for hl in ${hardlinks}; do
869 ln "${manpage}.gz" "${hl}.gz"
870 chmod 644 ${hl}.gz
871 done
874 done
877 if [[ $(check_option strip) = y ]]; then
878 msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
879 # make sure library stripping variables are defined to prevent excess stripping
880 [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
881 [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
882 local binary
883 find . -type f -perm -u+w 2>/dev/null | while read binary ; do
884 case "$(file -bi "$binary")" in
885 *application/x-sharedlib*) # Libraries (.so)
886 /usr/bin/strip $STRIP_SHARED "$binary";;
887 *application/x-archive*) # Libraries (.a)
888 /usr/bin/strip $STRIP_STATIC "$binary";;
889 *application/x-executable*) # Binaries
890 /usr/bin/strip $STRIP_BINARIES "$binary";;
891 esac
892 done
895 if [[ $(check_option libtool) = "n" ]]; then
896 msg2 "$(gettext "Removing libtool .la files...")"
897 find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
900 if [[ $(check_option emptydirs) = "n" ]]; then
901 msg2 "$(gettext "Removing empty directories...")"
902 find . -depth -type d -empty -delete
906 write_pkginfo() {
907 local builddate=$(date -u "+%s")
908 if [[ -n $PACKAGER ]]; then
909 local packager="$PACKAGER"
910 else
911 local packager="Unknown Packager"
913 local size="$(@DUPATH@ -sk)"
914 size="$(( ${size%%[^0-9]*} * 1024 ))"
916 msg2 "$(gettext "Generating .PKGINFO file...")"
917 echo "# Generated by makepkg $myver"
918 if (( INFAKEROOT )); then
919 echo "# using $(fakeroot -v)"
921 echo "# $(LC_ALL=C date -u)"
922 echo "pkgname = $1"
923 (( SPLITPKG )) && echo pkgbase = $pkgbase
924 echo "pkgver = $pkgver-$pkgrel"
925 echo "pkgdesc = $pkgdesc"
926 echo "url = $url"
927 echo "builddate = $builddate"
928 echo "packager = $packager"
929 echo "size = $size"
930 echo "arch = $PKGARCH"
931 if [[ $(check_option force) = "y" ]]; then
932 echo "force = true"
935 [[ $license ]] && printf "license = %s\n" "${license[@]}"
936 [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
937 [[ $groups ]] && printf "group = %s\n" "${groups[@]}"
938 [[ $depends ]] && printf "depend = %s\n" "${depends[@]}"
939 [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]}"
940 [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
941 [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
942 [[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
944 local it
945 for it in "${packaging_options[@]}"; do
946 local ret="$(check_option $it)"
947 if [[ $ret != "?" ]]; then
948 if [[ $ret = y ]]; then
949 echo "makepkgopt = $it"
950 else
951 echo "makepkgopt = !$it"
954 done
956 # TODO maybe remove this at some point
957 # warn if license array is not present or empty
958 if [[ -z $license ]]; then
959 warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
960 plain "$(gettext "Example for GPL\'ed software: license=('GPL').")"
964 check_package() {
965 cd "$pkgdir"
967 # check existence of backup files
968 local file
969 for file in "${backup[@]}"; do
970 if [[ ! -f $file ]]; then
971 warning "$(gettext "Backup entry file not in package : %s")" "$file"
973 done
975 # check for references to the build and package directory
976 if find "${pkgdir}" -type f -exec grep -q -I "${srcdir}" {} +; then
977 warning "$(gettext "Package contains reference to %s")" "\$srcdir"
979 if find "${pkgdir}" -type f -exec grep -q -I "${pkgdir}" {} +; then
980 warning "$(gettext "Package contains reference to %s")" "\$pkgdir"
985 create_package() {
986 if [[ ! -d $pkgdir ]]; then
987 error "$(gettext "Missing pkg/ directory.")"
988 plain "$(gettext "Aborting...")"
989 exit 1 # $E_MISSING_PKGDIR
992 check_package
994 cd "$pkgdir"
995 msg "$(gettext "Creating package...")"
997 local nameofpkg
998 if [[ -z $1 ]]; then
999 nameofpkg="$pkgname"
1000 else
1001 nameofpkg="$1"
1004 if [[ $arch = "any" ]]; then
1005 PKGARCH="any"
1006 else
1007 PKGARCH=$CARCH
1010 write_pkginfo $nameofpkg > .PKGINFO
1012 local comp_files=".PKGINFO"
1014 # check for changelog/install files
1015 for i in 'changelog' 'install'; do
1016 orig=${!i}
1017 dest=$(tr '[:lower:]' '[:upper:]' <<<".$i")
1019 if [[ -n $orig ]]; then
1020 msg2 "$(gettext "Adding %s file...")" "$i"
1021 cp "$startdir/$orig" "$dest"
1022 chmod 644 "$dest"
1023 comp_files+=" $dest"
1025 done
1027 # tar it up
1028 msg2 "$(gettext "Compressing package...")"
1030 local EXT
1031 case "$PKGEXT" in
1032 *tar.gz) EXT=${PKGEXT%.gz} ;;
1033 *tar.bz2) EXT=${PKGEXT%.bz2} ;;
1034 *tar.xz) EXT=${PKGEXT%.xz} ;;
1035 *tar) EXT=${PKGEXT} ;;
1036 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1037 "$PKGEXT" ; EXT=$PKGEXT ;;
1038 esac
1040 local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${PKGARCH}${PKGEXT}"
1041 local ret=0
1043 # when fileglobbing, we want * in an empty directory to expand to
1044 # the null string rather than itself
1045 shopt -s nullglob
1046 # TODO: Maybe this can be set globally for robustness
1047 shopt -s -o pipefail
1048 bsdtar -cf - $comp_files * |
1049 case "$PKGEXT" in
1050 *tar.gz) gzip -c -f -n ;;
1051 *tar.bz2) bzip2 -c -f ;;
1052 *tar.xz) xz -c -z - ;;
1053 *tar) cat ;;
1054 esac > ${pkg_file} || ret=$?
1056 shopt -u nullglob
1057 shopt -u -o pipefail
1059 if (( ret )); then
1060 error "$(gettext "Failed to create package file.")"
1061 exit 1 # TODO: error code
1064 if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
1065 ln -sf "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
1066 ret=$?
1069 if (( ret )); then
1070 warning "$(gettext "Failed to create symlink to package file.")"
1074 create_srcpackage() {
1075 cd "$startdir"
1077 # Get back to our src directory so we can begin with sources.
1078 mkdir -p "$srcdir"
1079 chmod a-s "$srcdir"
1080 cd "$srcdir"
1081 if (( ! SKIPINTEG || SOURCEONLY == 2 )); then
1082 download_sources
1084 if (( ! SKIPINTEG )); then
1085 # We can only check checksums if we have all files.
1086 check_checksums
1087 else
1088 warning "$(gettext "Skipping integrity checks.")"
1090 cd "$startdir"
1092 msg "$(gettext "Creating source package...")"
1093 local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
1094 mkdir "${srclinks}"/${pkgbase}
1096 msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
1097 ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
1099 local file
1100 for file in "${source[@]}"; do
1101 if [[ -f $file ]]; then
1102 msg2 "$(gettext "Adding %s...")" "$file"
1103 ln -s "${startdir}/$file" "$srclinks/$pkgbase"
1104 elif (( SOURCEONLY == 2 )); then
1105 local absfile=$(get_filepath "$file") || missing_source_file "$file"
1106 msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
1107 ln -s "$absfile" "$srclinks/$pkgbase"
1109 done
1111 local i
1112 for i in 'changelog' 'install'; do
1113 local filelist=$(sed -n "s/^[[:space:]]*$i=//p" "$BUILDSCRIPT")
1114 local file
1115 for file in $filelist; do
1116 # evaluate any bash variables used
1117 eval file=${file}
1118 if [[ ! -f "${srclinks}/${pkgbase}/$file" ]]; then
1119 msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
1120 ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
1122 done
1123 done
1125 local TAR_OPT
1126 case "$SRCEXT" in
1127 *tar.gz) TAR_OPT="z" ;;
1128 *tar.bz2) TAR_OPT="j" ;;
1129 *tar.xz) TAR_OPT="J" ;;
1130 *tar) TAR_OPT="" ;;
1131 *) warning "$(gettext "'%s' is not a valid archive extension.")" \
1132 "$SRCEXT" ;;
1133 esac
1135 local pkg_file="$SRCPKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT}"
1137 # tar it up
1138 msg2 "$(gettext "Compressing source package...")"
1139 cd "${srclinks}"
1140 if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
1141 error "$(gettext "Failed to create source package file.")"
1142 exit 1 # TODO: error code
1145 if (( ! ret )) && [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
1146 ln -sf "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
1147 ret=$?
1150 if (( ret )); then
1151 warning "$(gettext "Failed to create symlink to source package file.")"
1154 cd "${startdir}"
1155 rm -rf "${srclinks}"
1158 install_package() {
1159 (( ! INSTALL )) && return
1161 if (( ! SPLITPKG )); then
1162 msg "$(gettext "Installing package %s with %s -U...")" "$pkgname" "$PACMAN"
1163 else
1164 msg "$(gettext "Installing %s package group with %s -U...")" "$pkgbase" "$PACMAN"
1167 local pkg pkglist
1168 for pkg in ${pkgname[@]}; do
1169 if [[ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} ]]; then
1170 pkglist+=" $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}"
1171 else
1172 pkglist+=" $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT}"
1174 done
1176 if ! run_pacman -U $pkglist; then
1177 warning "$(gettext "Failed to install built package(s).")"
1178 return 0
1182 check_sanity() {
1183 # check for no-no's in the build script
1184 local i
1185 for i in 'pkgname' 'pkgrel' 'pkgver'; do
1186 if [[ -z ${!i} ]]; then
1187 error "$(gettext "%s is not allowed to be empty.")" "$i"
1188 return 1
1190 done
1192 for i in "${pkgname[@]}"; do
1193 if [[ ${i:0:1} = "-" ]]; then
1194 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname"
1195 return 1
1197 done
1199 if [[ ${pkgbase:0:1} = "-" ]]; then
1200 error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase"
1201 return 1
1203 if [[ $pkgver != ${pkgver//-/} ]]; then
1204 error "$(gettext "%s is not allowed to contain hyphens.")" "pkgver"
1205 return 1
1207 if [[ $pkgrel != ${pkgrel//-/} ]]; then
1208 error "$(gettext "%s is not allowed to contain hyphens.")" "pkgrel"
1209 return 1
1212 if [[ $arch != 'any' ]]; then
1213 if ! in_array $CARCH ${arch[@]}; then
1214 if (( ! IGNOREARCH )); then
1215 error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH"
1216 plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT"
1217 plain "$(gettext "such as arch=('%s').")" "$CARCH"
1218 return 1
1223 for i in ${provides[@]}; do
1224 if [[ $i != ${i//</} || $i != ${i//>/} ]]; then
1225 error "$(gettext "Provides array cannot contain comparison (< or >) operators.")"
1226 return 1
1228 done
1230 for i in "${backup[@]}"; do
1231 if [[ ${i:0:1} = "/" ]]; then
1232 error "$(gettext "Backup entry should not contain leading slash : %s")" "$i"
1233 return 1
1235 done
1237 for i in "${optdepends[@]}"; do
1238 local pkg=${i%%:*}
1239 if [[ ! $pkg =~ ^[[:alnum:]\>\<\=\.\+\_\-]+$ ]]; then
1240 error "$(gettext "Invalid syntax for optdepend : '%s'")" "$i"
1242 done
1244 for i in 'changelog' 'install'; do
1245 local filelist=$(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE")
1246 local file
1247 for file in $filelist; do
1248 # evaluate any bash variables used
1249 eval file=${file}
1250 if [[ ! -f $file ]]; then
1251 error "$(gettext "%s file (%s) does not exist.")" "$i" "$file"
1252 return 1
1254 done
1255 done
1257 local valid_options=1
1258 local known kopt
1259 for i in ${options[@]}; do
1260 known=0
1261 # check if option matches a known option or its inverse
1262 for kopt in ${packaging_options[@]} ${other_options[@]}; do
1263 if [[ ${i} = ${kopt} || ${i} = "!${kopt}" ]]; then
1264 known=1
1266 done
1267 if (( ! known )); then
1268 error "$(gettext "options array contains unknown option '%s'")" "$i"
1269 valid_options=0
1271 done
1272 if (( ! valid_options )); then
1273 return 1
1276 if (( ${#pkgname[@]} > 1 )); then
1277 for i in ${pkgname[@]}; do
1278 if ! declare -f package_${i} >/dev/null; then
1279 error "$(gettext "missing package function for split package '%s'")" "$i"
1280 return 1
1282 done
1285 for i in ${PKGLIST[@]}; do
1286 if ! in_array $i ${pkgname[@]}; then
1287 error "$(gettext "requested package %s is not provided in %s")" "$i" "$BUILDFILE"
1288 return 1
1290 done
1292 return 0
1295 devel_check() {
1296 newpkgver=""
1298 # Do not update pkgver if --holdver is set, when building a source package, repackaging,
1299 # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w)
1300 if (( HOLDVER || SOURCEONLY || REPKG )) \
1301 || [[ ! -f $BUILDFILE || ! -w $BUILDFILE ]]; then
1302 return
1305 if [[ -z $FORCE_VER ]]; then
1306 # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so.
1307 # This will only be used on the first call to makepkg; subsequent
1308 # calls to makepkg via fakeroot will explicitly pass the version
1309 # number to avoid having to determine the version number twice.
1310 # Also do a brief check to make sure we have the VCS tool available.
1311 oldpkgver=$pkgver
1312 if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then
1313 type -p darcs >/dev/null || return 0
1314 msg "$(gettext "Determining latest darcs revision...")"
1315 newpkgver=$(date +%Y%m%d)
1316 elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then
1317 type -p cvs >/dev/null || return 0
1318 msg "$(gettext "Determining latest cvs revision...")"
1319 newpkgver=$(date +%Y%m%d)
1320 elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then
1321 type -p git >/dev/null || return 0
1322 msg "$(gettext "Determining latest git revision...")"
1323 newpkgver=$(date +%Y%m%d)
1324 elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then
1325 type -p svn >/dev/null || return 0
1326 msg "$(gettext "Determining latest svn revision...")"
1327 newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p')
1328 elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then
1329 type -p bzr >/dev/null || return 0
1330 msg "$(gettext "Determining latest bzr revision...")"
1331 newpkgver=$(bzr revno ${_bzrtrunk})
1332 elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then
1333 type -p hg >/dev/null || return 0
1334 msg "$(gettext "Determining latest hg revision...")"
1335 if [[ -d ./src/$_hgrepo ]] ; then
1336 cd ./src/$_hgrepo
1337 hg pull
1338 hg update
1339 else
1340 [[ ! -d ./src/ ]] && mkdir ./src/
1341 hg clone $_hgroot/$_hgrepo ./src/$_hgrepo
1342 cd ./src/$_hgrepo
1344 newpkgver=$(hg tip --template "{rev}")
1345 cd ../../
1348 if [[ -n $newpkgver ]]; then
1349 msg2 "$(gettext "Version found: %s")" "$newpkgver"
1352 else
1353 # Version number retrieved from fakeroot->makepkg argument
1354 newpkgver=$FORCE_VER
1358 devel_update() {
1359 # This is lame, but if we're wanting to use an updated pkgver for
1360 # retrieving svn/cvs/etc sources, we'll update the PKGBUILD with
1361 # the new pkgver and then re-source it. This is the most robust
1362 # method for dealing with PKGBUILDs that use, e.g.:
1364 # pkgver=23
1365 # ...
1366 # _foo=pkgver
1368 if [[ -n $newpkgver ]]; then
1369 if [[ $newpkgver != $pkgver ]]; then
1370 if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
1371 @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
1372 @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
1373 source "$BUILDFILE"
1379 backup_package_variables() {
1380 local var
1381 for var in ${splitpkg_overrides[@]}; do
1382 local indirect="${var}_backup"
1383 eval "${indirect}=(\"\${$var[@]}\")"
1384 done
1387 restore_package_variables() {
1388 local var
1389 for var in ${splitpkg_overrides[@]}; do
1390 local indirect="${var}_backup"
1391 if [[ -n ${!indirect} ]]; then
1392 eval "${var}=(\"\${$indirect[@]}\")"
1393 else
1394 unset ${var}
1396 done
1399 run_split_packaging() {
1400 for pkg in ${pkgname[@]}; do
1401 pkgdir="$pkgdir/$pkg"
1402 mkdir -p "$pkgdir"
1403 chmod a-s "$pkgdir"
1404 backup_package_variables
1405 run_package $pkg
1406 tidy_install
1407 create_package $pkg
1408 restore_package_variables
1409 pkgdir="${pkgdir%/*}"
1410 done
1413 # Canonicalize a directory path if it exists
1414 canonicalize_path() {
1415 local path="$1";
1417 if [[ -d $path ]]; then
1419 cd "$path"
1420 pwd -P
1422 else
1423 echo "$path"
1427 # getopt like parser
1428 parse_options() {
1429 local short_options=$1; shift;
1430 local long_options=$1; shift;
1431 local ret=0;
1432 local unused_options=""
1433 local i
1435 while [[ -n $1 ]]; do
1436 if [[ ${1:0:2} = '--' ]]; then
1437 if [[ -n ${1:2} ]]; then
1438 local match=""
1439 for i in ${long_options//,/ }; do
1440 if [[ ${1:2} = ${i//:} ]]; then
1441 match=$i
1442 break
1444 done
1445 if [[ -n $match ]]; then
1446 if [[ ${1:2} = $match ]]; then
1447 printf ' %s' "$1"
1448 else
1449 if [[ -n $2 ]]; then
1450 printf ' %s' "$1"
1451 shift
1452 printf " '%s'" "$1"
1453 else
1454 echo "makepkg: option '$1' $(gettext "requires an argument")" >&2
1455 ret=1
1458 else
1459 echo "makepkg: $(gettext "unrecognized option") '$1'" >&2
1460 ret=1
1462 else
1463 shift
1464 break
1466 elif [[ ${1:0:1} = '-' ]]; then
1467 for ((i=1; i<${#1}; i++)); do
1468 if [[ $short_options =~ ${1:i:1} ]]; then
1469 if [[ $short_options =~ ${1:i:1}: ]]; then
1470 if [[ -n ${1:$i+1} ]]; then
1471 printf ' -%s' "${1:i:1}"
1472 printf " '%s'" "${1:$i+1}"
1473 else
1474 if [[ -n $2 ]]; then
1475 printf ' -%s' "${1:i:1}"
1476 shift
1477 printf " '%s'" "${1}"
1478 else
1479 echo "makepkg: option $(gettext "requires an argument") -- '${1:i:1}'" >&2
1480 ret=1
1483 break
1484 else
1485 printf ' -%s' "${1:i:1}"
1487 else
1488 echo "makepkg: $(gettext "invalid option") -- '${1:i:1}'" >&2
1489 ret=1
1491 done
1492 else
1493 unused_options="${unused_options} '$1'"
1495 shift
1496 done
1498 printf " --"
1499 if [[ -n $unused_options ]]; then
1500 for i in ${unused_options[@]}; do
1501 printf ' %s' "$i"
1502 done
1504 if [[ -n $1 ]]; then
1505 while [[ -n $1 ]]; do
1506 printf " '%s'" "${1}"
1507 shift
1508 done
1510 printf "\n"
1512 return $ret
1515 usage() {
1516 printf "makepkg (pacman) %s\n" "$myver"
1517 echo
1518 printf "$(gettext "Usage: %s [options]")\n" "$0"
1519 echo
1520 echo "$(gettext "Options:")"
1521 printf "$(gettext " -A, --ignorearch Ignore incomplete arch field in %s")\n" "$BUILDSCRIPT"
1522 echo "$(gettext " -c, --clean Clean up work files after build")"
1523 echo "$(gettext " -C, --cleancache Clean up source files from the cache")"
1524 echo "$(gettext " -d, --nodeps Skip all dependency checks")"
1525 echo "$(gettext " -e, --noextract Do not extract source files (use existing src/ dir)")"
1526 echo "$(gettext " -f, --force Overwrite existing package")"
1527 echo "$(gettext " -g, --geninteg Generate integrity checks for source files")"
1528 echo "$(gettext " -h, --help This help")"
1529 echo "$(gettext " -i, --install Install package after successful build")"
1530 echo "$(gettext " -L, --log Log package build process")"
1531 echo "$(gettext " -m, --nocolor Disable colorized output messages")"
1532 echo "$(gettext " -o, --nobuild Download and extract files only")"
1533 printf "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
1534 echo "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")"
1535 echo "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")"
1536 echo "$(gettext " -s, --syncdeps Install missing dependencies with pacman")"
1537 echo "$(gettext " --allsource Generate a source-only tarball including downloaded sources")"
1538 echo "$(gettext " --asroot Allow makepkg to run as root user")"
1539 printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
1540 echo "$(gettext " --holdver Prevent automatic version bumping for development PKGBUILDs")"
1541 echo "$(gettext " --pkg <list> Only build listed packages from a split package")"
1542 echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")"
1543 echo "$(gettext " --source Generate a source-only tarball without downloaded sources")"
1544 echo
1545 echo "$(gettext "These options can be passed to pacman:")"
1546 echo
1547 echo "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")"
1548 echo "$(gettext " --noprogressbar Do not show a progress bar when downloading files")"
1549 echo
1550 printf "$(gettext "If -p is not specified, makepkg will look for '%s'")\n" "$BUILDSCRIPT"
1551 echo
1554 version() {
1555 printf "makepkg (pacman) %s\n" "$myver"
1556 printf "$(gettext "\
1557 Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org>.\n\
1558 Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\
1559 This is free software; see the source for copying conditions.\n\
1560 There is NO WARRANTY, to the extent permitted by law.\n")"
1563 # PROGRAM START
1565 # determine whether we have gettext; make it a no-op if we do not
1566 if ! type -p gettext >/dev/null; then
1567 gettext() {
1568 echo "$@"
1572 ARGLIST=("$@")
1574 # Parse Command Line Options.
1575 OPT_SHORT="AcCdefFghiLmop:rRsV"
1576 OPT_LONG="allsource,asroot,ignorearch,clean,cleancache,nodeps"
1577 OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver"
1578 OPT_LONG+=",install,log,nocolor,nobuild,pkg:,rmdeps,repackage,skipinteg"
1579 OPT_LONG+=",source,syncdeps,version,config:"
1580 # Pacman Options
1581 OPT_LONG+=",noconfirm,noprogressbar"
1582 OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'PARSE_OPTIONS FAILED')"
1583 if [[ $OPT_TEMP = *'PARSE_OPTIONS FAILED'* ]]; then
1584 # This is a small hack to stop the script bailing with 'set -e'
1585 echo; usage; exit 1 # E_INVALID_OPTION;
1587 eval set -- "$OPT_TEMP"
1588 unset OPT_SHORT OPT_LONG OPT_TEMP
1590 while true; do
1591 case "$1" in
1592 # Pacman Options
1593 --noconfirm) PACMAN_OPTS+=" --noconfirm" ;;
1594 --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;;
1596 # Makepkg Options
1597 --allsource) SOURCEONLY=2 ;;
1598 --asroot) ASROOT=1 ;;
1599 -A|--ignorearch) IGNOREARCH=1 ;;
1600 -c|--clean) CLEANUP=1 ;;
1601 -C|--cleancache) CLEANCACHE=1 ;;
1602 --config) shift; MAKEPKG_CONF=$1 ;;
1603 -d|--nodeps) NODEPS=1 ;;
1604 -e|--noextract) NOEXTRACT=1 ;;
1605 -f|--force) FORCE=1 ;;
1606 #hidden opt used by fakeroot call for svn/cvs/etc PKGBUILDs to set pkgver
1607 --forcever) shift; FORCE_VER=$1;;
1608 -F) INFAKEROOT=1 ;;
1609 -g|--geninteg) GENINTEG=1 ;;
1610 --holdver) HOLDVER=1 ;;
1611 -i|--install) INSTALL=1 ;;
1612 -L|--log) LOGGING=1 ;;
1613 -m|--nocolor) USE_COLOR='n' ;;
1614 -o|--nobuild) NOBUILD=1 ;;
1615 -p) shift; BUILDFILE=$1 ;;
1616 --pkg) shift; PKGLIST=($1) ;;
1617 -r|--rmdeps) RMDEPS=1 ;;
1618 -R|--repackage) REPKG=1 ;;
1619 --skipinteg) SKIPINTEG=1 ;;
1620 --source) SOURCEONLY=1 ;;
1621 -s|--syncdeps) DEP_BIN=1 ;;
1623 -h|--help) usage; exit 0 ;; # E_OK
1624 -V|--version) version; exit 0 ;; # E_OK
1626 --) OPT_IND=0; shift; break;;
1627 *) usage; exit 1 ;; # E_INVALID_OPTION
1628 esac
1629 shift
1630 done
1632 # preserve environment variables and canonicalize path
1633 [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
1634 [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
1635 [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
1637 # default config is makepkg.conf
1638 MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
1640 # Source the config file; fail if it is not found
1641 if [[ -r $MAKEPKG_CONF ]]; then
1642 source "$MAKEPKG_CONF"
1643 else
1644 error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
1645 plain "$(gettext "Aborting...")"
1646 exit 1 # $E_CONFIG_ERROR
1649 # Source user-specific makepkg.conf overrides
1650 if [[ -r ~/.makepkg.conf ]]; then
1651 source ~/.makepkg.conf
1654 # set pacman command if not already defined
1655 PACMAN=${PACMAN:-pacman}
1657 # check if messages are to be printed using color
1658 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
1659 if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then
1660 # prefer terminal safe colored and bold text when tput is supported
1661 if tput setaf 0 &>/dev/null; then
1662 ALL_OFF="$(tput sgr0)"
1663 BOLD="$(tput bold)"
1664 BLUE="${BOLD}$(tput setaf 4)"
1665 GREEN="${BOLD}$(tput setaf 2)"
1666 RED="${BOLD}$(tput setaf 1)"
1667 YELLOW="${BOLD}$(tput setaf 3)"
1668 else
1669 ALL_OFF="\033[1;0m"
1670 BOLD="\033[1;1m"
1671 BLUE="${BOLD}\033[1;34m"
1672 GREEN="${BOLD}\033[1;32m"
1673 RED="${BOLD}\033[1;31m"
1674 YELLOW="${BOLD}\033[1;33m"
1677 readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
1679 # override settings with an environment variable for batch processing
1680 PKGDEST=${_PKGDEST:-$PKGDEST}
1681 PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
1682 if [[ ! -w $PKGDEST ]]; then
1683 error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST"
1684 plain "$(gettext "Aborting...")"
1685 exit 1
1688 SRCDEST=${_SRCDEST:-$SRCDEST}
1689 SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined
1690 if [[ ! -w $SRCDEST ]] ; then
1691 error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST"
1692 plain "$(gettext "Aborting...")"
1693 exit 1
1696 SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST}
1697 SRCPKGDEST=${SRCPKGDEST:-$PKGDEST} #default to $PKGDEST if undefined
1700 if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then
1701 # The '\\0' is here to prevent gettext from thinking --holdver is an option
1702 error "$(gettext "\\0--holdver and --forcever cannot both be specified" )"
1703 exit 1
1706 if (( CLEANCACHE )); then
1707 #fix flyspray feature request #5223
1708 if [[ -n $SRCDEST && ! $SRCDEST -ef "${startdir}" ]]; then
1709 msg "$(gettext "Cleaning up ALL files from %s.")" "$SRCDEST"
1710 echo -n "$(gettext " Are you sure you wish to do this? ")"
1711 echo -n "$(gettext "[y/N]")"
1712 read answer
1713 answer=$(tr '[:lower:]' '[:upper:]' <<< "$answer")
1714 if [[ $answer = $(gettext YES) || $answer = $(gettext Y) ]]; then
1715 rm "$SRCDEST"/*
1716 if (( $? )); then
1717 error "$(gettext "Problem removing files; you may not have correct permissions in %s")" "$SRCDEST"
1718 exit 1
1719 else
1720 # removal worked
1721 msg "$(gettext "Source cache cleaned.")"
1722 exit 0
1724 else
1725 # answer = no
1726 msg "$(gettext "No files have been removed.")"
1727 exit 0
1729 else
1730 # $SRCDEST is $startdir, two possibilities
1731 error "$(gettext "Source destination must be defined in %s.")" "$MAKEPKG_CONF"
1732 plain "$(gettext "In addition, please run makepkg -C outside of your cache directory.")"
1733 exit 1
1737 if (( ! INFAKEROOT )); then
1738 if (( EUID == 0 && ! ASROOT )); then
1739 # Warn those who like to live dangerously.
1740 error "$(gettext "Running makepkg as root is a BAD idea and can cause")"
1741 plain "$(gettext "permanent, catastrophic damage to your system. If you")"
1742 plain "$(gettext "wish to run as root, please use the --asroot option.")"
1743 exit 1 # $E_USER_ABORT
1744 elif (( EUID > 0 && ASROOT )); then
1745 # Warn those who try to use the --asroot option when they are not root
1746 error "$(gettext "The --asroot option is meant for the root user only.")"
1747 plain "$(gettext "Please rerun makepkg without the --asroot flag.")"
1748 exit 1 # $E_USER_ABORT
1749 elif [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then
1750 if ! type -p fakeroot >/dev/null; then
1751 error "$(gettext "Fakeroot must be installed if using the 'fakeroot' option")"
1752 plain "$(gettext "in the BUILDENV array in %s.")" "$MAKEPKG_CONF"
1753 exit 1
1755 elif (( EUID > 0 )); then
1756 warning "$(gettext "Running makepkg as an unprivileged user will result in non-root")"
1757 plain "$(gettext "ownership of the packaged files. Try using the fakeroot environment by")"
1758 plain "$(gettext "placing 'fakeroot' in the BUILDENV array in %s.")" "$MAKEPKG_CONF"
1759 sleep 1
1761 else
1762 if [[ -z $FAKEROOTKEY ]]; then
1763 error "$(gettext "Do not use the '-F' option. This option is only for use by makepkg.")"
1764 exit 1 # TODO: error code
1768 # check for sudo if we will need it during makepkg execution
1769 if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
1770 if ! type -p sudo >/dev/null; then
1771 warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")"
1775 unset pkgname pkgbase pkgver pkgrel pkgdesc url license groups provides
1776 unset md5sums replaces depends conflicts backup source install changelog build
1777 unset makedepends optdepends options noextract
1779 BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
1780 if [[ ! -f $BUILDFILE ]]; then
1781 if [[ -t 0 ]]; then
1782 error "$(gettext "%s does not exist.")" "$BUILDFILE"
1783 exit 1
1784 else
1785 # PKGBUILD passed through a pipe
1786 BUILDFILE=/dev/stdin
1787 source "$BUILDFILE"
1789 else
1790 crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
1791 if [[ -n $crlftest ]]; then
1792 error "$(gettext "%s contains CRLF characters and cannot be sourced.")" "$BUILDFILE"
1793 exit 1
1796 if [[ ${BUILDFILE:0:1} != "/" ]]; then
1797 BUILDFILE="$startdir/$BUILDFILE"
1799 source "$BUILDFILE"
1802 if (( GENINTEG )); then
1803 mkdir -p "$srcdir"
1804 chmod a-s "$srcdir"
1805 cd "$srcdir"
1806 download_sources
1807 generate_checksums
1808 exit 0 # $E_OK
1811 # check the PKGBUILD for some basic requirements
1812 check_sanity || exit 1
1814 # We need to run devel_update regardless of whether we are in the fakeroot
1815 # build process so that if the user runs makepkg --forcever manually, we
1816 # 1) output the correct pkgver, and 2) use the correct filename when
1817 # checking if the package file already exists - fixes FS #9194
1818 devel_check
1819 devel_update
1821 if (( ${#pkgname[@]} > 1 )); then
1822 SPLITPKG=1
1825 # test for available PKGBUILD functions
1826 if declare -f build >/dev/null; then
1827 BUILDFUNC=1
1829 if declare -f package >/dev/null; then
1830 PKGFUNC=1
1831 elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then
1832 SPLITPKG=1
1835 pkgbase=${pkgbase:-${pkgname[0]}}
1837 if [[ -n "${PKGLIST[@]}" ]]; then
1838 unset pkgname
1839 pkgname=("${PKGLIST[@]}")
1842 if (( ! SPLITPKG )); then
1843 if [[ -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} \
1844 || -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-any${PKGEXT} ]] \
1845 && ! (( FORCE || SOURCEONLY || NOBUILD )); then
1846 if (( INSTALL )); then
1847 warning "$(gettext "A package has already been built, installing existing package...")"
1848 install_package
1849 exit $?
1850 else
1851 error "$(gettext "A package has already been built. (use -f to overwrite)")"
1852 exit 1
1855 else
1856 allpkgbuilt=1
1857 somepkgbuilt=0
1858 for pkg in ${pkgname[@]}; do
1859 if [[ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} \
1860 || -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT} ]]; then
1861 somepkgbuilt=1
1862 else
1863 allpkgbuilt=0
1865 done
1866 if ! (( FORCE || SOURCEONLY || NOBUILD )); then
1867 if (( allpkgbuilt )); then
1868 if (( INSTALL )); then
1869 warning "$(gettext "The package group has already been built, installing existing packages...")"
1870 install_package
1871 exit $?
1872 else
1873 error "$(gettext "The package group has already been built. (use -f to overwrite)")"
1874 exit 1
1877 if (( somepkgbuilt )); then
1878 error "$(gettext "Part of the package group has already been built. (use -f to overwrite)")"
1879 exit 1
1882 unset allpkgbuilt somepkgbuilt
1885 # Run the bare minimum in fakeroot
1886 if (( INFAKEROOT )); then
1887 if (( ! SPLITPKG )); then
1888 if (( ! PKGFUNC )); then
1889 if (( ! REPKG )); then
1890 if (( BUILDFUNC )); then
1891 run_build
1892 tidy_install
1894 else
1895 warning "$(gettext "Repackaging without the use of a package() function is deprecated.")"
1896 plain "$(gettext "File permissions may not be preserved.")"
1898 else
1899 run_package
1900 tidy_install
1902 create_package
1903 else
1904 run_split_packaging
1907 msg "$(gettext "Leaving fakeroot environment.")"
1908 exit 0 # $E_OK
1911 msg "$(gettext "Making package: %s")" "$pkgbase $pkgver-$pkgrel ($(date))"
1913 # if we are creating a source-only package, go no further
1914 if (( SOURCEONLY )); then
1915 if [[ -f $SRCPKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT} ]] \
1916 && (( ! FORCE )); then
1917 error "$(gettext "A source package has already been built. (use -f to overwrite)")"
1918 exit 1
1920 create_srcpackage
1921 msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
1922 exit 0
1925 if (( NODEPS || ( (NOBUILD || REPKG) && !DEP_BIN ) )); then
1926 # no warning message needed for nobuild, repkg
1927 if (( NODEPS || ( REPKG && PKGFUNC ) )); then
1928 warning "$(gettext "Skipping dependency checks.")"
1930 elif type -p "${PACMAN%% *}" >/dev/null; then
1931 if (( RMDEPS )); then
1932 original_pkglist=($(run_pacman -Qq)) # required by remove_dep
1934 deperr=0
1936 msg "$(gettext "Checking runtime dependencies...")"
1937 resolve_deps ${depends[@]} || deperr=1
1939 msg "$(gettext "Checking buildtime dependencies...")"
1940 resolve_deps ${makedepends[@]} || deperr=1
1942 if (( RMDEPS )); then
1943 current_pkglist=($(run_pacman -Qq)) # required by remove_deps
1946 if (( deperr )); then
1947 error "$(gettext "Could not resolve all dependencies.")"
1948 exit 1
1950 else
1951 warning "$(gettext "%s was not found in PATH; skipping dependency checks.")" "${PACMAN%% *}"
1954 # ensure we have a sane umask set
1955 umask 0022
1957 # get back to our src directory so we can begin with sources
1958 mkdir -p "$srcdir"
1959 chmod a-s "$srcdir"
1960 cd "$srcdir"
1962 if (( NOEXTRACT )); then
1963 warning "$(gettext "Skipping source retrieval -- using existing src/ tree")"
1964 warning "$(gettext "Skipping source integrity checks -- using existing src/ tree")"
1965 warning "$(gettext "Skipping source extraction -- using existing src/ tree")"
1967 if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then
1968 error "$(gettext "The source directory is empty, there is nothing to build!")"
1969 plain "$(gettext "Aborting...")"
1970 exit 1
1972 elif (( REPKG )); then
1973 if (( ! PKGFUNC && ! SPLITPKG )) \
1974 && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then
1975 error "$(gettext "The package directory is empty, there is nothing to repackage!")"
1976 plain "$(gettext "Aborting...")"
1977 exit 1
1979 else
1980 download_sources
1981 if (( ! SKIPINTEG )); then
1982 check_checksums
1983 else
1984 warning "$(gettext "Skipping integrity checks.")"
1986 extract_sources
1989 if (( NOBUILD )); then
1990 msg "$(gettext "Sources are ready.")"
1991 exit 0 #E_OK
1992 else
1993 # check for existing pkg directory; don't remove if we are repackaging
1994 if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then
1995 msg "$(gettext "Removing existing pkg/ directory...")"
1996 rm -rf "$pkgdir"
1998 mkdir -p "$pkgdir"
1999 chmod a-s "$pkgdir"
2000 cd "$startdir"
2002 # if we are root or if fakeroot is not enabled, then we don't use it
2003 if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
2004 if (( ! REPKG )); then
2005 devel_update
2006 (( BUILDFUNC )) && run_build
2008 if (( ! SPLITPKG )); then
2009 if (( PKGFUNC )); then
2010 run_package
2011 tidy_install
2012 else
2013 if (( ! REPKG )); then
2014 tidy_install
2015 else
2016 warning "$(gettext "Repackaging without the use of a package() function is deprecated.")"
2017 plain "$(gettext "File permissions may not be preserved.")"
2020 create_package
2021 else
2022 run_split_packaging
2024 else
2025 if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then
2026 devel_update
2027 (( BUILDFUNC )) && run_build
2028 cd "$startdir"
2031 msg "$(gettext "Entering fakeroot environment...")"
2033 if [[ -n $newpkgver ]]; then
2034 fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $?
2035 else
2036 fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
2041 msg "$(gettext "Finished making: %s")" "$pkgbase $pkgver-$pkgrel ($(date))"
2043 install_package
2045 exit 0 #E_OK
2047 # vim: set ts=2 sw=2 noet: