Logo Search packages:      
Sourcecode: xdeb version File versions  Download package

xdeb.py

#! /usr/bin/python
# Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
# Copyright (c) 2010 Canonical Ltd.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Written by Colin Watson for Canonical Ltd.

import multiprocessing
import optparse
import os
import re
import shutil
import sys

from debian_bundle import deb822
from debian_bundle import debfile
from debian_bundle import debian_support

from config import TargetConfig
# TODO(ajwong): Remove the from utils imports since style guide does not allow
# importing of global functions in this manner.
from utils import get_output
from utils import spawn
from utils import spawn_root
import aptutils
import tree
import tsort

# TODO(ajwong): Remove this global.
target_config = None

# Abstractions for aptutils/tree functions.

def want_apt_version(options, src):
    if options.prefer_apt:
        apt_ver = aptutils.get_src_version(src)
        tree_ver = tree.get_src_version(options, src)
        if apt_ver is None:
            return False
        elif tree_ver is None:
            return True
        else:
            return (debian_support.Version(apt_ver) >
                    debian_support.Version(tree_ver))
    elif options.apt_source:
        return tree.get_src_version(options, src) is None
    else:
        return False

def get_real_pkg(options, pkg):
    """Get the real name of binary package pkg, resolving Provides."""
    if options.apt_source or options.prefer_apt:
        real_pkg = aptutils.get_real_pkg(pkg)
        if real_pkg is not None:
            return real_pkg
    return tree.get_real_pkg(options, pkg)

def get_src_name(options, pkg):
    """Return the name of the source package that produces binary package
    pkg."""

    if options.apt_source or options.prefer_apt:
        src = aptutils.get_src_name(pkg)
        if src is not None:
            return src
    return tree.get_src_name(options, pkg)

def get_src_record(options, src):
    """Return a parsed source package record for source package src."""
    if want_apt_version(options, src):
        return aptutils.get_src_record(src)
    else:
        return tree.get_src_record(options, src)

def get_pkg_record(options, pkg):
    """Return a parsed binary package record for binary package pkg."""
    src = get_src_name(options, pkg)
    if src and want_apt_version(options, src):
        return aptutils.get_pkg_record(pkg)
    else:
        return tree.get_pkg_record(options, pkg)

def get_src_version(options, src):
    """Return the current version for source package src."""
    if want_apt_version(options, src):
        return aptutils.get_src_version(src)
    else:
        return tree.get_src_version(options, src)

def get_src_binaries(options, src):
    """Return all the binaries produced by source package src."""
    if want_apt_version(options, src):
        return aptutils.get_src_binaries(src)
    else:
        return tree.get_src_binaries(options, src)


def is_toolchain(pkg):
    """Is this tool incapable of cross-building pkg?"""
    return ('libc6' in pkg or 'lib32gcc' in pkg or 'lib64gcc' in pkg or
            'libgcc' in pkg or 'libgcj' in pkg or 'libstdc++' in pkg or
            'multilib' in pkg or
            pkg == 'linux-libc-dev')

def is_crossable(pkg, conversion=False):
    """Can pkg sensibly be cross-built?"""
    global target_config
    if pkg in target_config.blacklist:
        return False # manually blacklisted
    if conversion and pkg in target_config.cross_blacklist:
        return False # manually blacklisted for cross-conversion
    if pkg in target_config.whitelist:
        return True # manually whitelisted
    if (pkg.endswith('-bin') or pkg.endswith('-common') or
        pkg.endswith('-data') or pkg.endswith('-dbg') or
        pkg.endswith('-doc') or pkg.endswith('-i18n') or
        pkg.endswith('-perl') or pkg.endswith('-pic') or
        pkg.endswith('-refdbg') or pkg.endswith('-tcl') or
        pkg.endswith('-util') or pkg.endswith('-utils') or
        pkg.startswith('python-')):
        return False # generally want build versions of these, not host
    if 'lib' in pkg:
        return True
    if 'x11proto' in pkg:
        return True
    return False

def need_loop_break(parent, pkg):
    """Sometimes we need to break loops manually."""
    if parent in ('python2.5', 'python2.6') and pkg == 'libbluetooth-dev':
        # Python build-depends on several things that are optional for
        # building. These are only used for module builds, and not for the
        # core Python binary and libraries that we need to cross-convert.
        return True
    return False


explicit_requests = set()
all_srcs = {}
depends = {}
needs_build = {}

