diff options
Diffstat (limited to 'bitbake-dev/lib/bb/cooker.py')
| -rw-r--r-- | bitbake-dev/lib/bb/cooker.py | 978 | 
1 files changed, 0 insertions, 978 deletions
| diff --git a/bitbake-dev/lib/bb/cooker.py b/bitbake-dev/lib/bb/cooker.py deleted file mode 100644 index 8036d7e9d5..0000000000 --- a/bitbake-dev/lib/bb/cooker.py +++ /dev/null @@ -1,978 +0,0 @@ -#!/usr/bin/env python -# ex:ts=4:sw=4:sts=4:et -# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- -# -# Copyright (C) 2003, 2004  Chris Larson -# Copyright (C) 2003, 2004  Phil Blundell -# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer -# Copyright (C) 2005        Holger Hans Peter Freyther -# Copyright (C) 2005        ROAD GmbH -# Copyright (C) 2006 - 2007 Richard Purdie -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import sys, os, getopt, glob, copy, os.path, re, time -import bb -from bb import utils, data, parse, event, cache, providers, taskdata, runqueue -from bb import command -import bb.server.xmlrpc -import itertools, sre_constants - -class MultipleMatches(Exception): -    """ -    Exception raised when multiple file matches are found -    """ - -class ParsingErrorsFound(Exception): -    """ -    Exception raised when parsing errors are found -    """ - -class NothingToBuild(Exception): -    """ -    Exception raised when there is nothing to build -    """ - - -# Different states cooker can be in -cookerClean = 1 -cookerParsing = 2 -cookerParsed = 3 - -# Different action states the cooker can be in -cookerRun = 1           # Cooker is running normally -cookerShutdown = 2      # Active tasks should be brought to a controlled stop -cookerStop = 3          # Stop, now! - -#============================================================================# -# BBCooker -#============================================================================# -class BBCooker: -    """ -    Manages one bitbake build run -    """ - -    def __init__(self, configuration, server): -        self.status = None - -        self.cache = None -        self.bb_cache = None - -        self.server = server.BitBakeServer(self) - -        self.configuration = configuration - -        if self.configuration.verbose: -            bb.msg.set_verbose(True) - -        if self.configuration.debug: -            bb.msg.set_debug_level(self.configuration.debug) -        else: -            bb.msg.set_debug_level(0) - -        if self.configuration.debug_domains: -            bb.msg.set_debug_domains(self.configuration.debug_domains) - -        self.configuration.data = bb.data.init() - -        bb.data.inheritFromOS(self.configuration.data) - -        for f in self.configuration.file: -            self.parseConfigurationFile( f ) - -        self.parseConfigurationFile( os.path.join( "conf", "bitbake.conf" ) ) - -        if not self.configuration.cmd: -            self.configuration.cmd = bb.data.getVar("BB_DEFAULT_TASK", self.configuration.data, True) or "build" - -        bbpkgs = bb.data.getVar('BBPKGS', self.configuration.data, True) -        if bbpkgs and len(self.configuration.pkgs_to_build) == 0: -            self.configuration.pkgs_to_build.extend(bbpkgs.split()) - -        # -        # Special updated configuration we use for firing events -        # -        self.configuration.event_data = bb.data.createCopy(self.configuration.data) -        bb.data.update_data(self.configuration.event_data) - -        # TOSTOP must not be set or our children will hang when they output -        fd = sys.stdout.fileno() -        if os.isatty(fd): -            import termios -            tcattr = termios.tcgetattr(fd) -            if tcattr[3] & termios.TOSTOP: -                bb.msg.note(1, bb.msg.domain.Build, "The terminal had the TOSTOP bit set, clearing...") -                tcattr[3] = tcattr[3] & ~termios.TOSTOP -                termios.tcsetattr(fd, termios.TCSANOW, tcattr) - -        self.command = bb.command.Command(self) -        self.cookerState = cookerClean -        self.cookerAction = cookerRun - -    def parseConfiguration(self): - - -        # Change nice level if we're asked to -        nice = bb.data.getVar("BB_NICE_LEVEL", self.configuration.data, True) -        if nice: -            curnice = os.nice(0) -            nice = int(nice) - curnice -            bb.msg.note(2, bb.msg.domain.Build, "Renice to %s " % os.nice(nice)) - -    def parseCommandLine(self): -        # Parse any commandline into actions -        if self.configuration.show_environment: -            self.commandlineAction = None - -            if 'world' in self.configuration.pkgs_to_build: -                bb.error("'world' is not a valid target for --environment.") -            elif len(self.configuration.pkgs_to_build) > 1: -                bb.error("Only one target can be used with the --environment option.") -            elif self.configuration.buildfile and len(self.configuration.pkgs_to_build) > 0: -                bb.error("No target should be used with the --environment and --buildfile options.") -            elif len(self.configuration.pkgs_to_build) > 0: -                self.commandlineAction = ["showEnvironmentTarget", self.configuration.pkgs_to_build] -            else: -                self.commandlineAction = ["showEnvironment", self.configuration.buildfile] -        elif self.configuration.buildfile is not None: -            self.commandlineAction = ["buildFile", self.configuration.buildfile, self.configuration.cmd] -        elif self.configuration.revisions_changed: -            self.commandlineAction = ["compareRevisions"] -        elif self.configuration.show_versions: -            self.commandlineAction = ["showVersions"] -        elif self.configuration.parse_only: -            self.commandlineAction = ["parseFiles"] -        # FIXME - implement -        #elif self.configuration.interactive: -        #    self.interactiveMode() -        elif self.configuration.dot_graph: -            if self.configuration.pkgs_to_build: -                self.commandlineAction = ["generateDotGraph", self.configuration.pkgs_to_build, self.configuration.cmd] -            else: -                self.commandlineAction = None -                bb.error("Please specify a package name for dependency graph generation.") -        else: -            if self.configuration.pkgs_to_build: -                self.commandlineAction = ["buildTargets", self.configuration.pkgs_to_build, self.configuration.cmd] -            else: -                self.commandlineAction = None -                bb.error("Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.") - -    def runCommands(self, server, data, abort): -        """ -        Run any queued asynchronous command -        This is done by the idle handler so it runs in true context rather than -        tied to any UI. -        """ - -        return self.command.runAsyncCommand() - -    def tryBuildPackage(self, fn, item, task, the_data): -        """ -        Build one task of a package, optionally build following task depends -        """ -        try: -            if not self.configuration.dry_run: -                bb.build.exec_task('do_%s' % task, the_data) -            return True -        except bb.build.FuncFailed: -            bb.msg.error(bb.msg.domain.Build, "task stack execution failed") -            raise -        except bb.build.EventException, e: -            event = e.args[1] -            bb.msg.error(bb.msg.domain.Build, "%s event exception, aborting" % bb.event.getName(event)) -            raise - -    def tryBuild(self, fn, task): -        """ -        Build a provider and its dependencies.  -        build_depends is a list of previous build dependencies (not runtime) -        If build_depends is empty, we're dealing with a runtime depends -        """ - -        the_data = self.bb_cache.loadDataFull(fn, self.configuration.data) - -        item = self.status.pkg_fn[fn] - -        #if bb.build.stamp_is_current('do_%s' % self.configuration.cmd, the_data): -        #    return True - -        return self.tryBuildPackage(fn, item, task, the_data) - -    def showVersions(self): - -        # Need files parsed -        self.updateCache() - -        pkg_pn = self.status.pkg_pn -        preferred_versions = {} -        latest_versions = {} - -        # Sort by priority -        for pn in pkg_pn.keys(): -            (last_ver,last_file,pref_ver,pref_file) = bb.providers.findBestProvider(pn, self.configuration.data, self.status) -            preferred_versions[pn] = (pref_ver, pref_file) -            latest_versions[pn] = (last_ver, last_file) - -        pkg_list = pkg_pn.keys() -        pkg_list.sort() - -        bb.msg.plain("%-35s %25s %25s" % ("Package Name", "Latest Version", "Preferred Version")) -        bb.msg.plain("%-35s %25s %25s\n" % ("============", "==============", "=================")) - -        for p in pkg_list: -            pref = preferred_versions[p] -            latest = latest_versions[p] - -            prefstr = pref[0][0] + ":" + pref[0][1] + '-' + pref[0][2] -            lateststr = latest[0][0] + ":" + latest[0][1] + "-" + latest[0][2] - -            if pref == latest: -                prefstr = "" - -            bb.msg.plain("%-35s %25s %25s" % (p, lateststr, prefstr)) - -    def compareRevisions(self): -        ret = bb.fetch.fetcher_compare_revisons(self.configuration.data) -        bb.event.fire(bb.command.CookerCommandSetExitCode(ret), self.configuration.event_data) - -    def showEnvironment(self, buildfile = None, pkgs_to_build = []): -        """ -        Show the outer or per-package environment -        """ -        fn = None -        envdata = None - -        if buildfile: -            self.cb = None -            self.bb_cache = bb.cache.init(self) -            fn = self.matchFile(buildfile) -        elif len(pkgs_to_build) == 1: -            self.updateCache() - -            localdata = data.createCopy(self.configuration.data) -            bb.data.update_data(localdata) -            bb.data.expandKeys(localdata) - -            taskdata = bb.taskdata.TaskData(self.configuration.abort) -            taskdata.add_provider(localdata, self.status, pkgs_to_build[0]) -            taskdata.add_unresolved(localdata, self.status) - -            targetid = taskdata.getbuild_id(pkgs_to_build[0]) -            fnid = taskdata.build_targets[targetid][0] -            fn = taskdata.fn_index[fnid] -        else: -            envdata = self.configuration.data - -        if fn: -            try: -                envdata = self.bb_cache.loadDataFull(fn, self.configuration.data) -            except IOError, e: -                bb.msg.error(bb.msg.domain.Parsing, "Unable to read %s: %s" % (fn, e)) -                raise -            except Exception, e: -                bb.msg.error(bb.msg.domain.Parsing, "%s" % e) -                raise - -        class dummywrite: -            def __init__(self): -                self.writebuf = "" -            def write(self, output): -                self.writebuf = self.writebuf + output - -        # emit variables and shell functions -        try: -            data.update_data(envdata) -            wb = dummywrite() -            data.emit_env(wb, envdata, True) -            bb.msg.plain(wb.writebuf) -        except Exception, e: -            bb.msg.fatal(bb.msg.domain.Parsing, "%s" % e) -        # emit the metadata which isnt valid shell -        data.expandKeys(envdata) -        for e in envdata.keys(): -            if data.getVarFlag( e, 'python', envdata ): -                bb.msg.plain("\npython %s () {\n%s}\n" % (e, data.getVar(e, envdata, 1))) - -    def generateDepTreeData(self, pkgs_to_build, task): -        """ -        Create a dependency tree of pkgs_to_build, returning the data. -        """ - -        # Need files parsed -        self.updateCache() - -        # If we are told to do the None task then query the default task -        if (task == None): -            task = self.configuration.cmd - -        pkgs_to_build = self.checkPackages(pkgs_to_build) - -        localdata = data.createCopy(self.configuration.data) -        bb.data.update_data(localdata) -        bb.data.expandKeys(localdata) -        taskdata = bb.taskdata.TaskData(self.configuration.abort) - -        runlist = [] -        for k in pkgs_to_build: -            taskdata.add_provider(localdata, self.status, k) -            runlist.append([k, "do_%s" % task]) -        taskdata.add_unresolved(localdata, self.status) - -        rq = bb.runqueue.RunQueue(self, self.configuration.data, self.status, taskdata, runlist) -        rq.prepare_runqueue() - -        seen_fnids = []   -        depend_tree = {} -        depend_tree["depends"] = {} -        depend_tree["tdepends"] = {} -        depend_tree["pn"] = {} -        depend_tree["rdepends-pn"] = {} -        depend_tree["packages"] = {} -        depend_tree["rdepends-pkg"] = {} -        depend_tree["rrecs-pkg"] = {} - -        for task in range(len(rq.runq_fnid)): -            taskname = rq.runq_task[task] -            fnid = rq.runq_fnid[task] -            fn = taskdata.fn_index[fnid] -            pn = self.status.pkg_fn[fn] -            version  = "%s:%s-%s" % self.status.pkg_pepvpr[fn] -            if pn not in depend_tree["pn"]: -                depend_tree["pn"][pn] = {} -                depend_tree["pn"][pn]["filename"] = fn -                depend_tree["pn"][pn]["version"] = version -            for dep in rq.runq_depends[task]: -                depfn = taskdata.fn_index[rq.runq_fnid[dep]] -                deppn = self.status.pkg_fn[depfn] -                dotname = "%s.%s" % (pn, rq.runq_task[task]) -                if not dotname in depend_tree["tdepends"]: -                    depend_tree["tdepends"][dotname] = [] -                depend_tree["tdepends"][dotname].append("%s.%s" % (deppn, rq.runq_task[dep])) -            if fnid not in seen_fnids: -                seen_fnids.append(fnid) -                packages = [] - -                depend_tree["depends"][pn] = [] -                for dep in taskdata.depids[fnid]: -                    depend_tree["depends"][pn].append(taskdata.build_names_index[dep]) - -                depend_tree["rdepends-pn"][pn] = [] -                for rdep in taskdata.rdepids[fnid]: -                        depend_tree["rdepends-pn"][pn].append(taskdata.run_names_index[rdep]) - -                rdepends = self.status.rundeps[fn] -                for package in rdepends: -                    depend_tree["rdepends-pkg"][package] = [] -                    for rdepend in rdepends[package]: -                        depend_tree["rdepends-pkg"][package].append(rdepend) -                    packages.append(package) - -                rrecs = self.status.runrecs[fn] -                for package in rrecs: -                    depend_tree["rrecs-pkg"][package] = [] -                    for rdepend in rrecs[package]: -                        depend_tree["rrecs-pkg"][package].append(rdepend) -                    if not package in packages: -                        packages.append(package) - -                for package in packages: -                    if package not in depend_tree["packages"]: -                        depend_tree["packages"][package] = {} -                        depend_tree["packages"][package]["pn"] = pn -                        depend_tree["packages"][package]["filename"] = fn -                        depend_tree["packages"][package]["version"] = version - -        return depend_tree - - -    def generateDepTreeEvent(self, pkgs_to_build, task): -        """ -        Create a task dependency graph of pkgs_to_build. -        Generate an event with the result -        """ -        depgraph = self.generateDepTreeData(pkgs_to_build, task) -        bb.event.fire(bb.event.DepTreeGenerated(depgraph), self.configuration.data) - -    def generateDotGraphFiles(self, pkgs_to_build, task): -        """ -        Create a task dependency graph of pkgs_to_build. -        Save the result to a set of .dot files. -        """ - -        depgraph = self.generateDepTreeData(pkgs_to_build, task) - -        # Prints a flattened form of package-depends below where subpackages of a package are merged into the main pn -        depends_file = file('pn-depends.dot', 'w' ) -        print >> depends_file, "digraph depends {" -        for pn in depgraph["pn"]: -            fn = depgraph["pn"][pn]["filename"] -            version = depgraph["pn"][pn]["version"] -            print >> depends_file, '"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn) -        for pn in depgraph["depends"]: -            for depend in depgraph["depends"][pn]: -                print >> depends_file, '"%s" -> "%s"' % (pn, depend) -        for pn in depgraph["rdepends-pn"]: -            for rdepend in depgraph["rdepends-pn"][pn]: -                print >> depends_file, '"%s" -> "%s" [style=dashed]' % (pn, rdepend) -        print >> depends_file,  "}" -        bb.msg.plain("PN dependencies saved to 'pn-depends.dot'") - -        depends_file = file('package-depends.dot', 'w' ) -        print >> depends_file, "digraph depends {" -        for package in depgraph["packages"]: -            pn = depgraph["packages"][package]["pn"] -            fn = depgraph["packages"][package]["filename"] -            version = depgraph["packages"][package]["version"] -            if package == pn: -                print >> depends_file, '"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn) -            else: -                print >> depends_file, '"%s" [label="%s(%s) %s\\n%s"]' % (package, package, pn, version, fn) -            for depend in depgraph["depends"][pn]: -                print >> depends_file, '"%s" -> "%s"' % (package, depend) -        for package in depgraph["rdepends-pkg"]: -            for rdepend in depgraph["rdepends-pkg"][package]: -                print >> depends_file, '"%s" -> "%s" [style=dashed]' % (package, rdepend) -        for package in depgraph["rrecs-pkg"]: -            for rdepend in depgraph["rrecs-pkg"][package]: -                print >> depends_file, '"%s" -> "%s" [style=dashed]' % (package, rdepend) -        print >> depends_file,  "}" -        bb.msg.plain("Package dependencies saved to 'package-depends.dot'") - -        tdepends_file = file('task-depends.dot', 'w' ) -        print >> tdepends_file, "digraph depends {" -        for task in depgraph["tdepends"]: -            (pn, taskname) = task.rsplit(".", 1) -            fn = depgraph["pn"][pn]["filename"] -            version = depgraph["pn"][pn]["version"] -            print >> tdepends_file, '"%s.%s" [label="%s %s\\n%s\\n%s"]' % (pn, taskname, pn, taskname, version, fn) -            for dep in depgraph["tdepends"][task]: -                print >> tdepends_file, '"%s" -> "%s"' % (task, dep) -        print >> tdepends_file,  "}" -        bb.msg.plain("Task dependencies saved to 'task-depends.dot'") - -    def buildDepgraph( self ): -        all_depends = self.status.all_depends -        pn_provides = self.status.pn_provides - -        localdata = data.createCopy(self.configuration.data) -        bb.data.update_data(localdata) -        bb.data.expandKeys(localdata) - -        def calc_bbfile_priority(filename): -            for (regex, pri) in self.status.bbfile_config_priorities: -                if regex.match(filename): -                    return pri -            return 0 - -        # Handle PREFERRED_PROVIDERS -        for p in (bb.data.getVar('PREFERRED_PROVIDERS', localdata, 1) or "").split(): -            try: -                (providee, provider) = p.split(':') -            except: -                bb.msg.fatal(bb.msg.domain.Provider, "Malformed option in PREFERRED_PROVIDERS variable: %s" % p) -                continue -            if providee in self.status.preferred and self.status.preferred[providee] != provider: -                bb.msg.error(bb.msg.domain.Provider, "conflicting preferences for %s: both %s and %s specified" % (providee, provider, self.status.preferred[providee])) -            self.status.preferred[providee] = provider - -        # Calculate priorities for each file -        for p in self.status.pkg_fn.keys(): -            self.status.bbfile_priority[p] = calc_bbfile_priority(p) - -    def buildWorldTargetList(self): -        """ -         Build package list for "bitbake world" -        """ -        all_depends = self.status.all_depends -        pn_provides = self.status.pn_provides -        bb.msg.debug(1, bb.msg.domain.Parsing, "collating packages for \"world\"") -        for f in self.status.possible_world: -            terminal = True -            pn = self.status.pkg_fn[f] - -            for p in pn_provides[pn]: -                if p.startswith('virtual/'): -                    bb.msg.debug(2, bb.msg.domain.Parsing, "World build skipping %s due to %s provider starting with virtual/" % (f, p)) -                    terminal = False -                    break -                for pf in self.status.providers[p]: -                    if self.status.pkg_fn[pf] != pn: -                        bb.msg.debug(2, bb.msg.domain.Parsing, "World build skipping %s due to both us and %s providing %s" % (f, pf, p)) -                        terminal = False -                        break -            if terminal: -                self.status.world_target.add(pn) - -            # drop reference count now -            self.status.possible_world = None -            self.status.all_depends    = None - -    def interactiveMode( self ): -        """Drop off into a shell""" -        try: -            from bb import shell -        except ImportError, details: -            bb.msg.fatal(bb.msg.domain.Parsing, "Sorry, shell not available (%s)" % details ) -        else: -            shell.start( self ) - -    def parseConfigurationFile( self, afile ): -        try: -            self.configuration.data = bb.parse.handle( afile, self.configuration.data ) - -            # Handle any INHERITs and inherit the base class -            inherits  = ["base"] + (bb.data.getVar('INHERIT', self.configuration.data, True ) or "").split() -            for inherit in inherits: -                self.configuration.data = bb.parse.handle(os.path.join('classes', '%s.bbclass' % inherit), self.configuration.data, True ) - -            # Nomally we only register event handlers at the end of parsing .bb files -            # We register any handlers we've found so far here... -            for var in data.getVar('__BBHANDLERS', self.configuration.data) or []: -                bb.event.register(var,bb.data.getVar(var, self.configuration.data)) - -            bb.fetch.fetcher_init(self.configuration.data) - -            bb.event.fire(bb.event.ConfigParsed(), self.configuration.data) - -        except IOError, e: -            bb.msg.fatal(bb.msg.domain.Parsing, "Error when parsing %s: %s" % (afile, str(e))) -        except bb.parse.ParseError, details: -            bb.msg.fatal(bb.msg.domain.Parsing, "Unable to parse %s (%s)" % (afile, details) ) - -    def handleCollections( self, collections ): -        """Handle collections""" -        if collections: -            collection_list = collections.split() -            for c in collection_list: -                regex = bb.data.getVar("BBFILE_PATTERN_%s" % c, self.configuration.data, 1) -                if regex == None: -                    bb.msg.error(bb.msg.domain.Parsing, "BBFILE_PATTERN_%s not defined" % c) -                    continue -                priority = bb.data.getVar("BBFILE_PRIORITY_%s" % c, self.configuration.data, 1) -                if priority == None: -                    bb.msg.error(bb.msg.domain.Parsing, "BBFILE_PRIORITY_%s not defined" % c) -                    continue -                try: -                    cre = re.compile(regex) -                except re.error: -                    bb.msg.error(bb.msg.domain.Parsing, "BBFILE_PATTERN_%s \"%s\" is not a valid regular expression" % (c, regex)) -                    continue -                try: -                    pri = int(priority) -                    self.status.bbfile_config_priorities.append((cre, pri)) -                except ValueError: -                    bb.msg.error(bb.msg.domain.Parsing, "invalid value for BBFILE_PRIORITY_%s: \"%s\"" % (c, priority)) - -    def buildSetVars(self): -        """ -        Setup any variables needed before starting a build -        """ -        if not bb.data.getVar("BUILDNAME", self.configuration.data): -            bb.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), self.configuration.data) -        bb.data.setVar("BUILDSTART", time.strftime('%m/%d/%Y %H:%M:%S',time.gmtime()), self.configuration.data) - -    def matchFiles(self, buildfile): -        """ -        Find the .bb files which match the expression in 'buildfile'. -        """ - -        bf = os.path.abspath(buildfile) -        try: -            os.stat(bf) -            return [bf] -        except OSError: -            (filelist, masked) = self.collect_bbfiles() -            regexp = re.compile(buildfile) -            matches = [] -            for f in filelist: -                if regexp.search(f) and os.path.isfile(f): -                    bf = f -                    matches.append(f) -            return matches - -    def matchFile(self, buildfile): -        """ -        Find the .bb file which matches the expression in 'buildfile'. -        Raise an error if multiple files -        """ -        matches = self.matchFiles(buildfile) -        if len(matches) != 1: -            bb.msg.error(bb.msg.domain.Parsing, "Unable to match %s (%s matches found):" % (buildfile, len(matches))) -            for f in matches: -                bb.msg.error(bb.msg.domain.Parsing, "    %s" % f) -            raise MultipleMatches -        return matches[0] - -    def buildFile(self, buildfile, task): -        """ -        Build the file matching regexp buildfile -        """ - -        # Parse the configuration here. We need to do it explicitly here since -        # buildFile() doesn't use the cache -        self.parseConfiguration() - -        # If we are told to do the None task then query the default task -        if (task == None): -            task = self.configuration.cmd - -        fn = self.matchFile(buildfile) -        self.buildSetVars() - -        # Load data into the cache for fn and parse the loaded cache data -        self.bb_cache = bb.cache.init(self) -        self.status = bb.cache.CacheData() -        self.bb_cache.loadData(fn, self.configuration.data, self.status)       - -        # Tweak some variables -        item = self.bb_cache.getVar('PN', fn, True) -        self.status.ignored_dependencies = set() -        self.status.bbfile_priority[fn] = 1 - -        # Remove external dependencies -        self.status.task_deps[fn]['depends'] = {} -        self.status.deps[fn] = [] -        self.status.rundeps[fn] = [] -        self.status.runrecs[fn] = [] - -        # Remove stamp for target if force mode active -        if self.configuration.force: -            bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (task, fn)) -            bb.build.del_stamp('do_%s' % task, self.status, fn) - -        # Setup taskdata structure -        taskdata = bb.taskdata.TaskData(self.configuration.abort) -        taskdata.add_provider(self.configuration.data, self.status, item) - -        buildname = bb.data.getVar("BUILDNAME", self.configuration.data) -        bb.event.fire(bb.event.BuildStarted(buildname, [item]), self.configuration.event_data) - -        # Execute the runqueue -        runlist = [[item, "do_%s" % task]] - -        rq = bb.runqueue.RunQueue(self, self.configuration.data, self.status, taskdata, runlist) - -        def buildFileIdle(server, rq, abort): - -            if abort or self.cookerAction == cookerStop: -                rq.finish_runqueue(True) -            elif self.cookerAction == cookerShutdown: -                rq.finish_runqueue(False) -            failures = 0 -            try: -                retval = rq.execute_runqueue() -            except runqueue.TaskFailure, fnids: -                for fnid in fnids: -                    bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid]) -                    failures = failures + 1 -                retval = False -            if not retval: -                self.command.finishAsyncCommand() -                bb.event.fire(bb.event.BuildCompleted(buildname, item, failures), self.configuration.event_data) -                return False -            return 0.5 - -        self.server.register_idle_function(buildFileIdle, rq) - -    def buildTargets(self, targets, task): -        """ -        Attempt to build the targets specified -        """ - -        # Need files parsed -        self.updateCache() - -        # If we are told to do the NULL task then query the default task -        if (task == None): -            task = self.configuration.cmd - -        targets = self.checkPackages(targets) - -        def buildTargetsIdle(server, rq, abort): - -            if abort or self.cookerAction == cookerStop: -                rq.finish_runqueue(True) -            elif self.cookerAction == cookerShutdown: -                rq.finish_runqueue(False) -            failures = 0 -            try: -                retval = rq.execute_runqueue() -            except runqueue.TaskFailure, fnids: -                for fnid in fnids: -                    bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid]) -                    failures = failures + 1 -                retval = False -            if not retval: -                self.command.finishAsyncCommand() -                bb.event.fire(bb.event.BuildCompleted(buildname, targets, failures), self.configuration.event_data) -                return None -            return 0.5 - -        self.buildSetVars() - -        buildname = bb.data.getVar("BUILDNAME", self.configuration.data) -        bb.event.fire(bb.event.BuildStarted(buildname, targets), self.configuration.event_data) - -        localdata = data.createCopy(self.configuration.data) -        bb.data.update_data(localdata) -        bb.data.expandKeys(localdata) - -        taskdata = bb.taskdata.TaskData(self.configuration.abort) - -        runlist = [] -        for k in targets: -            taskdata.add_provider(localdata, self.status, k) -            runlist.append([k, "do_%s" % task]) -        taskdata.add_unresolved(localdata, self.status) - -        rq = bb.runqueue.RunQueue(self, self.configuration.data, self.status, taskdata, runlist) - -        self.server.register_idle_function(buildTargetsIdle, rq) - -    def updateCache(self): - -        if self.cookerState == cookerParsed: -            return - -        if self.cookerState != cookerParsing: - -            self.parseConfiguration () - -            # Import Psyco if available and not disabled -            import platform -            if platform.machine() in ['i386', 'i486', 'i586', 'i686']: -                if not self.configuration.disable_psyco: -                    try: -                        import psyco -                    except ImportError: -                        bb.msg.note(1, bb.msg.domain.Collection, "Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance.") -                    else: -                        psyco.bind( CookerParser.parse_next ) -                else: -                    bb.msg.note(1, bb.msg.domain.Collection, "You have disabled Psyco. This decreases performance.") - -            self.status = bb.cache.CacheData() - -            ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or "" -            self.status.ignored_dependencies = set(ignore.split()) -     -            for dep in self.configuration.extra_assume_provided: -                self.status.ignored_dependencies.add(dep) -     -            self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) ) - -            bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files") -            (filelist, masked) = self.collect_bbfiles() -            bb.data.renameVar("__depends", "__base_depends", self.configuration.data) - -            self.parser = CookerParser(self, filelist, masked) -            self.cookerState = cookerParsing - -        if not self.parser.parse_next(): -            bb.msg.debug(1, bb.msg.domain.Collection, "parsing complete") -            self.buildDepgraph() -            self.cookerState = cookerParsed -            return None - -        return True - -    def checkPackages(self, pkgs_to_build): - -        if len(pkgs_to_build) == 0: -            raise NothingToBuild - -        if 'world' in pkgs_to_build: -            self.buildWorldTargetList() -            pkgs_to_build.remove('world') -            for t in self.status.world_target: -                pkgs_to_build.append(t) - -        return pkgs_to_build - -    def get_bbfiles( self, path = os.getcwd() ): -        """Get list of default .bb files by reading out the current directory""" -        contents = os.listdir(path) -        bbfiles = [] -        for f in contents: -            (root, ext) = os.path.splitext(f) -            if ext == ".bb": -                bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f))) -        return bbfiles - -    def find_bbfiles( self, path ): -        """Find all the .bb files in a directory""" -        from os.path import join - -        found = [] -        for dir, dirs, files in os.walk(path): -            for ignored in ('SCCS', 'CVS', '.svn'): -                if ignored in dirs: -                    dirs.remove(ignored) -            found += [join(dir,f) for f in files if f.endswith('.bb')] - -        return found - -    def collect_bbfiles( self ): -        """Collect all available .bb build files""" -        parsed, cached, skipped, masked = 0, 0, 0, 0 -        self.bb_cache = bb.cache.init(self) - -        files = (data.getVar( "BBFILES", self.configuration.data, 1 ) or "").split() -        data.setVar("BBFILES", " ".join(files), self.configuration.data) - -        if not len(files): -            files = self.get_bbfiles() - -        if not len(files): -            bb.msg.error(bb.msg.domain.Collection, "no files to build.") - -        newfiles = [] -        for f in files: -            if os.path.isdir(f): -                dirfiles = self.find_bbfiles(f) -                if dirfiles: -                    newfiles += dirfiles -                    continue -            else: -                globbed = glob.glob(f) -                if not globbed and os.path.exists(f): -                    globbed = [f] -                newfiles += globbed - -        bbmask = bb.data.getVar('BBMASK', self.configuration.data, 1) - -        if not bbmask: -            return (newfiles, 0) - -        try: -            bbmask_compiled = re.compile(bbmask) -        except sre_constants.error: -            bb.msg.fatal(bb.msg.domain.Collection, "BBMASK is not a valid regular expression.") - -        finalfiles = [] -        for f in newfiles: -            if bbmask_compiled.search(f): -                bb.msg.debug(1, bb.msg.domain.Collection, "skipping masked file %s" % f) -                masked += 1 -                continue -            finalfiles.append(f) - -        return (finalfiles, masked) - -    def serve(self): - -        # Empty the environment. The environment will be populated as -        # necessary from the data store. -        bb.utils.empty_environment() - -        if self.configuration.profile: -            try: -                import cProfile as profile -            except: -                import profile - -            profile.runctx("self.server.serve_forever()", globals(), locals(), "profile.log") - -            # Redirect stdout to capture profile information -            pout = open('profile.log.processed', 'w') -            so = sys.stdout.fileno() -            os.dup2(pout.fileno(), so) - -            import pstats -            p = pstats.Stats('profile.log') -            p.sort_stats('time') -            p.print_stats() -            p.print_callers() -            p.sort_stats('cumulative') -            p.print_stats() - -            os.dup2(so, pout.fileno()) -            pout.flush() -            pout.close() -        else: -            self.server.serve_forever() -         -        bb.event.fire(CookerExit(), self.configuration.event_data) -         -class CookerExit(bb.event.Event): -    """ -    Notify clients of the Cooker shutdown -    """ - -    def __init__(self): -        bb.event.Event.__init__(self) - -class CookerParser: -    def __init__(self, cooker, filelist, masked): -        # Internal data -        self.filelist = filelist -        self.cooker = cooker - -        # Accounting statistics -        self.parsed = 0 -        self.cached = 0 -        self.error = 0 -        self.masked = masked -        self.total = len(filelist) - -        self.skipped = 0 -        self.virtuals = 0 - -        # Pointer to the next file to parse -        self.pointer = 0 - -    def parse_next(self): -        if self.pointer < len(self.filelist): -            f = self.filelist[self.pointer] -            cooker = self.cooker - -            try: -                fromCache, skipped, virtuals = cooker.bb_cache.loadData(f, cooker.configuration.data, cooker.status) -                if fromCache: -                    self.cached += 1 -                else: -                    self.parsed += 1 - -                self.skipped += skipped -                self.virtuals += virtuals - -            except IOError, e: -                self.error += 1 -                cooker.bb_cache.remove(f) -                bb.msg.error(bb.msg.domain.Collection, "opening %s: %s" % (f, e)) -                pass -            except KeyboardInterrupt: -                cooker.bb_cache.remove(f) -                cooker.bb_cache.sync() -                raise -            except Exception, e: -                self.error += 1 -                cooker.bb_cache.remove(f) -                bb.msg.error(bb.msg.domain.Collection, "%s while parsing %s" % (e, f)) -            except: -                cooker.bb_cache.remove(f) -                raise -            finally: -                bb.event.fire(bb.event.ParseProgress(self.cached, self.parsed, self.skipped, self.masked, self.virtuals, self.error, self.total), cooker.configuration.event_data) - -            self.pointer += 1 - -        if self.pointer >= self.total: -            cooker.bb_cache.sync() -            if self.error > 0: -                raise ParsingErrorsFound -            return False -        return True - | 
