#!/usr/bin/bash # # makepkg - make packages compatible for use with pacman # Generated from makepkg.sh.in; do not edit by hand. # # Copyright (c) 2021 by Pekka Helenius # Copyright (c) 2006-2018 Pacman Development Team # Copyright (c) 2002-2006 by Judd Vinet # Copyright (c) 2005 by Aurelien Foret # Copyright (c) 2006 by Miklos Vajna # Copyright (c) 2005 by Christian Hamar # Copyright (c) 2006 by Alex Smith # Copyright (c) 2006 by Andras Voroskoi # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # makepkg uses quite a few external programs during its execution. You # need to have at least the following installed for makepkg to function: # awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils), # gettext, gpg, grep, gzip, sed, tput (ncurses), xz # gettext initialization export TEXTDOMAIN='pacman-scripts' export TEXTDOMAINDIR='/usr/share/locale' # file -i does not work on Mac OSX unless legacy mode is set export COMMAND_MODE='legacy' # Ensure CDPATH doesn't screw with our cd calls unset CDPATH # Ensure GREP_OPTIONS doesn't screw with our grep calls unset GREP_OPTIONS declare -r makepkg_version='5.1.3' declare -r confdir='/etc' declare -r BUILDSCRIPT='PKGBUILD' declare -r startdir="$(pwd -P)" LIBRARY=${LIBRARY:-'/usr/share/makepkg'} build_options=('ccache' 'distcc' 'buildflags' 'makeflags') splitpkg_overrides=('pkgdesc' 'arch' 'url' 'license' 'groups' 'depends' 'optdepends' 'provides' 'conflicts' 'replaces' 'backup' 'options' 'install' 'changelog') readonly -a build_options splitpkg_overrides known_hash_algos=('md5' 'sha1' 'sha224' 'sha256' 'sha384' 'sha512' 'whirlpool') # Options ASDEPS=0 BUILDFUNC=0 CHECKFUNC=0 CLEANBUILD=0 CLEANUP=0 RMBUILDDEPS=0 DEP_BIN=0 FORCE=0 GENINTEG=0 HOLDVER=0 IGNOREARCH=0 INFAKEROOT=0 INSTALL=0 LOGGING=0 NEEDED=0 NOARCHIVE=0 NOBUILD=0 NODEPS=0 NOEXTRACT=0 PKGFUNC=0 PKGVERFUNC=0 PREPAREFUNC=0 REPKG=0 REPRODUCIBLE=0 RMDEPS=0 SKIPCHECKSUMS=0 SKIPPGPCHECK=0 SIGNPKG='' SPLITPKG=0 SOURCEONLY=0 UPDPKGSUMS=0 VERIFYSOURCE=0 if [[ -n $SOURCE_DATE_EPOCH ]]; then REPRODUCIBLE=1 else SOURCE_DATE_EPOCH=$(date +%s) fi export SOURCE_DATE_EPOCH PACMAN_OPTS=() shopt -s extglob ### SUBROUTINES ### # Import libmakepkg for lib in "$LIBRARY"/*.sh; do source "$lib" done ## # Special exit call for traps, Don't print any error messages when inside, # the fakeroot call, the error message will be printed by the main call. ## trap_exit() { local signal=$1; shift if (( ! INFAKEROOT )); then echo error "$@" fi [[ -n $srclinks ]] && rm -rf "$srclinks" # unset the trap for this signal, and then call the default handler trap -- "$signal" kill "-$signal" "$$" } ## # Clean up function. Called automatically when the script exits. ## clean_up() { local EXIT_CODE=$? if (( INFAKEROOT )); then # Don't clean up when leaving fakeroot, we're not done yet. return 0 fi if (( (EXIT_CODE == E_OK || EXIT_CODE == E_INSTALL_FAILED) && CLEANUP )); then local pkg file # If it's a clean exit and -c/--clean has been passed... msg "$(gettext "Cleaning up...")" rm -rf "$pkgdirbase" "$srcdir" if [[ -n $pkgbase ]]; then local fullver=$(get_full_version) # Can't do this unless the BUILDSCRIPT has been sourced. if (( PKGVERFUNC )); then rm -f "${pkgbase}-${fullver}-${CARCH}-pkgver.log"* fi if (( PREPAREFUNC )); then rm -f "${pkgbase}-${fullver}-${CARCH}-prepare.log"* fi if (( BUILDFUNC )); then rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"* fi if (( CHECKFUNC )); then rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"* fi if (( PKGFUNC )); then rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"* elif (( SPLITPKG )); then for pkg in ${pkgname[@]}; do rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"* done fi # clean up dangling symlinks to packages for pkg in ${pkgname[@]}; do for file in ${pkg}-*-*-*{${PKGEXT},${SRCEXT}}; do if [[ -h $file && ! -e $file ]]; then rm -f "$file" fi done done fi fi remove_deps } enter_fakeroot() { msg "$(gettext "Entering %s environment...")" "fakeroot" fakeroot -- $0 -F "${ARGLIST[@]}" || exit $? } # Automatically update pkgver variable if a pkgver() function is provided # Re-sources the PKGBUILD afterwards to allow for other variables that use $pkgver update_pkgver() { newpkgver=$(run_function_safe pkgver) if ! check_pkgver "$newpkgver"; then error "$(gettext "pkgver() generated an invalid version: %s")" "$newpkgver" exit $E_PKGBUILD_ERROR fi if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then if ! /usr/bin/sed --follow-symlinks -i "s:^pkgver=[^ ]*:pkgver=$newpkgver:" "$BUILDFILE"; then error "$(gettext "Failed to update %s from %s to %s")" \ "pkgver" "$pkgver" "$newpkgver" exit $E_PKGBUILD_ERROR fi /usr/bin/sed --follow-symlinks -i "s:^pkgrel=[^ ]*:pkgrel=1:" "$BUILDFILE" source_safe "$BUILDFILE" local fullver=$(get_full_version) msg "$(gettext "Updated version: %s")" "$pkgbase $fullver" else warning "$(gettext "%s is not writeable -- pkgver will not be updated")" \ "$BUILDFILE" fi fi } # Print 'source not found' error message and exit makepkg missing_source_file() { error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")" plain "$(gettext "Aborting...")" exit $E_MISSING_FILE } run_pacman() { local cmd if [[ $1 != -@(T|Q)*([[:alpha:]]) ]]; then cmd=("$PACMAN_PATH" "${PACMAN_OPTS[@]}" "$@") else cmd=("$PACMAN_PATH" "$@") fi if [[ $1 != -@(T|Q)*([[:alpha:]]) ]]; then if [[ $PACMAN == "pacman" ]]; then if type -p sudo >/dev/null; then cmd=(sudo "${cmd[@]}") else cmd=(su root -c "$(printf '%q ' "${cmd[@]}")") fi fi fi "${cmd[@]}" } check_deps() { (( $# > 0 )) || return 0 local ret=0 local pmout pmout=$(run_pacman -T "$@") ret=$? if (( ret == 127 )); then #unresolved deps printf "%s\n" "$pmout" elif (( ret )); then error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout" return "$ret" fi } handle_deps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 (( $# == 0 )) && return $R_DEPS_SATISFIED deplist=("$@") if (( ! DEP_BIN )); then return $R_DEPS_MISSING fi if (( DEP_BIN )); then # install missing deps from binary packages (using pacman -S) msg "$(gettext "Installing missing dependencies...")" if ! run_pacman -S "${PACMAN_OPTS[@]}" "${deplist[@]}"; then error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN" for d in "${deplist[@]}"; do if run_pacman -Qq "${d}" >/dev/null 2>&1; then msg "$(gettext "Removing obsolete dependency %s...")" "${d}" run_pacman -Rs --noconfirm "${d}" fi done exit $E_INSTALL_DEPS_FAILED fi fi # we might need the new system environment # save our shell options and turn off extglob local shellopts=$(shopt -p extglob) shopt -u extglob source /etc/profile &>/dev/null eval "$shellopts" # umask might have been changed in /etc/profile # ensure that sane default is set again umask 0022 return $R_DEPS_SATISFIED } function info_missingdeps() { local response depsall=$(printf '%s ' ${deplist[@]}) msg "$(gettext "Missing ${DEPS_TYPE} dependencies:")" msg2 "$depsall" printf "\n" case ${DEPS_TYPE} in "buildtime") buildtime_depsall=${depsall} ;; "runtime") runtime_depsall=${depsall} ;; esac } function enforce_missingdeps() { local R_DEPS_ENFORCED=0 local R_DEPS_MISSING=1 msg "$(gettext "Enforce compilation without missing dependencies? [Y/n]")" read depsresponse if [[ $(echo $depsresponse) =~ ^([yY][eE][sS]|[yY])$ ]]; then NODEPS=1 return $R_DEPS_ENFORCED else return $R_DEPS_MISSING fi } function ask_missingdeps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 local list=(${1}) local PACMAN_OPTS=('--noconfirm' '--asdeps') if [[ -z $depsresponse ]]; then msg "$(gettext "Do you want to install missing dependencies? [Y/n]")" read depsresponse fi if [[ $(echo $depsresponse) =~ ^([yY][eE][sS]|[yY])$ ]]; then DEP_BIN=1 handle_deps ${list[@]} else enforce_missingdeps fi if [[ $? -ne 0 ]]; then msg "$(gettext "Missing dependencies:")" info_missingdeps msg "$(gettext "These packages couldn't be provided by $PACMAN")" return $R_DEPS_MISSING else msg "$(gettext "Dependencies installed.")" return $R_DEPS_SATISFIED fi } resolve_deps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 local PACMAN_OPTS=('--asdeps') DEPS_TYPE=${1} shift # deplist cannot be declared like this: local deplist=$(foo) # Otherwise, the return value will depend on the assignment. local deplist deplist=($(check_deps "$@")) || exit $E_INSTALL_DEPS_FAILED [[ -z $deplist ]] && return $R_DEPS_SATISFIED if handle_deps "${deplist[@]}"; then # check deps again to make sure they were resolved deplist=$(check_deps "$@") || exit $E_INSTALL_DEPS_FAILED [[ -z $deplist ]] && return $R_DEPS_SATISFIED fi info_missingdeps } remove_deps() { (( ! RMDEPS )) && return 0 # check for packages removed during dependency install (e.g. due to conflicts) # removing all installed packages is risky in this case if [[ -n $(grep -xvFf <(printf '%s\n' "${current_pkglist[@]}") \ <(printf '%s\n' "${original_pkglist[@]}")) ]]; then warning "$(gettext "Failed to remove installed dependencies.")" return $E_REMOVE_DEPS_FAILED fi local deplist deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \ <(printf "%s\n" "${current_pkglist[@]}"))) if [[ -z $deplist ]]; then return 0 fi msg "Removing installed dependencies..." # exit cleanly on failure to remove deps as package has been built successfully if ! run_pacman -Rn ${deplist[@]}; then warning "$(gettext "Failed to remove installed dependencies.")" return $E_REMOVE_DEPS_FAILED fi } error_function() { if [[ -p $logpipe ]]; then rm "$logpipe" fi # first exit all subshells, then print the error if (( ! BASH_SUBSHELL )); then error "$(gettext "A failure occurred in %s().")" "$1" plain "$(gettext "Aborting...")" fi exit $E_USER_FUNCTION_FAILED } source_safe() { shopt -u extglob if ! source "$@"; then error "$(gettext "Failed to source %s")" "$1" exit $E_MISSING_FILE fi shopt -s extglob } merge_arch_attrs() { local attr supported_attrs=( provides conflicts depends replaces optdepends makedepends checkdepends) for attr in "${supported_attrs[@]}"; do eval "$attr+=(\"\${${attr}_$CARCH[@]}\")" done # ensure that calling this function is idempotent. unset -v "${supported_attrs[@]/%/_$CARCH}" } source_buildfile() { source_safe "$@" } prepare_buildenv() { # clear user-specified buildflags if requested if check_option "buildflags" "n"; then unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS fi if check_option "debug" "y"; then DEBUG_CFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}" DEBUG_CXXFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}" CFLAGS+=" $DEBUG_CFLAGS" CXXFLAGS+=" $DEBUG_CXXFLAGS" fi # clear user-specified makeflags if requested if check_option "makeflags" "n"; then unset MAKEFLAGS fi # ensure all necessary build variables are exported export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST local ccache=0 # use ccache if it is requested (check buildenv and PKGBUILD opts) if check_buildoption "ccache" "y" && [[ -d /usr/lib/ccache/bin ]]; then export PATH="/usr/lib/ccache/bin:$PATH" ccache=1 fi # use distcc if it is requested (check buildenv and PKGBUILD opts) if check_buildoption "distcc" "y"; then if (( ccache )); then export CCACHE_PREFIX="${CCACHE_PREFIX:+$CCACHE_PREFIX }distcc" export CCACHE_BASEDIR="$srcdir" elif [[ -d /usr/lib/distcc/bin ]]; then export PATH="/usr/lib/distcc/bin:$PATH" fi export DISTCC_HOSTS fi } run_function_safe() { local restoretrap restoreset restoreshopt # we don't set any special shopts of our own, but we don't want the user to # muck with our environment. restoreshopt=$(shopt -p) restoreset=$(shopt -o -p) shopt -o -s errexit errtrace restoretrap=$(trap -p ERR) trap "error_function '$1'" ERR run_function "$1" trap - ERR eval "$restoretrap" eval "$restoreset" eval "$restoreshopt" } run_function() { if [[ -z $1 ]]; then return 1 fi local pkgfunc="$1" msg "$(gettext "Starting %s()...")" "$pkgfunc" cd_safe "$srcdir" # save our shell options so pkgfunc() can't override what we need local shellopts=$(shopt -p) local ret=0 if (( LOGGING )); then local fullver=$(get_full_version) local BUILDLOG="$LOGDEST/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log" if [[ -f $BUILDLOG ]]; then local i=1 while true; do if [[ -f $BUILDLOG.$i ]]; then i=$(($i +1)) else break fi done mv "$BUILDLOG" "$BUILDLOG.$i" fi # ensure overridden package variables survive tee with split packages logpipe=$(mktemp -u "$LOGDEST/logpipe.XXXXXXXX") mkfifo "$logpipe" tee "$BUILDLOG" < "$logpipe" & local teepid=$! $pkgfunc &>"$logpipe" wait $teepid rm "$logpipe" else "$pkgfunc" fi # reset our shell options eval "$shellopts" } run_prepare() { run_function_safe "prepare" } run_build() { run_function_safe "build" } run_check() { run_function_safe "check" } run_package() { local pkgfunc if [[ -z $1 ]]; then pkgfunc="package" else pkgfunc="package_$1" fi run_function_safe "$pkgfunc" } find_libdepends() { local d sodepends; sodepends=0; for d in "${depends[@]}"; do if [[ $d = *.so ]]; then sodepends=1; break; fi done if (( sodepends == 0 )); then (( ${#depends[@]} )) && printf '%s\n' "${depends[@]}" return 0 fi local libdeps filename soarch sofile soname soversion; declare -A libdeps; while read -r filename; do # get architecture of the file; if soarch is empty it's not an ELF binary soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') [[ -n "$soarch" ]] || continue # process all libraries needed by the binary for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p') do # extract the library name: libfoo.so soname="${sofile%.so?(+(.+([0-9])))}".so # extract the major version: 1 soversion="${sofile##*\.so\.}" if [[ ${libdeps[$soname]} ]]; then if [[ ${libdeps[$soname]} != *${soversion}-${soarch}* ]]; then libdeps[$soname]+=" ${soversion}-${soarch}" fi else libdeps[$soname]="${soversion}-${soarch}" fi done done < <(find "$pkgdir" -type f -perm -u+x) local libdepends v for d in "${depends[@]}"; do case "$d" in *.so) if [[ ${libdeps[$d]} ]]; then for v in ${libdeps[$d]}; do libdepends+=("$d=$v") done else warning "$(gettext "Library listed in %s is not required by any files: %s")" "'depends'" "$d" libdepends+=("$d") fi ;; *) libdepends+=("$d") ;; esac done (( ${#libdepends[@]} )) && printf '%s\n' "${libdepends[@]}" } find_libprovides() { local p libprovides missing for p in "${provides[@]}"; do missing=0 case "$p" in *.so) mapfile -t filename < <(find "$pkgdir" -type f -name $p\*) if [[ $filename ]]; then # packages may provide multiple versions of the same library for fn in "${filename[@]}"; do # check if we really have a shared object if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1) local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p') if [[ -z "$sofile" ]]; then warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p" libprovides+=("$p") continue fi # get the library architecture (32 or 64 bit) local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') # extract the library major version local soversion="${sofile##*\.so\.}" libprovides+=("${p}=${soversion}-${soarch}") else warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p" libprovides+=("$p") fi done else libprovides+=("$p") missing=1 fi ;; *) libprovides+=("$p") ;; esac if (( missing )); then warning "$(gettext "Cannot find library listed in %s: %s")" "'provides'" "$p" fi done (( ${#libprovides[@]} )) && printf '%s\n' "${libprovides[@]}" } write_kv_pair() { local key="$1" shift for val in "$@"; do if [[ $val = *$'\n'* ]]; then error "$(gettext "Invalid value for %s: %s")" "$key" "$val" exit $E_PKGBUILD_ERROR fi printf "%s = %s\n" "$key" "$val" done } write_pkginfo() { local size="$(/usr/bin/du -sk --apparent-size)" size="$(( ${size%%[^0-9]*} * 1024 ))" merge_arch_attrs msg2 "$(gettext "Generating %s file...")" ".PKGINFO" printf "# Generated by makepkg %s\n" "$makepkg_version" printf "# using %s\n" "$(fakeroot -v)" write_kv_pair "pkgname" "$pkgname" write_kv_pair "pkgbase" "$pkgbase" local fullver=$(get_full_version) write_kv_pair "pkgver" "$fullver" # TODO: all fields should have this treatment local spd="${pkgdesc//+([[:space:]])/ }" spd=("${spd[@]#[[:space:]]}") spd=("${spd[@]%[[:space:]]}") write_kv_pair "pkgdesc" "$spd" write_kv_pair "url" "$url" write_kv_pair "builddate" "$SOURCE_DATE_EPOCH" write_kv_pair "packager" "$PACKAGER" write_kv_pair "size" "$size" write_kv_pair "arch" "$pkgarch" mapfile -t provides < <(find_libprovides) mapfile -t depends < <(find_libdepends) write_kv_pair "license" "${license[@]}" write_kv_pair "replaces" "${replaces[@]}" write_kv_pair "group" "${groups[@]}" write_kv_pair "conflict" "${conflicts[@]}" write_kv_pair "provides" "${provides[@]}" write_kv_pair "backup" "${backup[@]}" write_kv_pair "depend" "${depends[@]}" write_kv_pair "optdepend" "${optdepends[@]//+([[:space:]])/ }" write_kv_pair "makedepend" "${makedepends[@]}" write_kv_pair "checkdepend" "${checkdepends[@]}" } write_buildinfo() { msg2 "$(gettext "Generating %s file...")" ".BUILDINFO" write_kv_pair "format" "1" write_kv_pair "pkgname" "$pkgname" write_kv_pair "pkgbase" "$pkgbase" local fullver=$(get_full_version) write_kv_pair "pkgver" "$fullver" write_kv_pair "pkgarch" "$pkgarch" local sum="$(sha256sum "${BUILDFILE}")" sum=${sum%% *} write_kv_pair "pkgbuild_sha256sum" $sum write_kv_pair "packager" "${PACKAGER}" write_kv_pair "builddate" "${SOURCE_DATE_EPOCH}" write_kv_pair "builddir" "${BUILDDIR}" write_kv_pair "buildenv" "${BUILDENV[@]}" write_kv_pair "options" "${OPTIONS[@]}" local pkginfos_parsed=($(LC_ALL=C run_pacman -Qi | awk -F': ' '\ /^Name .*/ {printf "%s", $2} \ /^Version .*/ {printf "-%s", $2} \ /^Architecture .*/ {print "-"$2} \ ')) write_kv_pair "installed" "${pkginfos_parsed[@]}" } #write_kv_pair() { # local key="$1" # shift # # for val in "$@"; do # if [[ $val = *$'\n'* ]]; then # error "$(gettext "Invalid value for %s: %s")" "$key" "$val" # exit $E_PKGBUILD_ERROR # fi # done # printf "%s = %s\n" "$key" "$@" #} # #write_pkginfo() { # local size="$(/usr/bin/du -sk --apparent-size)" # size="$(( ${size%%[^0-9]*} * 1024 ))" # # merge_arch_attrs # # msg2 "$(gettext "Generating %s file...")" ".PKGINFO" # printf "# Generated by makepkg %s\n" "$makepkg_version" # printf "# using %s\n" "$(fakeroot -v)" # # write_kv_pair "pkgname" "$pkgname" # write_kv_pair "pkgbase" "$pkgbase" # # local fullver=$(get_full_version) # write_kv_pair "pkgver" "$fullver" # # # TODO: all fields should have this treatment # local spd="${pkgdesc//+([[:space:]])/ }" # spd=("${spd[@]#[[:space:]]}") # spd=("${spd[@]%[[:space:]]}") # # write_kv_pair "pkgdesc" "$spd" # write_kv_pair "url" "$url" # write_kv_pair "builddate" "$SOURCE_DATE_EPOCH" # write_kv_pair "packager" "$PACKAGER" # write_kv_pair "size" "$size" # write_kv_pair "arch" "$pkgarch" # # mapfile -t provides < <(find_libprovides) # mapfile -t depends < <(find_libdepends) # # write_kv_pair "license" "${license[@]}" # write_kv_pair "replaces" "${replaces[@]}" # write_kv_pair "group" "${groups[@]}" # write_kv_pair "conflict" "${conflicts[@]}" # write_kv_pair "provides" "${provides[@]}" # write_kv_pair "backup" "${backup[@]}" # write_kv_pair "depend" "${depends[@]}" # write_kv_pair "optdepend" "${optdepends[@]//+([[:space:]])/ }" # write_kv_pair "makedepend" "${makedepends[@]}" # write_kv_pair "checkdepend" "${checkdepends[@]}" #} # #write_buildinfo() { # msg2 "$(gettext "Generating %s file...")" ".BUILDINFO" # # write_kv_pair "format" "1" # # write_kv_pair "pkgname" "$pkgname" # write_kv_pair "pkgbase" "$pkgbase" # # local fullver=$(get_full_version) # write_kv_pair "pkgver" "$fullver" # # write_kv_pair "pkgarch" "$pkgarch" # # local sum="$(sha256sum "${BUILDFILE}")" # sum=${sum%% *} # write_kv_pair "pkgbuild_sha256sum" $sum # # write_kv_pair "packager" "${PACKAGER}" # write_kv_pair "builddate" "${SOURCE_DATE_EPOCH}" # write_kv_pair "builddir" "${BUILDDIR}" # write_kv_pair "buildenv" "${BUILDENV[@]}" # write_kv_pair "options" "${OPTIONS[@]}" # # # Additional build time environment information # write_kv_pair "CPPFLAGS" "${CPPFLAGS}" # write_kv_pair "CFLAGS" "${CFLAGS}" # write_kv_pair "CXXFLAGS" "${CXXFLAGS}" # write_kv_pair "LDFLAGS" "${LDFLAGS}" # write_kv_pair "MAKEFLAGS" "${MAKEFLAGS}" # write_kv_pair "DEBUG_CFLAGS" "${DEBUG_CFLAGS}" # write_kv_pair "DEBUG_CXXFLAGS" "${DEBUG_CXXFLAGS}" # write_kv_pair "STRIP_BINARIES" "${STRIP_BINARIES}" # write_kv_pair "STRIP_SHARED" "${STRIP_SHARED}" # write_kv_pair "STRIP_STATIC" "${STRIP_STATIC}" # # local pkginfos_parsed=($(LC_ALL=C run_pacman -Qi | awk -F': ' '\ # /^Name .*/ {printf "%s", $2} \ # /^Version .*/ {printf "-%s", $2} \ # /^Architecture .*/ {print "-"$2} \ # ')) # # write_kv_pair "installed" "${pkginfos_parsed[@]}" #} # build a sorted NUL-separated list of the full contents of the current # directory suitable for passing to `bsdtar --files-from` # database files are placed at the beginning of the package regardless of # sorting list_package_files() { (find . -path './.*' \! -name '.'; find . \! -path './.*' \! -name '.' | LC_ALL=C sort) | sed -e 's|^\./||' | tr '\n' '\0' } create_package() { (( NOARCHIVE )) && return 0 if [[ ! -d $pkgdir ]]; then error "$(gettext "Missing %s directory.")" "\$pkgdir/" plain "$(gettext "Aborting...")" exit $E_MISSING_PKGDIR fi cd_safe "$pkgdir" msg "$(gettext "Creating package \"%s\"...")" "$pkgname" pkgarch=$(get_pkg_arch) write_pkginfo > .PKGINFO write_buildinfo > .BUILDINFO # check for changelog/install files for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do IFS='/' read -r orig dest < <(printf '%s\n' "$i") if [[ -n ${!orig} ]]; then msg2 "$(gettext "Adding %s file...")" "$orig" if ! cp "$startdir/${!orig}" "$dest"; then error "$(gettext "Failed to add %s file to package.")" "$orig" exit $E_MISSING_FILE fi chmod 644 "$dest" fi done # tar it up local fullver=$(get_full_version) local pkg_file="$PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT}" local ret=0 [[ -f $pkg_file ]] && rm -f "$pkg_file" [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig" # ensure all elements of the package have the same mtime find . -exec touch -h -d @$SOURCE_DATE_EPOCH {} + msg2 "$(gettext "Generating .MTREE file...")" list_package_files | LANG=C bsdtar -cnf - --format=mtree \ --options='!all,use-set,type,uid,gid,mode,time,size,md5,sha256,link' \ --null --files-from - --exclude .MTREE | gzip -c -f -n > .MTREE touch -d @$SOURCE_DATE_EPOCH .MTREE msg2 "$(gettext "Compressing package...")" # TODO: Maybe this can be set globally for robustness shopt -s -o pipefail list_package_files | LANG=C bsdtar -cnf - --null --files-from - | compress_as "$PKGEXT" > "${pkg_file}" || ret=$? shopt -u -o pipefail if (( ret )); then error "$(gettext "Failed to create package file.")" exit $E_PACKAGE_FAILED fi } create_debug_package() { # check if a debug package was requested if ! check_option "debug" "y" || ! check_option "strip" "y"; then return 0 fi pkgdir="$pkgdirbase/$pkgbase-debug" # check if we have any debug symbols to package if dir_is_empty "$pkgdir/usr/lib/debug"; then return 0 fi unset groups depends optdepends provides conflicts replaces backup install changelog local pkg for pkg in ${pkgname[@]}; do if [[ $pkg != $pkgbase ]]; then provides+=("$pkg-debug") fi done pkgdesc="Detached debugging symbols for $pkgname" pkgname=$pkgbase-debug create_package } create_srcpackage() { local ret=0 msg "$(gettext "Creating source package...")" local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)" mkdir "${srclinks}"/${pkgbase} msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT" ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}" msg2 "$(gettext "Generating %s file...")" .SRCINFO write_srcinfo > "$srclinks/$pkgbase"/.SRCINFO local file all_sources get_all_sources 'all_sources' for file in "${all_sources[@]}"; do if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then local absfile absfile=$(get_filepath "$file") || missing_source_file "$file" msg2 "$(gettext "Adding %s...")" "${absfile##*/}" ln -s "$absfile" "$srclinks/$pkgbase" fi done local i for i in 'changelog' 'install'; do local file files [[ ${!i} ]] && files+=("${!i}") for name in "${pkgname[@]}"; do if extract_function_variable "package_$name" "$i" 0 file; then files+=("$file") fi done for file in "${files[@]}"; do if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}" ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/" fi done done local fullver=$(get_full_version) local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}" # tar it up msg2 "$(gettext "Compressing source package...")" cd_safe "${srclinks}" # TODO: Maybe this can be set globally for robustness shopt -s -o pipefail LANG=C bsdtar -cLf - ${pkgbase} | compress_as "$SRCEXT" > "${pkg_file}" || ret=$? shopt -u -o pipefail if (( ret )); then error "$(gettext "Failed to create source package file.")" exit $E_PACKAGE_FAILED fi cd_safe "${startdir}" rm -rf "${srclinks}" } install_package() { (( ! INSTALL )) && return 0 if (( ! SPLITPKG )); then msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U" else msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U" fi local fullver pkgarch pkg pkglist (( ASDEPS )) && pkglist+=('--asdeps') (( NEEDED )) && pkglist+=('--needed') for pkg in ${pkgname[@]}; do fullver=$(get_full_version) pkgarch=$(get_pkg_arch $pkg) pkglist+=("$PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT}") if [[ -f "$PKGDEST/${pkg}-debug-${fullver}-${pkgarch}${PKGEXT}" ]]; then pkglist+=("$PKGDEST/${pkg}-debug-${fullver}-${pkgarch}${PKGEXT}") fi done if ! run_pacman -U "${pkglist[@]}"; then warning "$(gettext "Failed to install built package(s).")" return $E_INSTALL_FAILED fi } get_vcsclient() { local proto=${1%%+*} local i for i in "${VCSCLIENTS[@]}"; do local handler="${i%%::*}" if [[ $proto = "$handler" ]]; then local client="${i##*::}" break fi done # if we didn't find an client, return an error if [[ -z $client ]]; then error "$(gettext "Unknown download protocol: %s")" "$proto" plain "$(gettext "Aborting...")" exit $E_CONFIG_ERROR fi printf "%s\n" "$client" } check_vcs_software() { local netfile all_sources all_deps deps ret=0 if (( SOURCEONLY == 1 )); then # we will not download VCS sources return $ret fi if [[ -z $PACMAN_PATH ]]; then warning "$(gettext "Cannot find the %s binary needed to check VCS source requirements.")" "$PACMAN" return $ret fi # we currently only use global depends/makedepends arrays for --syncdeps for attr in depends makedepends; do get_pkgbuild_attribute "$pkg" "$attr" 1 'deps' all_deps+=("${deps[@]}") get_pkgbuild_attribute "$pkg" "${attr}_$CARCH" 1 'deps' all_deps+=("${deps[@]}") done get_all_sources_for_arch 'all_sources' for netfile in ${all_sources[@]}; do local proto=$(get_protocol "$netfile") case $proto in bzr*|git*|hg*|svn*) if ! type -p ${proto%%+*} > /dev/null; then local client client=$(get_vcsclient "$proto") || exit $? # ensure specified program is installed local uninstalled uninstalled=$(check_deps "$client") || exit $E_INSTALL_DEPS_FAILED # if not installed, check presence in depends or makedepends if [[ -n "$uninstalled" ]] && (( ! NODEPS || ( VERIFYSOURCE && !DEP_BIN ) )); then if ! in_array "$client" ${all_deps[@]}; then error "$(gettext "Cannot find the %s package needed to handle %s sources.")" \ "$client" "${proto%%+*}" ret=1 fi fi fi ;; *) # non VCS source ;; esac done return $ret } check_software() { # check for needed software local ret=0 # check for PACMAN if we need it if (( ! NODEPS || DEP_BIN || RMDEPS || INSTALL )); then if [[ -z $PACMAN_PATH ]]; then error "$(gettext "Cannot find the %s binary required for dependency operations.")" "$PACMAN" ret=1 fi fi # check for sudo if we will need it during makepkg execution if (( DEP_BIN || RMDEPS || INSTALL )); then if ! type -p sudo >/dev/null; then warning "$(gettext "Cannot find the %s binary. Will use %s to acquire root privileges.")" "sudo" "su" fi fi # fakeroot - correct package file permissions if check_buildenv "fakeroot" "y" && (( EUID > 0 )); then if ! type -p fakeroot >/dev/null; then error "$(gettext "Cannot find the %s binary.")" "fakeroot" ret=1 fi fi # gpg - package signing if [[ $SIGNPKG == 'y' ]] || { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; }; then if ! type -p gpg >/dev/null; then error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg" ret=1 fi fi # gpg - source verification if (( ! SKIPPGPCHECK )) && source_has_signatures; then if ! type -p gpg >/dev/null; then error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg" ret=1 fi fi # checksum operations if (( GENINTEG || ! SKIPCHECKSUMS )); then local integlist IFS=$'\n' read -rd '' -a integlist < <(get_integlist) local integ for integ in "${integlist[@]}"; do if ! type -p "${integ}sum" >/dev/null; then error "$(gettext "Cannot find the %s binary required for source file checksums operations.")" "${integ}sum" ret=1 fi done fi # distcc - compilation with distcc if check_buildoption "distcc" "y"; then if ! type -p distcc >/dev/null; then error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc" ret=1 fi fi # ccache - compilation with ccache if check_buildoption "ccache" "y"; then if ! type -p ccache >/dev/null; then error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache" ret=1 fi fi # strip - strip symbols from binaries/libraries if check_option "strip" "y"; then if ! type -p strip >/dev/null; then error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip" ret=1 fi fi # gzip - compressig man and info pages if check_option "zipman" "y"; then if ! type -p gzip >/dev/null; then error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip" ret=1 fi fi # tools to download vcs sources if ! check_vcs_software; then ret=1 fi return $ret } check_build_status() { if (( ! SPLITPKG )); then fullver=$(get_full_version) pkgarch=$(get_pkg_arch) if [[ -f $PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT} ]] \ && ! (( FORCE || SOURCEONLY || NOBUILD || NOARCHIVE)); then if (( INSTALL )); then warning "$(gettext "A package has already been built, installing existing package...")" install_package exit $? else error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f" exit $E_ALREADY_BUILT fi fi else allpkgbuilt=1 somepkgbuilt=0 for pkg in ${pkgname[@]}; do fullver=$(get_full_version) pkgarch=$(get_pkg_arch $pkg) if [[ -f $PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT} ]]; then somepkgbuilt=1 else allpkgbuilt=0 fi done if ! (( FORCE || SOURCEONLY || NOBUILD || NOARCHIVE)); then if (( allpkgbuilt )); then if (( INSTALL )); then warning "$(gettext "The package group has already been built, installing existing packages...")" install_package exit $? else error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f" exit $E_ALREADY_BUILT fi fi if (( somepkgbuilt && ! PKGVERFUNC )); then error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f" exit $E_ALREADY_BUILT fi fi unset allpkgbuilt somepkgbuilt fi } backup_package_variables() { local var for var in ${splitpkg_overrides[@]}; do local indirect="${var}_backup" eval "${indirect}=(\"\${$var[@]}\")" done } restore_package_variables() { local var for var in ${splitpkg_overrides[@]}; do local indirect="${var}_backup" if [[ -n ${!indirect} ]]; then eval "${var}=(\"\${$indirect[@]}\")" else unset ${var} fi done } run_split_packaging() { local pkgname_backup=("${pkgname[@]}") for pkgname in ${pkgname_backup[@]}; do pkgdir="$pkgdirbase/$pkgname" mkdir "$pkgdir" backup_package_variables run_package $pkgname tidy_install lint_package || exit $E_PACKAGE_FAILED create_package restore_package_variables done pkgname=("${pkgname_backup[@]}") create_debug_package } function get_repository_files() { if [[ -n ${REPOPACKAGE} ]]; then getsource $REPOPACKAGE $BUILDSCRIPT if [[ $? -ne 0 ]]; then error "$(gettext "Couldn't get source files for $REPOPACKAGE")" exit 1 fi else error "$(gettext "Package name not given.")" exit 1 fi exit $E_OK } usage() { printf "makepkg (pacman) %s\n" "$makepkg_version" echo printf -- "$(gettext "Make packages compatible for use with pacman")\n" echo printf -- "$(gettext "Usage: %s [options]")\n" "$0" echo printf -- "$(gettext "Options:")\n" printf -- "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT" printf -- "$(gettext " -c, --clean Clean up work files after build")\n" printf -- "$(gettext " -C, --cleanbuild Remove %s dir before building the package")\n" "\$srcdir/" printf -- "$(gettext " -d, --nodeps Skip all dependency checks")\n" printf -- "$(gettext " -D, --rmbuilddeps Remove installed build time dependencies after a successful build")\n" printf -- "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "\$srcdir/" printf -- "$(gettext " -f, --force Overwrite existing package")\n" printf -- "$(gettext " -g, --geninteg Generate integrity checks for source files")\n" printf -- "$(gettext " -h, --help Show this help message and exit")\n" printf -- "$(gettext " -i, --install Install package after successful build")\n" printf -- "$(gettext " -L, --log Log package build process")\n" printf -- "$(gettext " -m, --nocolor Disable colorized output messages")\n" printf -- "$(gettext " -o, --nobuild Download and extract files only")\n" printf -- "$(gettext " -p Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" printf -- "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")\n" printf -- "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")\n" printf -- "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "${PACMAN}" printf -- "$(gettext " -S, --source Generate a source-only tarball without downloaded sources")\n" printf -- "$(gettext " -U, --updpkgsums Update integrity check sums for source files with updpkgsums")\n" printf -- "$(gettext " -V, --version Show version information and exit")\n" printf -- "$(gettext " --addgroup Add package to a user-defined pacman group")\n" printf -- "$(gettext " --allsource Generate a source-only tarball including downloaded sources")\n" printf -- "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT" printf -- "$(gettext " --config Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" printf -- "$(gettext " --getsource Get source files from Arch Linux repositories")\n" printf -- "$(gettext " --holdver Do not update VCS sources")\n" printf -- "$(gettext " --key Specify a key to use for %s signing instead of the default")\n" "gpg" printf -- "$(gettext " --noarchive Do not create package archive")\n" printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT" printf -- "$(gettext " --noprepare Do not run the %s function in the %s")\n" "prepare()" "$BUILDSCRIPT" printf -- "$(gettext " --nosign Do not create a signature for the package")\n" printf -- "$(gettext " --packagelist Only list package filepaths that would be produced")\n" printf -- "$(gettext " --printsrcinfo Print the generated SRCINFO and exit")\n" printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg" printf -- "$(gettext " --nochecksums Do not verify checksums of the source files")\n" printf -- "$(gettext " --nointeg Do not perform any verification checks on source files")\n" printf -- "$(gettext " --nocertcheck Do not verify source files with PGP signatures")\n" printf -- "$(gettext " --verifysource Download source files (if needed) and perform integrity checks")\n" echo printf -- "$(gettext "These options can be passed to %s:")\n" "${PACMAN}" echo printf -- "$(gettext " --asdeps Install packages as non-explicitly installed")\n" printf -- "$(gettext " --needed Do not reinstall the targets that are already up to date")\n" printf -- "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")\n" printf -- "$(gettext " --noprogressbar Do not show a progress bar when downloading files")\n" echo printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT" echo } version() { printf "makepkg (pacman) %s\n" "$makepkg_version" printf -- "$(gettext "\ Copyright (c) 2019 Pekka Helenius .\n\ Copyright (c) 2006-2018 Pacman Development Team .\n\ Copyright (C) 2002-2006 Judd Vinet .\n\n\ This is free software; see the source for copying conditions.\n\ There is NO WARRANTY, to the extent permitted by law.\n")" } # PROGRAM START # ensure we have a sane umask set umask 0022 # determine whether we have gettext; make it a no-op if we do not if ! type -p gettext >/dev/null; then gettext() { printf "%s\n" "$@" } fi ARGLIST=("$@") # Parse Command Line Options. OPT_SHORT="AcCdDefFghiLmop:rRsSUV" OPT_LONG=('allsource' 'addgroup:' 'check' 'clean' 'cleanbuild' 'rmbuilddeps' 'config:' 'force' 'geninteg' 'help' 'holdver' 'ignorearch' 'install' 'key:' 'log' 'noarchive' 'nobuild' 'nocolor' 'nocheck' 'nodeps' 'noextract' 'noprepare' 'nosign' 'packagelist' 'printsrcinfo' 'repackage' 'rmdeps' 'sign' 'nochecksums' 'nointeg' 'nocertcheck' 'source' 'syncdeps' 'updpkgsums' 'verifysource' 'version' 'getsource:') # Pacman Options OPT_LONG+=('asdeps' 'noconfirm' 'needed' 'noprogressbar') if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then exit $E_INVALID_OPTION; fi set -- "${OPTRET[@]}" unset OPT_SHORT OPT_LONG OPTRET while true; do case "$1" in # Pacman Options --asdeps) ASDEPS=1 ;; --needed) NEEDED=1 ;; --noconfirm) PACMAN_OPTS+=("--noconfirm") ;; --noprogressbar) PACMAN_OPTS+=("--noprogressbar") ;; # Makepkg Options --addgroup) shift; ADDGROUP=$1 ;; --allsource) SOURCEONLY=2 ;; -A|--ignorearch) IGNOREARCH=1 ;; -c|--clean) CLEANUP=1 ;; -C|--cleanbuild) CLEANBUILD=1 ;; --check) RUN_CHECK='y' ;; --config) shift; MAKEPKG_CONF=$1 ;; -d|--nodeps) NODEPS=1 ;; -D|--rmbuilddeps) RMBUILDDEPS=1 ;; -e|--noextract) NOEXTRACT=1 ;; -f|--force) FORCE=1 ;; -F) INFAKEROOT=1 ;; # generating integrity checks does not depend on architecture -g|--geninteg) GENINTEG=1 IGNOREARCH=1 ;; --getsource) shift; REPOPACKAGE=$1 ;; --holdver) HOLDVER=1 ;; -i|--install) INSTALL=1 ;; --key) shift; GPGKEY=$1 ;; -L|--log) LOGGING=1 ;; -m|--nocolor) USE_COLOR='n'; PACMAN_OPTS+=("--color" "never") ;; --noarchive) NOARCHIVE=1 ;; --nocheck) RUN_CHECK='n' ;; --noprepare) RUN_PREPARE='n' ;; --nosign) SIGNPKG='n' ;; -o|--nobuild) NOBUILD=1; NODEPS=1; SKIPPGPCHECK=1; SKIPPGPCHECK=1; SKIPCHECKSUMS=1 ;; -p) shift; BUILDFILE=$1 ;; --packagelist) PACKAGELIST=1 IGNOREARCH=1 ;; --printsrcinfo) PRINTSRCINFO=1 IGNOREARCH=1 ;; -r|--rmdeps) RMDEPS=1 ;; -R|--repackage) REPKG=1 ;; --sign) SIGNPKG='y' ;; --nochecksums) SKIPCHECKSUMS=1 ;; --nointeg) SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;; --nocertcheck) SKIPPGPCHECK=1 ;; -s|--syncdeps) DEP_BIN=1 ;; -S|--source) SOURCEONLY=1 ;; -U|--updpkgsums) UPDPKGSUMS=1; ;; --verifysource) VERIFYSOURCE=1 ;; -h|--help) usage; exit $E_OK ;; -V|--version) version; exit $E_OK ;; --) shift; break ;; esac shift done # attempt to consume any extra argv as environment variables. this supports # overriding (e.g. CC=clang) as well as overriding (e.g. CFLAGS+=' -g'). extra_environment=() while [[ $1 ]]; do if [[ $1 = [_[:alpha:]]*([[:alnum:]_])?(+)=* ]]; then extra_environment+=("$1") fi shift done # TODO improve left-over dependency handling here # setup signal traps trap 'clean_up' 0 for signal in TERM HUP QUIT; do trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal" done trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR # preserve environment variables to override makepkg.conf restore_envvars=$(declare -p PKGDEST SRCDEST SRCPKGDEST LOGDEST BUILDDIR PKGEXT SRCEXT GPGKEY PACKAGER CARCH 2>/dev/null || true) # default config is makepkg.conf MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} # Source the config file; fail if it is not found if [[ -r $MAKEPKG_CONF ]]; then source_safe "$MAKEPKG_CONF" else error "$(gettext "%s not found.")" "$MAKEPKG_CONF" plain "$(gettext "Aborting...")" exit $E_CONFIG_ERROR fi # Source user-specific makepkg.conf overrides, but only if no override config # file was specified XDG_PACMAN_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/pacman" if [[ "$MAKEPKG_CONF" = "$confdir/makepkg.conf" ]]; then if [[ -r "$XDG_PACMAN_DIR/makepkg.conf" ]]; then source_safe "$XDG_PACMAN_DIR/makepkg.conf" elif [[ -r "$HOME/.makepkg.conf" ]]; then source_safe "$HOME/.makepkg.conf" fi fi eval "$restore_envvars" # override settings from extra variables on commandline, if any if (( ${#extra_environment[*]} )); then export "${extra_environment[@]}" fi # canonicalize paths and provide defaults if anything is still undefined for var in PKGDEST SRCDEST SRCPKGDEST LOGDEST BUILDDIR; do printf -v "$var" "$(canonicalize_path "${!var:-$startdir}")" done unset var PACKAGER=${PACKAGER:-"Unknown Packager"} # set pacman command if not already defined PACMAN_HELPER="pacaur" PACMAN=${PACMAN:-${PACMAN_HELPER}} # save full path to command as PATH may change when sourcing /etc/profile PACMAN_PATH=$(type -P $PACMAN) # check if messages are to be printed using color if [[ -t 2 && $USE_COLOR != "n" ]] && check_buildenv "color" "y"; then colorize else unset ALL_OFF BOLD BLUE GREEN RED YELLOW fi # check makepkg.conf for some basic requirements lint_config || exit $E_CONFIG_ERROR # check that all settings directories are user-writable if ! ensure_writable_dir "BUILDDIR" "$BUILDDIR"; then plain "$(gettext "Aborting...")" exit $E_FS_PERMISSIONS fi if (( ! (NOBUILD || GENINTEG) )) && ! ensure_writable_dir "PKGDEST" "$PKGDEST"; then plain "$(gettext "Aborting...")" exit $E_FS_PERMISSIONS fi if ! ensure_writable_dir "SRCDEST" "$SRCDEST" ; then plain "$(gettext "Aborting...")" exit $E_FS_PERMISSIONS fi if (( SOURCEONLY )); then if ! ensure_writable_dir "SRCPKGDEST" "$SRCPKGDEST"; then plain "$(gettext "Aborting...")" exit $E_FS_PERMISSIONS fi # If we're only making a source tarball, then we need to ignore architecture- # dependent behavior. IGNOREARCH=1 fi if (( LOGGING )) && ! ensure_writable_dir "LOGDEST" "$LOGDEST"; then plain "$(gettext "Aborting...")" exit $E_FS_PERMISSIONS fi if (( ! INFAKEROOT )); then if (( EUID == 0 )); then error "$(gettext "Running %s as root is not allowed as it can cause permanent,\n\ catastrophic damage to your system.")" "makepkg" exit $E_ROOT fi else if [[ -z $FAKEROOTKEY ]]; then error "$(gettext "Do not use the %s option. This option is only for internal use by %s.")" "'-F'" "makepkg" exit $E_INVALID_OPTION fi fi unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides unset md5sums replaces depends conflicts backup source install changelog build unset sha{1,224,256,384,512}sums makedepends optdepends options noextract validpgpkeys unset "${!makedepends_@}" "${!depends_@}" "${!source_@}" "${!checkdepends_@}" unset "${!optdepends_@}" "${!conflicts_@}" "${!provides_@}" "${!replaces_@}" unset "${!md5sums_@}" "${!sha1sums_@}" "${!sha224sums_@}" "${!sha256sums_@}" unset "${!sha384sums_@}" "${!sha512sums_@}" [[ -n ${REPOPACKAGE} ]] && get_repository_files BUILDFILE=${BUILDFILE:-$BUILDSCRIPT} if [[ ! -f $BUILDFILE ]]; then error "$(gettext "%s does not exist.")" "$BUILDFILE" exit $E_USER_FUNCTION_FAILED else if [[ $(<"$BUILDFILE") = *$'\r'* ]]; then error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF" exit $E_PKGBUILD_ERROR fi if [[ ! $BUILDFILE -ef $PWD/${BUILDFILE##*/} ]]; then error "$(gettext "%s must be in the current working directory.")" "$BUILDFILE" exit $E_PKGBUILD_ERROR fi if [[ ${BUILDFILE:0:1} != "/" ]]; then BUILDFILE="$startdir/$BUILDFILE" fi source_buildfile "$BUILDFILE" fi if [[ -v ADDGROUP ]]; then groups=(${groups[@]//$ADDGROUP}) groups+=($ADDGROUP) sed -i "s/^groups=.*//" "$BUILDFILE" printf 'groups=(' >> "$BUILDFILE" printf " '%s' " "${groups[@]}" >> "$BUILDFILE" printf ")" >> "$BUILDFILE" msg "$(gettext "Package added into group %s in %s")" "'$ADDGROUP'" "$BUILDSCRIPT" fi pkgbase=${pkgbase:-${pkgname[0]}} # check the PKGBUILD for some basic requirements lint_pkgbuild || exit $E_PKGBUILD_ERROR if (( !SOURCEONLY && !PRINTSRCINFO )); then merge_arch_attrs fi basever=$(get_full_version) if [[ $BUILDDIR -ef "$startdir" ]]; then srcdir="$BUILDDIR/src" pkgdirbase="$BUILDDIR/pkg" else srcdir="$BUILDDIR/$pkgbase/src" pkgdirbase="$BUILDDIR/$pkgbase/pkg" fi # set pkgdir to something "sensible" for (not recommended) use during build() pkgdir="$pkgdirbase/$pkgbase" # TODO fix incorrect duplicate functionality if (( GENINTEG )); then mkdir -p "$srcdir" chmod a-s "$srcdir" cd_safe "$srcdir" download_sources novcs allarch generate_checksums msg "$(gettext "Update your $BUILDSCRIPT")" exit $E_OK fi if have_function pkgver; then PKGVERFUNC=1 fi # check we have the software required to process the PKGBUILD check_software || exit $E_MISSING_MAKEPKG_DEPS if (( ${#pkgname[@]} > 1 )); then SPLITPKG=1 fi # test for available PKGBUILD functions if have_function prepare; then # "Hide" prepare() function if not going to be run if [[ $RUN_PREPARE != "n" ]]; then PREPAREFUNC=1 fi fi if have_function build; then BUILDFUNC=1 fi if have_function check; then # "Hide" check() function if not going to be run if [[ $RUN_CHECK = 'y' ]] || { ! check_buildenv "check" "n" && [[ $RUN_CHECK != "n" ]]; }; then CHECKFUNC=1 fi fi if have_function package; then PKGFUNC=1 elif [[ $SPLITPKG -eq 0 ]] && have_function package_${pkgname}; then SPLITPKG=1 fi # check if gpg signature is to be created and if signing key is valid if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then SIGNPKG='y' if ! gpg --list-key ${GPGKEY} &>/dev/null; then if [[ ! -z $GPGKEY ]]; then error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}" else error "$(gettext "There is no key in your keyring.")" fi exit $E_PRETTY_BAD_PRIVACY fi fi if (( PACKAGELIST )); then print_all_package_names exit $E_OK fi if (( PRINTSRCINFO )); then write_srcinfo_content exit $E_OK fi if (( ! PKGVERFUNC )); then check_build_status fi # Run the bare minimum in fakeroot if (( INFAKEROOT )); then if (( SOURCEONLY )); then create_srcpackage msg "$(gettext "Leaving %s environment.")" "fakeroot" exit $E_OK fi prepare_buildenv chmod 755 "$pkgdirbase" if (( ! SPLITPKG )); then pkgdir="$pkgdirbase/$pkgname" mkdir "$pkgdir" if (( PKGFUNC )); then run_package fi tidy_install lint_package || exit $E_PACKAGE_FAILED create_package create_debug_package else run_split_packaging fi msg "$(gettext "Leaving %s environment.")" "fakeroot" exit $E_OK fi msg "$(gettext "Making package: %s")" "$pkgbase $basever ($(date +%c))" # if we are creating a source-only package, go no further if (( SOURCEONLY )); then if [[ -f $SRCPKGDEST/${pkgbase}-${basever}${SRCEXT} ]] \ && (( ! FORCE )); then error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f" exit $E_ALREADY_BUILT fi # Get back to our src directory so we can begin with sources. mkdir -p "$srcdir" chmod a-s "$srcdir" cd_safe "$srcdir" if (( SOURCEONLY == 2 )); then download_sources allarch elif ( (( ! SKIPCHECKSUMS )) || \ ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ); then download_sources allarch novcs fi check_source_integrity all cd_safe "$startdir" enter_fakeroot if [[ $SIGNPKG = 'y' ]]; then msg "$(gettext "Signing package...")" create_signature "$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}" fi msg "$(gettext "Source package created: %s")" "$pkgbase ($(date +%c))" exit $E_OK fi # get back to our src directory so we can begin with sources mkdir -p "$srcdir" chmod a-s "$srcdir" cd_safe "$srcdir" if (( !REPKG )); then if (( NOEXTRACT && ! VERIFYSOURCE )); then warning "$(gettext "Using existing %s tree")" "\$srcdir/" else download_sources if (( UPDPKGSUMS )); then if type -p updpkgsums >/dev/null; then updpkgsums "${startdir}/${BUILDSCRIPT}" exit else error "$(gettext "Missing updpkgsums executable. Couldn't update checksums.")" exit 1 fi fi check_source_integrity all (( VERIFYSOURCE )) && exit $E_OK if (( CLEANBUILD )); then msg "$(gettext "Removing existing %s directory...")" "\$srcdir/" rm -rf "$srcdir"/* fi extract_sources if (( PREPAREFUNC )); then run_prepare fi if (( REPRODUCIBLE )); then # We have activated reproducible builds, so unify source times before # building find "$srcdir" -exec touch -h -d @$SOURCE_DATE_EPOCH {} + fi fi if (( PKGVERFUNC )); then update_pkgver basever=$(get_full_version) check_build_status fi fi if (( NODEPS || ( VERIFYSOURCE && !DEP_BIN ) )); then if (( NODEPS )); then warning "$(gettext "Skipping dependency checks.")" fi else if (( RMDEPS && ! INSTALL )); then original_pkglist=($(run_pacman -Qq)) # required by remove_dep fi deperr=0 msg "$(gettext "Checking runtime dependencies...")" resolve_deps runtime "${depends[@]}" || deperr=1 if (( RMDEPS && INSTALL )); then original_pkglist=($(run_pacman -Qq)) # required by remove_dep fi msg "$(gettext "Checking buildtime dependencies...")" if (( CHECKFUNC )); then resolve_deps buildtime "${makedepends[@]}" "${checkdepends[@]}" || deperr=1 else resolve_deps buildtime "${makedepends[@]}" || deperr=1 fi [[ -n $runtime_depsall ]] && ask_missingdeps $runtime_depsall [[ -n $buildtime_depsall ]] && ask_missingdeps $buildtime_depsall if (( RMDEPS )); then current_pkglist=($(run_pacman -Qq)) # required by remove_deps fi if (( deperr )); then error "$(gettext "Could not resolve all dependencies.")" exit $E_INSTALL_DEPS_FAILED fi fi if (( NOBUILD )); then msg "$(gettext "Sources are ready.")" exit $E_OK else # clean existing pkg directory if [[ -d $pkgdirbase ]]; then msg "$(gettext "Removing existing %s directory...")" "\$pkgdir/" rm -rf "$pkgdirbase" fi mkdir -p "$pkgdirbase" chmod a-srw "$pkgdirbase" cd_safe "$startdir" prepare_buildenv if (( ! REPKG )); then (( BUILDFUNC )) && run_build (( CHECKFUNC )) && run_check cd_safe "$startdir" fi enter_fakeroot create_package_signatures fi if [[ ${runtime_depsall} ]]; then msg "$(gettext "Runtime dependencies installed in prior to compilation:")" msg2 "$runtime_depsall" fi if [[ ${buildtime_depsall} ]]; then msg "$(gettext "Buildtime dependencies installed in prior to compilation:")" msg2 "$buildtime_depsall" if [[ $RMDEPS == 0 ]];then if [[ $RMBUILDDEPS == 0 ]]; then msg "$(gettext "Do you want to remove the buildtime dependencies? [Y/n]")" read response else response=y fi if [[ $(echo $response) =~ ^([yY][eE][sS]|[yY])$ ]]; then msg "$(gettext "Removing installed buildtime dependencies...")" echo "${buildtime_depsall}" run_pacman -Rs ${buildtime_depsall} fi fi fi # if inhibiting archive creation, go no further if (( NOARCHIVE )); then msg "$(gettext "Package directory is ready.")" exit $E_OK fi msg "$(gettext "Finished making: %s")" "$pkgbase $basever ($(date +%c))" install_package && exit $E_OK || exit $E_INSTALL_FAILED