def filter_arch(deps, arch):
    """Filter out (build-)dependencies that do not apply to arch."""
    new_deps = []
    for dep in deps:
        new_or_deps = []
        for or_dep in dep:
            ok = False
            if or_dep['arch'] is None:
                ok = True
            else:
                negated = False
                for or_dep_arch in or_dep['arch']:
                    if not or_dep_arch[0]:
                        negated = True
                    if or_dep_arch[1] == arch:
                        ok = or_dep_arch[0]
                        break
                else:
                    # Reached end of list without finding our architecture.
                    # If there were no negated elements, skip this
                    # dependency; otherwise, include it. See policy 7.1.
                    if negated:
                        ok = True
            if ok:
                new_or_deps.append(or_dep)
        if new_or_deps:
            new_deps.append(new_or_deps)
    return new_deps

def should_expand(parent, pkg):
    if pkg in explicit_requests:
        # We're going to build it anyway because it was requested on the
        # command line, so we might as well sequence it properly.
        return True
    return (is_crossable(pkg) and not is_toolchain(pkg) and
            not need_loop_break(parent, pkg))

def expand_depends(options, pkg, depth, parent=None, parent_binary=None):
    """Recursively expand (build-)dependencies of pkg."""
    src = get_src_name(options, pkg)
    if not src:
        # Is it already a source package name?
        src = pkg
    if not tree.get_src_directory(options, src):
        # Maybe it's a directory name, either relative to the current
        # directory or a build directory.
        if os.path.isdir(src):
            trydir = src
        else:
            for builddir in options.builddirs:
                if os.path.isdir(os.path.join(builddir, src)):
                    trydir = os.path.join(builddir, src)
                    break
            else:
                trydir = None
        if trydir:
            tree.scan_dir(trydir)
            realsrc = tree.get_directory_src(options, trydir)
            if realsrc:
                src = realsrc
    src_record = get_src_record(options, src)
    if not src_record:
        return

    if parent is not None and parent != src:
        if options.debug:
            if parent_binary is not None:
                print "%s%s (%s) -> %s (%s)" % (' ' * depth,
                                                parent, parent_binary,
                                                src, pkg)
            else:
                print "%s%s -> %s (%s)" % (' ' * depth, parent, src, pkg)
        depends[parent].add(src)
    if src in all_srcs:
        return
    all_srcs[src] = get_src_version(options, src)
    depends[src] = set()

    builddeps = src_record.relations['build-depends']
    if options.architecture == build_arch:
        builddeps.extend(src_record.relations['build-depends-indep'])
    builddeps = filter_arch(builddeps, options.architecture)
    for builddep in builddeps:
        if [d for d in builddep if d['name'] == 'linux-gnu']:
            # e.g. glib2.0 Build-Depends: libgamin-dev | libfam-dev | linux-gnu
            # libgamin-dev Build-Depends: libglib2.0-dev, so we need to
            # break this cycle
            continue
        bd_pkg = builddep[0]['name']
        if should_expand(src, bd_pkg):
            expand_depends(options, bd_pkg, depth + 1, parent=src)

    for binary in get_src_binaries(options, src):
        if not is_crossable(binary) or is_toolchain(binary):
            continue
        parsed_binary = get_pkg_record(options, binary)
        deps = parsed_binary.relations['pre-depends']
        deps.extend(parsed_binary.relations['depends'])
        filter_arch(deps, options.architecture)
        for dep in deps:
            for or_dep in dep:
                # TODO version handling?
                real_dep = get_real_pkg(options, or_dep['name'])
                if (real_dep is not None and
                    get_src_name(options, real_dep) is not None):
                    if should_expand(src, real_dep):
                        expand_depends(options, real_dep, depth + 1,
                                       parent=src, parent_binary=binary)
                    break

def mark_needs_build(options, src, force=False):
    """Decide whether a package needs to be (re)built."""
    if src in needs_build:
        return

    ver = all_srcs[src]
    newer = False

    if not options.force_rebuild and not force:
        ver_obj = debian_support.Version(ver)
        built_vers = sorted([b[1] for b in all_builds(options, src)])
        if built_vers:
            if built_vers[-1] >= ver_obj:
                if options.debug:
                    print "%s already built at version %s" % (src,
                                                              built_vers[-1])
                newer = False
            else:
                newer = True
        else:
            newer = True

    if options.force_rebuild or force or newer:
        needs_build[src] = True
        for depsrc, depset in depends.iteritems():
            if src in depset:
                if options.debug:
                    print "Recursing:", src, "->", depsrc
                mark_needs_build(options, depsrc, force=True)
    else:
        needs_build[src] = False


