#!/bin/bash # pbuilder -- personal Debian package builder # Copyright (C) 2001,2002,2003,2005-2007 Junichi Uekawa # # 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, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # module to satisfy build dependencies; default flavor # The original pbuilder-satisfydepends code, which is now called 'classic' set -e export PBUILDER_PKGLIBDIR="${PBUILDER_PKGLIBDIR:-$PBUILDER_ROOT/usr/lib/pbuilder}" . "$PBUILDER_PKGLIBDIR"/pbuilder-satisfydepends-funcs # splits lines of deps (possibly with alternates) separated by commas into one # dep (possibly with alternates) per line; also changes all spaces to slashes # first as to iterate on deps with "for"; e.g. "foo, bar | baz", "foobar (>= # 2)" becomes "foo", "bar/|/baz", "foobar/(>=/2)" split_deps() { sed 's#, *#\n#g; s# #/#g' } # and build-conflicts # splits build-dep with alternates into one alternate per line; e.g. "foo|bar" # becomes "foo", "bar" split_alternates() { echo "$*" | sed 's/ *| */\n/g' } # filters package name out of a "/" escaped simple build-dep, possibly with # architecture or version specifier; e.g. "/foo/(>=/2)/[i386/amd64]" becomes # "foo" get_pkg_name() { echo "$*" | sed 's#^/*##; s#[[/(<].*##' } # filter operator and version of a "/" escaped versioned build-dep; e.g. # "foo/(>=/2)" becomes ">= 2" get_dep_op_and_ver() { echo "$*" | sed -n 's#/# #g; s/.*( *\(<<\|<=\|>=\|=\|<\|>>\|>\) *\([^ )]*\) *).*/\1 \2/p' } # call apt-get in chroot in simulate mode apt_sim() { $CHROOTEXEC /usr/bin/apt-get -s install "$@" } # Use this function to fulfill the dependency (almost) checkbuilddep_internal() { local ARCH=$($CHROOTEXEC dpkg-architecture -qDEB_HOST_ARCH) local INSTALLPKG local INSTALLPKGLIST local INSTALLPKGMULTI local CURRENTREALPKGNAME local SATISFIED local APTFLAG="-o APT::Install-Recommends=false" echo " -> Attempting to parse the build-deps " for INSTALLPKGMULTI in $(get_build_deps | split_deps); do echo " -> Considering build-dep $(echo "$INSTALLPKGMULTI" | tr "/" " ")" SATISFIED="no" for INSTALLPKG in $(split_alternates "$INSTALLPKGMULTI"); do CURRENTREALPKGNAME=$(get_pkg_name "$INSTALLPKG") if echo "$INSTALLPKG" | grep -q '\['; then if checkbuilddep_archdeps "$INSTALLPKG" "$ARCH"; then SATISFIED="yes" echo " -> This package is not for this architecture" continue fi fi if echo "$INSTALLPKG" | grep -q '<'; then if checkbuilddep_restrictiondeps "$INSTALLPKG" "$DEB_BUILD_PROFILES"; then SATISFIED="yes" echo " -> This package is not for the current build profiles" continue fi fi if echo "$INSTALLPKG" | grep -q '('; then #echo "Debug: $INSTALLPKG" if ! checkbuilddep_versiondeps "$CURRENTREALPKGNAME" $(get_dep_op_and_ver "$INSTALLPKG"); then echo " -> Does not satisfy version, not trying" continue fi fi echo " -> Trying $CURRENTREALPKGNAME" if apt_sim $APTFLAG $INSTALLPKGLIST $CURRENTREALPKGNAME >& /dev/null; then SATISFIED="yes" INSTALLPKGLIST="$INSTALLPKGLIST $CURRENTREALPKGNAME" else echo " -> Cannot install $CURRENTREALPKGNAME; apt errors follow:" if apt_sim $APTFLAG $INSTALLPKGLIST "$CURRENTREALPKGNAME"; then : fi # package could not be found. -- looking for alternative. PROVIDED="" checkbuilddep_provides "$CURRENTREALPKGNAME" if [ -n "$PROVIDED" ]; then # something provides this package echo " -> Considering $PROVIDED to satisfy the dependency " if apt_sim $APTFLAG $INSTALLPKGLIST $PROVIDED >& /dev/null; then SATISFIED="yes"; INSTALLPKGLIST="$INSTALLPKGLIST $PROVIDED" else # show the error for diagnostic purposes echo " -> Cannot install $PROVIDED; apt errors follow:" apt_sim $APTFLAG $INSTALLPKGLIST $PROVIDED || true fi fi fi if [ "$SATISFIED" = "yes" ]; then break; fi done; if [ "$SATISFIED" = "no" ]; then echo "E: Could not satisfy build-dependency." >&2 if [ "$CONTINUE_FAIL" != "yes" ]; then exit 2 fi fi done; # now actually install the packages echo " -> Installing $INSTALLPKGLIST" if ! $CHROOTEXEC apt-get -y "${APTGETOPT[@]}" install $APTFLAG $INSTALLPKGLIST; then echo " -> Trying to fix apt error" # Work around an apt bug which causes configure to fail. if $CHROOTEXEC dpkg --configure --pending && $CHROOTEXEC apt-get -y "${APTGETOPT[@]}" install $APTFLAG $INSTALLPKGLIST; then echo " -> Apt bug workaround succeeded" elif [ "$CONTINUE_FAIL" != "yes" ]; then echo "E: Unrecoverable error installing build-dependencies." >&2 exit 1 fi fi # start processing build-conflicts. for INSTALLPKG in $(get_build_conflicts | split_deps); do CURRENTREALPKGNAME=$(get_pkg_name "$INSTALLPKG") echo " -> Considering $CURRENTREALPKGNAME" if echo "$INSTALLPKG" | grep -q '\['; then # this package has arch-conflicts. if checkbuilddep_archdeps "$INSTALLPKG" "$ARCH"; then echo "I: Ignoring other-arch" continue fi fi if echo "$INSTALLPKG" | greq -q '<'; then # this package has build-profiles-conflicts. if checkbuilddep_restrictiondeps "$INSTALLPKG" "$DEB_BUILD_PROFILES"; then echo "I: Ignoring other-buildprofiles" continue fi fi if echo "$INSTALLPKG" | grep -q '('; then # this package has version-conflicts if ! checkbuilddep_versiondeps "$CURRENTREALPKGNAME" $(get_dep_op_and_ver "$INSTALLPKG"); then echo "I: Satisfies version, not trying" continue fi fi # if package exists, remove it. if $CHROOTEXEC /usr/bin/dpkg -s "$CURRENTREALPKGNAME" 2>&1 | grep -q ^Package:; then if ! $CHROOTEXEC /usr/bin/apt-get -y remove "$CURRENTREALPKGNAME" ; then echo "E: Could not satisfy build-conflicts" >&2 exit 1 fi else echo "I: $CURRENTREALPKGNAME package is not installed, no need to remove" fi done echo " -> Finished parsing the build-deps" } print_help() { # print out help message cat < --help: give help --control: specify control file (debian/control, *.dsc) --chroot: operate inside chroot --binary-all: include binary-all --binary-arch: include binary-arch only --echo: echo mode, do nothing. (--force-version required for most operation) --force-version: skip version check. --continue-fail: continue even when failed. EOF } . "$PBUILDER_PKGLIBDIR"/pbuilder-satisfydepends-checkparams