diff options
author | Richard Purdie <richard@openedhand.com> | 2007-04-01 15:04:49 +0000 |
---|---|---|
committer | Richard Purdie <richard@openedhand.com> | 2007-04-01 15:04:49 +0000 |
commit | 7371e6323c3fb6b0545712e3cf84606644073e77 (patch) | |
tree | e08f25669ec0f0e9d11334909f3b68c0ab6aca19 /bitbake/lib/bb/cooker.py | |
parent | 8b36dc217443aeeec8493d39561d2bb010336774 (diff) | |
download | openembedded-core-7371e6323c3fb6b0545712e3cf84606644073e77.tar.gz openembedded-core-7371e6323c3fb6b0545712e3cf84606644073e77.tar.bz2 openembedded-core-7371e6323c3fb6b0545712e3cf84606644073e77.tar.xz openembedded-core-7371e6323c3fb6b0545712e3cf84606644073e77.zip |
bitbake: Update to 1.8.1 (inc. various bug fixes, epoch support)
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@1419 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'bitbake/lib/bb/cooker.py')
-rw-r--r-- | bitbake/lib/bb/cooker.py | 318 |
1 files changed, 153 insertions, 165 deletions
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py index 8a9c58863..4b2a90613 100644 --- a/bitbake/lib/bb/cooker.py +++ b/bitbake/lib/bb/cooker.py @@ -31,29 +31,6 @@ import itertools parsespin = itertools.cycle( r'|/-\\' ) #============================================================================# -# BBStatistics -#============================================================================# -class BBStatistics: - """ - Manage build statistics for one run - """ - def __init__(self ): - self.attempt = 0 - self.success = 0 - self.fail = 0 - self.deps = 0 - - def show( self ): - print "Build statistics:" - print " Attempted builds: %d" % self.attempt - if self.fail: - print " Failed builds: %d" % self.fail - if self.deps: - print " Dependencies not satisfied: %d" % self.deps - if self.fail or self.deps: return 1 - else: return 0 - -#============================================================================# # BBCooker #============================================================================# class BBCooker: @@ -61,43 +38,61 @@ class BBCooker: Manages one bitbake build run """ - Statistics = BBStatistics # make it visible from the shell - - def __init__( self ): - self.build_cache_fail = [] - self.build_cache = [] - self.stats = BBStatistics() + def __init__(self, configuration): self.status = None self.cache = None self.bb_cache = None + 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() + + 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) or "build" + + # + # 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) + def tryBuildPackage(self, fn, item, task, the_data, build_depends): """ Build one task of a package, optionally build following task depends """ bb.event.fire(bb.event.PkgStarted(item, the_data)) try: - self.stats.attempt += 1 if not build_depends: bb.data.setVarFlag('do_%s' % task, 'dontrundeps', 1, the_data) if not self.configuration.dry_run: bb.build.exec_task('do_%s' % task, the_data) bb.event.fire(bb.event.PkgSucceeded(item, the_data)) - self.build_cache.append(fn) return True except bb.build.FuncFailed: - self.stats.fail += 1 bb.msg.error(bb.msg.domain.Build, "task stack execution failed") bb.event.fire(bb.event.PkgFailed(item, the_data)) - self.build_cache_fail.append(fn) raise except bb.build.EventException, e: - self.stats.fail += 1 event = e.args[1] bb.msg.error(bb.msg.domain.Build, "%s event exception, aborting" % bb.event.getName(event)) bb.event.fire(bb.event.PkgFailed(item, the_data)) - self.build_cache_fail.append(fn) raise def tryBuild( self, fn, build_depends): @@ -112,12 +107,11 @@ class BBCooker: item = self.status.pkg_fn[fn] if bb.build.stamp_is_current('do_%s' % self.configuration.cmd, the_data): - self.build_cache.append(fn) return True return self.tryBuildPackage(fn, item, self.configuration.cmd, the_data, build_depends) - def showVersions( self ): + def showVersions(self): pkg_pn = self.status.pkg_pn preferred_versions = {} latest_versions = {} @@ -136,11 +130,11 @@ class BBCooker: latest = latest_versions[p] if pref != latest: - prefstr = pref[0][0] + "-" + pref[0][1] + prefstr = pref[0][0] + ":" + pref[0][1] + '-' + pref[0][2] else: prefstr = "" - print "%-30s %20s %20s" % (p, latest[0][0] + "-" + latest[0][1], + print "%-30s %20s %20s" % (p, latest[0][0] + ":" + latest[0][1] + "-" + latest[0][2], prefstr) @@ -192,8 +186,8 @@ class BBCooker: taskdata.add_unresolved(localdata, self.status) except bb.providers.NoProvider: sys.exit(1) - rq = bb.runqueue.RunQueue() - rq.prepare_runqueue(self, self.configuration.data, self.status, taskdata, runlist) + rq = bb.runqueue.RunQueue(self, self.configuration.data, self.status, taskdata, runlist) + rq.prepare_runqueue() seen_fnids = [] depends_file = file('depends.dot', 'w' ) @@ -371,98 +365,138 @@ class BBCooker: 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 cook(self, configuration): + def buildFile(self, buildfile): """ - We are building stuff here. We do the building - from here. By default we try to execute task - build. + Build the file matching regexp buildfile """ - self.configuration = configuration + bf = os.path.abspath(buildfile) + try: + os.stat(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) + 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) + sys.exit(1) + bf = matches[0] - if self.configuration.verbose: - bb.msg.set_verbose(True) + bbfile_data = bb.parse.handle(bf, self.configuration.data) - if self.configuration.debug: - bb.msg.set_debug_level(self.configuration.debug) + # Remove stamp for target if force mode active + if self.configuration.force: + bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (self.configuration.cmd, bf)) + bb.build.del_stamp('do_%s' % self.configuration.cmd, bbfile_data) + + item = bb.data.getVar('PN', bbfile_data, 1) + try: + self.tryBuildPackage(bf, item, self.configuration.cmd, bbfile_data, True) + except bb.build.EventException: + bb.msg.error(bb.msg.domain.Build, "Build of '%s' failed" % item ) + + sys.exit(0) + + def buildTargets(self, targets): + """ + Attempt to build the targets specified + """ + + 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 = [] + try: + for k in targets: + taskdata.add_provider(localdata, self.status, k) + runlist.append([k, "do_%s" % self.configuration.cmd]) + taskdata.add_unresolved(localdata, self.status) + except bb.providers.NoProvider: + sys.exit(1) + + rq = bb.runqueue.RunQueue(self, self.configuration.data, self.status, taskdata, runlist) + rq.prepare_runqueue() + try: + failures = rq.execute_runqueue() + except runqueue.TaskFailure, fnids: + for fnid in fnids: + bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid]) + sys.exit(1) + bb.event.fire(bb.event.BuildCompleted(buildname, targets, self.configuration.event_data, failures)) + + sys.exit(0) + + def updateCache(self): + # Import Psyco if available and not disabled + 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( self.parse_bbfiles ) else: - bb.msg.set_debug_level(0) + bb.msg.note(1, bb.msg.domain.Collection, "You have disabled Psyco. This decreases performance.") - if self.configuration.debug_domains: - bb.msg.set_debug_domains(self.configuration.debug_domains) + self.status = bb.cache.CacheData() - self.configuration.data = bb.data.init() + ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or "" + self.status.ignored_dependencies = Set( ignore.split() ) - for f in self.configuration.file: - self.parseConfigurationFile( f ) + self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) ) - self.parseConfigurationFile( os.path.join( "conf", "bitbake.conf" ) ) + bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files") + (filelist, masked) = self.collect_bbfiles() + self.parse_bbfiles(filelist, masked, self.myProgressCallback) + bb.msg.debug(1, bb.msg.domain.Collection, "parsing complete") - if not self.configuration.cmd: - self.configuration.cmd = bb.data.getVar("BB_DEFAULT_TASK", self.configuration.data) or "build" + self.buildDepgraph() - # - # 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) + def cook(self): + """ + We are building stuff here. We do the building + from here. By default we try to execute task + build. + """ if self.configuration.show_environment: self.showEnvironment() sys.exit( 0 ) - # inject custom variables - 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) - - buildname = bb.data.getVar("BUILDNAME", self.configuration.data) + self.buildSetVars() if self.configuration.interactive: self.interactiveMode() if self.configuration.buildfile is not None: - bf = os.path.abspath( self.configuration.buildfile ) - try: - os.stat(bf) - except OSError: - (filelist, masked) = self.collect_bbfiles() - regexp = re.compile(self.configuration.buildfile) - matches = [] - for f in filelist: - if regexp.search(f) and os.path.isfile(f): - bf = f - matches.append(f) - if len(matches) != 1: - bb.msg.error(bb.msg.domain.Parsing, "Unable to match %s (%s matches found):" % (self.configuration.buildfile, len(matches))) - for f in matches: - bb.msg.error(bb.msg.domain.Parsing, " %s" % f) - sys.exit(1) - bf = matches[0] - - bbfile_data = bb.parse.handle(bf, self.configuration.data) - - # Remove stamp for target if force mode active - if self.configuration.force: - bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (self.configuration.cmd, bf)) - bb.build.del_stamp('do_%s' % self.configuration.cmd, bbfile_data) - - item = bb.data.getVar('PN', bbfile_data, 1) - try: - self.tryBuildPackage(bf, item, self.configuration.cmd, bbfile_data, True) - except bb.build.EventException: - bb.msg.error(bb.msg.domain.Build, "Build of '%s' failed" % item ) - - sys.exit( self.stats.show() ) + return self.buildFile(self.configuration.buildfile) # initialise the parsing status now we know we will need deps - self.status = bb.cache.CacheData() + self.updateCache() - ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or "" - self.status.ignored_dependencies = Set( ignore.split() ) - - self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) ) + if self.configuration.parse_only: + bb.msg.note(1, bb.msg.domain.Collection, "Requested parsing .bb files only. Exiting.") + return 0 pkgs_to_build = self.configuration.pkgs_to_build @@ -475,30 +509,7 @@ class BBCooker: print "for usage information." sys.exit(0) - # Import Psyco if available and not disabled - 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( self.parse_bbfiles ) - else: - bb.msg.note(1, bb.msg.domain.Collection, "You have disabled Psyco. This decreases performance.") - try: - bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files") - (filelist, masked) = self.collect_bbfiles() - self.parse_bbfiles(filelist, masked, self.myProgressCallback) - bb.msg.debug(1, bb.msg.domain.Collection, "parsing complete") - print - if self.configuration.parse_only: - bb.msg.note(1, bb.msg.domain.Collection, "Requested parsing .bb files only. Exiting.") - return - - - self.buildDepgraph() - if self.configuration.show_versions: self.showVersions() sys.exit( 0 ) @@ -512,34 +523,7 @@ class BBCooker: self.generateDotGraph( pkgs_to_build, self.configuration.ignored_dot_deps ) sys.exit( 0 ) - bb.event.fire(bb.event.BuildStarted(buildname, pkgs_to_build, 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 = [] - try: - for k in pkgs_to_build: - taskdata.add_provider(localdata, self.status, k) - runlist.append([k, "do_%s" % self.configuration.cmd]) - taskdata.add_unresolved(localdata, self.status) - except bb.providers.NoProvider: - sys.exit(1) - - rq = bb.runqueue.RunQueue() - rq.prepare_runqueue(self, self.configuration.data, self.status, taskdata, runlist) - try: - failures = rq.execute_runqueue(self, self.configuration.data, self.status, taskdata, runlist) - except runqueue.TaskFailure, fnids: - for fnid in fnids: - bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid]) - sys.exit(1) - bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, self.configuration.event_data, failures)) - - sys.exit( self.stats.show() ) + return self.buildTargets(pkgs_to_build) except KeyboardInterrupt: bb.msg.note(1, bb.msg.domain.Collection, "KeyboardInterrupt - Build not completed.") @@ -556,13 +540,17 @@ class BBCooker: return bbfiles def find_bbfiles( self, path ): - """Find all the .bb files in a directory (uses find)""" - findcmd = 'find ' + path + ' -name *.bb | grep -v SCCS/' - try: - finddata = os.popen(findcmd) - except OSError: - return [] - return finddata.readlines() + """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""" |