re_changes_filename = re.compile(r"(.+?)_(.+?)_(.+)\.changes$")

def all_builds(options, src=None):
    """Return the versions of all builds for source package src."""
    for name in sorted(os.listdir(options.destdir)):
        if not name.endswith('.changes'):
            continue
        path = os.path.join(options.destdir, name)
        if not os.path.isfile(path):
            continue
        matchobj = re_changes_filename.match(name)
        if not matchobj:
            continue
        if ((src is None or matchobj.group(1) == src) and
            matchobj.group(3) == options.architecture):
            changes_file = open(path)
            try:
                changes = deb822.Changes(changes_file)
                if 'version' in changes:
                    yield (matchobj.group(1),
                           debian_support.Version(changes['version']))
            finally:
                changes_file.close()


apt_conf_written = False

def update_apt_repository(options):
    global apt_conf_written
    apt_conf = os.path.join(options.destdir, 'apt.conf')
    if not apt_conf_written:
        apt_conf_file = open(apt_conf, 'w')
        print >>apt_conf_file, '''
Dir {
      ArchiveDir ".";
      CacheDir ".";
};

BinDirectory "." {
      Packages "Packages";
      BinCacheDB "pkgcache.apt";
      FileList "filelist.apt";
};'''
        apt_conf_file.close()
        apt_conf_written = True

    filelist = os.path.join(options.destdir, 'filelist.apt')
    filelist_file = open(filelist, 'w')
    for name in sorted(os.listdir(options.destdir)):
        if name.endswith('.deb'):
            print >>filelist_file, './%s' % name
    filelist_file.close()

    spawn(['apt-ftparchive', 'generate', 'apt.conf'], cwd=options.destdir)


build_arch = get_output(['dpkg-architecture', '-qDEB_BUILD_ARCH']).strip()
all_builddeps = set()

# regexes from dak
re_no_epoch = re.compile(r"^\d+\:")
re_package = re.compile(r"^(.+?)_(.+?)_([^.]+).*")

re_deb_filename = re.compile(r"(.+?)_(.+?)_(.+)\.deb$")

def install_build_depends(options, srcs):
    available_builddeps = set()
    if options.architecture != build_arch:
        if ('binutils-multiarch' in aptutils.cache and
            not aptutils.cache['binutils-multiarch'].is_installed):
            all_builddeps.add('binutils-multiarch')
    for src in srcs:
        src_record = get_src_record(options, src)
        if src_record is None:
            continue
        builddeps = src_record.relations['build-depends']
        builddeps.extend(src_record.relations['build-depends-indep'])
        for builddep in builddeps:
            if [d for d in builddep if d['name'] == 'linux-gnu']:
                continue
            # TODO versioned dependencies?
            bd_pkg = builddep[0]['name']
            real_bd_pkg = get_real_pkg(options, bd_pkg)
            if real_bd_pkg is None:
                real_bd_pkg = bd_pkg
            all_builddeps.add(real_bd_pkg)
            if (real_bd_pkg in aptutils.cache and
                not aptutils.cache[real_bd_pkg].is_installed):
                available_builddeps.add(real_bd_pkg)

    if available_builddeps:
        command = ['apt-get', '-y', '--allow-unauthenticated',
                   '--no-install-recommends', 'install']
        command.extend(sorted(available_builddeps))
        spawn_root(command)

def cross_convert(options, debs, outdir='.'):
    crossable_debs = []
    exclude_deps = set()
    for deb in debs:
        pkg = re_package.sub(r"\1", deb)
        if not is_crossable(pkg, conversion=True):
            continue
        crossable_debs.append(deb)
        control = debfile.DebFile(filename='%s/%s' % (outdir,
                                                      deb)).debcontrol()
        for field in ('pre-depends', 'depends', 'conflicts', 'breaks',
                      'provides', 'replaces'):
            if field not in control:
                continue
            for dep in deb822.PkgRelation.parse_relations(control[field]):
                for or_dep in dep:
                    if not is_crossable(or_dep['name'], conversion=True):
                        exclude_deps.add(or_dep['name'])

    crossed_debs = []
    if crossable_debs:
        convert = ['dpkg-cross', '-a', options.architecture, '-b']
        for dep in exclude_deps:
            convert.extend(('-X', dep))
        convert.extend(crossable_debs)
        spawn(convert, cwd=outdir)

        # .debs use package name suffixed with -%arch-cross and arch: all;
        # \1 and \2 are package name and version from re_deb_filename
        re_cross_deb_name = (r"\1-%s-cross_\2_all.deb" % options.architecture)
        for deb in crossable_debs:
            crossed_debs.append(re_deb_filename.sub(re_cross_deb_name, deb))
        print crossed_debs

    return crossed_debs

def native_import(options, src):
    """Import a native build of source package src at version ver."""
    src_record = aptutils.get_src_record(src)
    if not src_record:
        return
    ver = src_record['version']
    ver_no_epoch = re_no_epoch.sub('', ver)

    print
    print "===== Importing %s_%s =====" % (src, ver)
    print

    debs = []
    for binary in aptutils.get_src_binaries(src):
        try:
            bin_cache = get_output(['apt-cache', 'show', binary]).splitlines()
        except Exception:
            continue # might be a udeb
        bin_stanzas = deb822.Packages.iter_paragraphs(bin_cache)
        while True:
            try:
                bin_stanza = bin_stanzas.next()
                if 'version' not in bin_stanza or bin_stanza['version'] != ver:
                    continue
                if 'filename' not in bin_stanza:
                    continue
                deb = bin_stanza['filename']
                deb_bits = re_deb_filename.match(deb)
                if deb_bits is None:
                    continue

                if deb_bits.group(3) == build_arch:
                    deb = re_deb_filename.sub(
                        r'\1_\2_%s.deb' % options.architecture, deb)
                spawn(['wget', '-N',
                       '%s/%s' % (target_config.native_import_source, deb)],
                      cwd=options.builddirs[0])
                deb_base = deb.split('/')[-1]
                debs.append(deb_base)
            except StopIteration:
                break

    changes = '%s_%s_%s.changes' % (src, ver_no_epoch, options.architecture)
    changes_file = open(os.path.join(options.builddirs[0], changes), 'w')
    print >>changes_file, 'Version: %s\nFake: yes' % ver
    changes_file.close()

    crossed_debs = cross_convert(options, debs, options.builddirs[0])

    if crossed_debs:
        install = ['dpkg', '-i']
        install.extend(crossed_debs)
        spawn_root(install, cwd=options.builddirs[0])

    if options.builddirs[0] != options.destdir:
        files = debs + crossed_debs
        files.append(changes)
        for f in files:
            os.rename(os.path.join(options.builddirs[0], f),
                      os.path.join(options.destdir, f))

    update_apt_repository(options)

class BuildException(RuntimeError):
    pass

def build(options, src, ver):
    """Build source package src at version ver."""
    ver_no_epoch = re_no_epoch.sub('', ver)
    srcdir = tree.get_src_directory(options, src)

    use_apt = want_apt_version(options, src)
    if use_apt:
        refetch = False
        if not srcdir or not os.path.isdir(srcdir):
            refetch = True
        else:
            tree_ver = tree.get_src_version(options, src)
            if debian_support.Version(ver) < debian_support.Version(tree_ver):
                refetch = True

    if use_apt and refetch:
        spawn(['apt-get', '-d', 'source', '%s=%s' % (src, ver)],
              cwd=options.builddirs[0])
        dsc = '%s_%s.dsc' % (src, ver_no_epoch)
        if srcdir:
            shutil.rmtree(srcdir, ignore_errors=True)
        spawn(['dpkg-source', '-x', dsc, src], cwd=options.builddirs[0])
        tree.scan_dir(os.path.join(options.builddirs[0], src))
        srcdir = tree.get_src_directory(options, src)
    else:
        # Re-acquire version from the source tree, since it may be newer
        # than what we asked for.
        ver = tree.get_src_version(options, src)
        if not ver:
            return
        ver_no_epoch = re_no_epoch.sub('', ver)

    arches = tree.architectures(options, src)
    if ('any' not in arches and 'all' not in arches and
        options.architecture not in arches):
        print "%s_%s not buildable for %s" % (src, ver, options.architecture)
        return

    print
    print "===== Building %s_%s =====" % (src, ver)
    print

    spawn(['dpkg-checkbuilddeps'], cwd=srcdir)

    buildpackage = ['debuild', '--no-lintian', '-eUSER']
    global target_config
    if options.parallel and src not in target_config.parallel_blacklist:
        cpu_count = multiprocessing.cpu_count()
        if cpu_count > 1:
            # Rule of thumb is to spawn 1 more than the number of CPUs when
            # building.
            buildpackage.append('-j%s' % (cpu_count + 1) )
    if options.architecture != build_arch:
        buildpackage.append('-eCONFIG_SITE=/etc/dpkg-cross/cross-config.%s' %
                            options.architecture)
        if 'DEB_BUILD_OPTIONS' in os.environ:
            buildpackage.append('-eDEB_BUILD_OPTIONS=%s nocheck' %
                                os.environ['DEB_BUILD_OPTIONS'])
        else:
            buildpackage.append('-eDEB_BUILD_OPTIONS=nocheck')
        deb_host_gnu_type = get_output(['dpkg-architecture',
                                        '-a%s' % options.architecture,
                                        '-qDEB_HOST_GNU_TYPE']).rstrip('\n')
        buildpackage.append('-eGTEST_INCLUDEDIR=/usr/%s/include' %
                            deb_host_gnu_type)
        buildpackage.append('-eGTEST_LIBDIR=/usr/%s/lib' % deb_host_gnu_type)
        if options.debug:
            buildpackage.append('-eDH_VERBOSE=1')
        buildpackage.append('-a%s' % options.architecture)
    buildpackage.extend(['-b', '-uc', '-us'])
    if options.clean_after:
        buildpackage.append('-tc')
    spawn(buildpackage, cwd=srcdir)

    outdir = os.path.normpath(os.path.join(
        tree.get_src_directory(options, src), '..'))
    changes = '%s_%s_%s.changes' % (src, ver_no_epoch, options.architecture)
    build_log = '%s_%s_%s.build' % (src, ver_no_epoch, options.architecture)
    debs = get_output(['dcmd', '--deb', changes], cwd=outdir).splitlines()
    print "Built packages:", ' '.join(debs)

    # Install whatever we're going to need for future build-dependencies. We
    # do this in both native and cross modes because it's fairly common to
    # need things like data files from native packages even in cross mode,
    # and because that allows us to build and install
    # architecture-independent packages in cross mode.
    builddep_debs = []
    for deb in debs:
        pkg = re_package.sub(r"\1", deb)
        arch = re_package.sub(r"\3", deb)
        # TODO: is_crossable is a hack, mostly to avoid problems with
        # libfoo-dev depending on libfoo0 because we don't have a proper
        # build-dependency installer yet.
        if arch in (build_arch, 'all') and \
            pkg not in target_config.blacklist and \
            (pkg in all_builddeps or is_crossable(pkg) or
             pkg in target_config.builddep_whitelist):
            builddep_debs.append(deb)

    if options.architecture != build_arch:
        if options.lintian:
            spawn(['lintian', '-C', 'xdeb', '-o', changes], cwd=outdir)
        crossed_debs = cross_convert(options, debs, outdir)
        builddep_debs.extend(crossed_debs)

    if builddep_debs:
        install = ['dpkg', '-i']
        install.extend(builddep_debs)
        spawn_root(install, cwd=outdir)

    if outdir != options.destdir:
        files = get_output(['dcmd', changes], cwd=outdir).splitlines()
        for f in files:
            os.rename(os.path.join(outdir, f),
                      os.path.join(options.destdir, f))
        if os.path.exists(os.path.join(outdir, build_log)):
            os.rename(os.path.join(outdir, build_log),
                      os.path.join(options.destdir, build_log))
        if options.architecture != build_arch:
            for deb in crossed_debs:
                os.rename(os.path.join(outdir, deb),
                          os.path.join(options.destdir, deb))

    update_apt_repository(options)


def main():
    usage = '%prog [options] package ...'
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('-C', '--config-files', dest='config_files',
                      help='read these config files [e.g., file1, file2]')
    parser.add_option('-a', '--architecture',
                      dest='architecture', default=build_arch,
                      help='build for architecture ARCH', metavar='ARCH')
    parser.add_option('--variant',
                      dest='variant', default='generic',
                      help='build for VARIANT variant of the architecture '
                           '(default: generic)',
                      metavar='VARIANT')
    parser.add_option('-b', '--build-directory',
                      action='append', dest='builddirs',
                      help='build packages in DIR (default: .)', metavar='DIR')
    parser.add_option('-d', '--dest-directory',
                      dest='destdir', default=None,
                      help='leave built packages in DIR '
                           '(default: value of --build-directory)',
                      metavar='DIR')
    parser.add_option('-f', '--force-rebuild', dest='force_rebuild',
                      action='store_true', default=False,
                      help="force rebuild even if unchanged")
    parser.add_option('--apt-source', dest='apt_source',
                      action='store_true', default=False,
                      help='fetch source code using apt-get')
    parser.add_option('--prefer-apt', dest='prefer_apt',
                      action='store_true', default=False,
                      help='prefer source packages available using apt-get')
    parser.add_option('--debug', dest='debug',
                      action='store_true', default=False,
                      help='debug build sequencing')
    parser.add_option('--parallel', dest='parallel',
                      action='store_true', default=False,
                      help='use as many jobs as there are CPUs on the system')
    parser.add_option('--no-clean-after', dest='clean_after',
                      action='store_false', default=True,
                      help='clean source tree after build')
    parser.add_option('--no-lintian', dest='lintian',
                      action='store_false', default=True,
                      help='disable Lintian checks of cross-built packages')
    parser.add_option('--sequence', dest='sequence',
                      action='store_true', default=False,
                      help="don't build; just show build sequence")
    parser.add_option('--list-builds', dest='list_builds',
                      action='store_true', default=False,
                      help="list current successful builds")
    parser.add_option('--all', dest='all',
                      action='store_true', default=False,
                      help="build all packages in the working tree")
    parser.add_option('-x', '--exclude', dest='exclude',
                      action='append',
                      help="don't build this package (unless required by "
                           "dependencies)")
    parser.add_option('--no-native-import', dest='native_import',
                      action='store_false', default=True,
                      help='disable automatic native imports')
    parser.add_option('--convert', dest='convert',
                      action='store_true', default=False,
                      help="don't build; just cross-convert packages")
    parser.add_option('--no-convert-install', dest='convert_install',
                      action='store_false', default=True,
                      help="don't install packages after cross-conversion")
    options, args = parser.parse_args()

    config_paths = None
    if options.config_files:
        config_paths = options.config_files.split(',')

    global target_config
    target_config = TargetConfig(options.architecture,
                                 options.variant)
    target_config.InitializeFromConfigs(config_paths)

    if options.debug:
        print 'Configuration is:\n%s' % target_config

    # Use config file values for options if no commandline override was given.
    for name, value in target_config.options.iteritems():
        if name in parser.defaults:
            if getattr(options, name) == parser.defaults[name]:
                if name in ('builddirs', 'exclude'):
                    setattr(options, name, value.split())
                elif isinstance(parser.defaults[name], bool):
                    setattr(options, name, bool(value))
                else:
                    setattr(options, name, value)

    if not options.builddirs:
        options.builddirs = ['.']
    if options.destdir is None:
        options.destdir = options.builddirs[0]
    if not options.exclude:
        options.exclude = []

    for builddir in options.builddirs:
        if not os.path.exists(builddir):
            os.makedirs(builddir)
    if not os.path.exists(options.destdir):
        os.makedirs(options.destdir)

    if options.list_builds:
        build_srcs = {}
        for b in all_builds(options):
            src, ver = b
            if src not in build_srcs or ver > build_srcs[src]:
                build_srcs[src] = ver
        for src in sorted(build_srcs.keys()):
            print src, build_srcs[src]
        sys.exit(0)

    if options.convert:
        crossed_debs = cross_convert(options, args)
        if crossed_debs and options.convert_install:
            install = ['dpkg', '-i']
            install.extend(crossed_debs)
            spawn_root(install)
        sys.exit(0)

    if options.all:
        args = tree.all_packages(options) + args

    explicit_requests.update(args)
    for pkg in args:
        expand_depends(options, pkg, 0)

    try:
        build_sequence = tsort.topo_sort(depends)
    except tsort.GraphCycleError, e:
        print "Dependency cycle:", e.graph
        sys.exit(1)
    for src in build_sequence:
        mark_needs_build(options, src)
    print "Build sequence:",
    for src in build_sequence:
        if needs_build[src]:
            print '%s*' % src,
        else:
            print src,
    print
    if options.sequence:
        sys.exit(0)

    if not build_sequence and not (options.apt_source or options.prefer_apt):
        print ("Build sequence is empty. Did you mean to use "
               "--apt-source or --prefer-apt?")

    install_build_depends(options, build_sequence)

    for src in build_sequence:
        if needs_build[src]:
            if src in target_config.native_import:
                native_import(options, src)
            else:
                build(options, src, all_srcs[src])

if __name__ == '__main__':
    main()

Generated by  Doxygen 1.6.0   Back to index