2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
5 # Copyright (C) 2003, 2004 Chris Larson
6 # Copyright (C) 2003, 2004 Phil Blundell
7 # Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
8 # Copyright (C) 2005 Holger Hans Peter Freyther
9 # Copyright (C) 2005 ROAD GmbH
10 # Copyright (C) 2006 Richard Purdie
12 # This program is free software; you can redistribute it and/or modify it under
13 # the terms of the GNU General Public License as published by the Free Software
14 # Foundation; either version 2 of the License, or (at your option) any later
17 # This program is distributed in the hope that it will be useful, but WITHOUT
18 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License along with
22 # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23 # Place, Suite 330, Boston, MA 02111-1307 USA.
25 import sys, os, getopt, glob, copy, os.path, re, time
26 sys.path.insert(0,os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
28 from bb import utils, data, parse, event, cache, providers, taskdata, runqueue
30 import itertools, optparse
32 parsespin = itertools.cycle( r'|/-\\' )
36 #============================================================================#
38 #============================================================================#
41 Manage build statistics for one run
50 print "Build statistics:"
51 print " Attempted builds: %d" % self.attempt
53 print " Failed builds: %d" % self.fail
55 print " Dependencies not satisfied: %d" % self.deps
56 if self.fail or self.deps: return 1
60 #============================================================================#
62 #============================================================================#
63 class BBConfiguration( object ):
65 Manages build options and configurations for one run
67 def __init__( self, options ):
68 for key, val in options.__dict__.items():
69 setattr( self, key, val )
71 #============================================================================#
73 #============================================================================#
76 Manages one bitbake build run
79 Statistics = BBStatistics # make it visible from the shell
82 self.build_cache_fail = []
84 self.stats = BBStatistics()
90 def tryBuildPackage(self, fn, item, task, the_data, build_depends):
92 Build one task of a package, optionally build following task depends
94 bb.event.fire(bb.event.PkgStarted(item, the_data))
96 self.stats.attempt += 1
97 if self.configuration.force:
98 bb.data.setVarFlag('do_%s' % task, 'force', 1, the_data)
100 bb.data.setVarFlag('do_%s' % task, 'dontrundeps', 1, the_data)
101 if not self.configuration.dry_run:
102 bb.build.exec_task('do_%s' % task, the_data)
103 bb.event.fire(bb.event.PkgSucceeded(item, the_data))
104 self.build_cache.append(fn)
106 except bb.build.FuncFailed:
108 bb.msg.error(bb.msg.domain.Build, "task stack execution failed")
109 bb.event.fire(bb.event.PkgFailed(item, the_data))
110 self.build_cache_fail.append(fn)
112 except bb.build.EventException, e:
115 bb.msg.error(bb.msg.domain.Build, "%s event exception, aborting" % bb.event.getName(event))
116 bb.event.fire(bb.event.PkgFailed(item, the_data))
117 self.build_cache_fail.append(fn)
120 def tryBuild( self, fn, build_depends):
122 Build a provider and its dependencies.
123 build_depends is a list of previous build dependencies (not runtime)
124 If build_depends is empty, we're dealing with a runtime depends
127 the_data = self.bb_cache.loadDataFull(fn, self)
129 item = self.status.pkg_fn[fn]
131 if bb.build.stamp_is_current('do_%s' % self.configuration.cmd, the_data):
132 self.build_cache.append(fn)
135 return self.tryBuildPackage(fn, item, self.configuration.cmd, the_data, build_depends)
137 def showVersions( self ):
138 pkg_pn = self.status.pkg_pn
139 preferred_versions = {}
143 for pn in pkg_pn.keys():
144 (last_ver,last_file,pref_ver,pref_file) = bb.providers.findBestProvider(pn, self.configuration.data, self.status)
145 preferred_versions[pn] = (pref_ver, pref_file)
146 latest_versions[pn] = (last_ver, last_file)
148 pkg_list = pkg_pn.keys()
152 pref = preferred_versions[p]
153 latest = latest_versions[p]
156 prefstr = pref[0][0] + "-" + pref[0][1]
160 print "%-30s %20s %20s" % (p, latest[0][0] + "-" + latest[0][1],
164 def showEnvironment( self ):
165 """Show the outer or per-package environment"""
166 if self.configuration.buildfile:
168 self.bb_cache = bb.cache.init(self)
170 self.configuration.data = self.bb_cache.loadDataFull(self.configuration.buildfile, self)
172 bb.msg.fatal(bb.msg.domain.Parsing, "Unable to read %s: %s" % ( self.configuration.buildfile, e ))
174 bb.msg.fatal(bb.msg.domain.Parsing, "%s" % e)
175 # emit variables and shell functions
177 data.update_data( self.configuration.data )
178 data.emit_env(sys.__stdout__, self.configuration.data, True)
180 bb.msg.fatal(bb.msg.domain.Parsing, "%s" % e)
181 # emit the metadata which isnt valid shell
182 for e in self.configuration.data.keys():
183 if data.getVarFlag( e, 'python', self.configuration.data ):
184 sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, data.getVar(e, self.configuration.data, 1)))
186 def generateDotGraph( self, pkgs_to_build, ignore_deps ):
188 Generate two graphs one for the DEPENDS and RDEPENDS. The current
189 implementation creates crappy graphs ;)
191 pkgs_to_build A list of packages that needs to be built
192 ignore_deps A list of names where processing of dependencies
193 should be stopped. e.g. dependencies that get
196 def myFilterProvider( providers, item):
198 Take a list of providers and filter according to environment
199 variables. In contrast to filterProviders we do not discriminate
200 and take PREFERRED_PROVIDER into account.
203 preferred_versions = {}
205 # Collate providers by PN
208 pn = self.status.pkg_fn[p]
213 bb.msg.debug(1, bb.msg.domain.Provider, "providers for %s are: %s" % (item, pkg_pn.keys()))
215 for pn in pkg_pn.keys():
216 preferred_versions[pn] = bb.providers.findBestProvider(pn, self.configuration.data, self.status, pkg_pn)[2:4]
217 eligible.append(preferred_versions[pn][1])
220 if p in self.build_cache_fail:
221 bb.msg.debug(1, bb.msg.domain.Provider, "rejecting already-failed %s" % p)
224 if len(eligible) == 0:
225 bb.msg.error(bb.msg.domain.Provider, "no eligible providers for %s" % item)
228 prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % item, self.configuration.data, 1)
230 # try the preferred provider first
233 if prefervar == self.status.pkg_fn[p]:
234 bb.msg.note(1, bb.msg.domain.Provider, "Selecting PREFERRED_PROVIDER %s" % prefervar)
236 eligible = [p] + eligible
241 # try to avoid adding the same rdepends over an over again
246 def add_depends(package_list):
248 Add all depends of all packages from this list
250 for package in package_list:
251 if package in seen_depends or package in ignore_deps:
254 seen_depends.append( package )
255 if not package in self.status.providers:
257 We have not seen this name -> error in
260 bb.msg.note(1, bb.msg.domain.Depends, "ERROR with provider: %(package)s" % vars() )
261 print >> depends_file, '"%(package)s" -> ERROR' % vars()
264 # get all providers for this package
265 providers = self.status.providers[package]
267 # now let us find the bestProvider for it
268 fn = myFilterProvider(providers, package)[0]
270 depends = bb.utils.explode_deps(self.bb_cache.getVar('DEPENDS', fn, True) or "")
271 version = self.bb_cache.getVar('PV', fn, True ) + '-' + self.bb_cache.getVar('PR', fn, True)
272 add_depends ( depends )
274 # now create the node
275 print >> depends_file, '"%(package)s" [label="%(package)s\\n%(version)s"]' % vars()
277 depends = filter( (lambda x: x not in ignore_deps), depends )
278 for depend in depends:
279 print >> depends_file, '"%(package)s" -> "%(depend)s"' % vars()
282 def add_all_depends( the_depends, the_rdepends ):
284 Add both DEPENDS and RDEPENDS. RDEPENDS will get dashed
287 package_list = the_depends + the_rdepends
288 for package in package_list:
289 if package in seen_rdepends or package in ignore_deps:
292 seen_rdepends.append( package )
294 # Let us find out if the package is a DEPENDS or RDEPENDS
295 # and we will set 'providers' with the avilable providers
297 if package in the_depends:
298 if not package in self.status.providers:
299 bb.msg.note(1, bb.msg.domain.Depends, "ERROR with provider: %(package)s" % vars() )
300 print >> alldepends_file, '"%(package)s" -> ERROR' % vars()
303 providers = self.status.providers[package]
304 elif package in the_rdepends:
305 if len(bb.providers.getRuntimeProviders(self.status, package)) == 0:
306 bb.msg.note(1, bb.msg.domain.Depends, "ERROR with rprovider: %(package)s" % vars() )
307 print >> alldepends_file, '"%(package)s" -> ERROR [style="dashed"]' % vars()
310 providers = bb.providers.getRuntimeProviders(self.status, package)
312 # something went wrong...
313 print "Complete ERROR! %s" % package
316 # now let us find the bestProvider for it
317 fn = myFilterProvider(providers, package)[0]
319 # Now we have a filename let us get the depends and RDEPENDS of it
320 depends = bb.utils.explode_deps(self.bb_cache.getVar('DEPENDS', fn, True) or "")
321 if fn in self.status.rundeps and package in self.status.rundeps[fn]:
322 rdepends= self.status.rundeps[fn][package].keys()
325 version = self.bb_cache.getVar('PV', fn, True ) + '-' + self.bb_cache.getVar('PR', fn, True)
327 # handle all the depends and rdepends of package
328 add_all_depends ( depends, rdepends )
330 # now create the node using package name
331 print >> alldepends_file, '"%(package)s" [label="%(package)s\\n%(version)s"]' % vars()
333 # remove the stuff we want to ignore and add the edges
334 depends = filter( (lambda x: x not in ignore_deps), depends )
335 rdepends = filter( (lambda x: x not in ignore_deps), rdepends )
336 for depend in depends:
337 print >> alldepends_file, '"%(package)s" -> "%(depend)s"' % vars()
338 for depend in rdepends:
339 print >> alldepends_file, '"%(package)s" -> "%(depend)s" [style=dashed]' % vars()
343 depends_file = file('depends.dot', 'w' )
344 print >> depends_file, "digraph depends {"
345 add_depends( pkgs_to_build )
346 print >> depends_file, "}"
348 # Add all depends now
349 alldepends_file = file('alldepends.dot', 'w' )
350 print >> alldepends_file, "digraph alldepends {"
351 add_all_depends( pkgs_to_build, [] )
352 print >> alldepends_file, "}"
354 def buildDepgraph( self ):
355 all_depends = self.status.all_depends
356 pn_provides = self.status.pn_provides
358 localdata = data.createCopy(self.configuration.data)
359 bb.data.update_data(localdata)
361 def calc_bbfile_priority(filename):
362 for (regex, pri) in self.status.bbfile_config_priorities:
363 if regex.match(filename):
367 # Handle PREFERRED_PROVIDERS
368 for p in (bb.data.getVar('PREFERRED_PROVIDERS', localdata, 1) or "").split():
369 (providee, provider) = p.split(':')
370 if providee in self.status.preferred and self.status.preferred[providee] != provider:
371 bb.msg.error(bb.msg.domain.Provider, "conflicting preferences for %s: both %s and %s specified" % (providee, provider, self.status.preferred[providee]))
372 self.status.preferred[providee] = provider
374 # Calculate priorities for each file
375 for p in self.status.pkg_fn.keys():
376 self.status.bbfile_priority[p] = calc_bbfile_priority(p)
378 def buildWorldTargetList(self):
380 Build package list for "bitbake world"
382 all_depends = self.status.all_depends
383 pn_provides = self.status.pn_provides
384 bb.msg.debug(1, bb.msg.domain.Parsing, "collating packages for \"world\"")
385 for f in self.status.possible_world:
387 pn = self.status.pkg_fn[f]
389 for p in pn_provides[pn]:
390 if p.startswith('virtual/'):
391 bb.msg.debug(2, bb.msg.domain.Parsing, "World build skipping %s due to %s provider starting with virtual/" % (f, p))
394 for pf in self.status.providers[p]:
395 if self.status.pkg_fn[pf] != pn:
396 bb.msg.debug(2, bb.msg.domain.Parsing, "World build skipping %s due to both us and %s providing %s" % (f, pf, p))
400 self.status.world_target.add(pn)
402 # drop reference count now
403 self.status.possible_world = None
404 self.status.all_depends = None
406 def myProgressCallback( self, x, y, f, bb_cache, from_cache ):
407 # feed the status with new input
409 bb_cache.handle_data(f, self.status)
411 if os.isatty(sys.stdout.fileno()):
412 sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
416 sys.stdout.write("Parsing .bb files, please wait...")
419 sys.stdout.write("done.")
422 def interactiveMode( self ):
423 """Drop off into a shell"""
426 except ImportError, details:
427 bb.msg.fatal(bb.msg.domain.Parsing, "Sorry, shell not available (%s)" % details )
429 bb.data.update_data( self.configuration.data )
433 def parseConfigurationFile( self, afile ):
435 self.configuration.data = bb.parse.handle( afile, self.configuration.data )
437 # Add the handlers we inherited by INHERIT
438 # we need to do this manually as it is not guranteed
439 # we will pick up these classes... as we only INHERIT
440 # on .inc and .bb files but not on .conf
441 data = bb.data.createCopy( self.configuration.data )
442 inherits = ["base"] + (bb.data.getVar('INHERIT', data, True ) or "").split()
443 for inherit in inherits:
444 data = bb.parse.handle( os.path.join('classes', '%s.bbclass' % inherit ), data, True )
446 # FIXME: This assumes that we included at least one .inc file
447 for var in bb.data.keys(data):
448 if bb.data.getVarFlag(var, 'handler', data):
449 bb.event.register(var,bb.data.getVar(var, data))
452 bb.msg.fatal(bb.msg.domain.Parsing, "Unable to open %s" % afile )
453 except bb.parse.ParseError, details:
454 bb.msg.fatal(bb.msg.domain.Parsing, "Unable to parse %s (%s)" % (afile, details) )
456 def handleCollections( self, collections ):
457 """Handle collections"""
459 collection_list = collections.split()
460 for c in collection_list:
461 regex = bb.data.getVar("BBFILE_PATTERN_%s" % c, self.configuration.data, 1)
463 bb.msg.error(bb.msg.domain.Parsing, "BBFILE_PATTERN_%s not defined" % c)
465 priority = bb.data.getVar("BBFILE_PRIORITY_%s" % c, self.configuration.data, 1)
467 bb.msg.error(bb.msg.domain.Parsing, "BBFILE_PRIORITY_%s not defined" % c)
470 cre = re.compile(regex)
472 bb.msg.error(bb.msg.domain.Parsing, "BBFILE_PATTERN_%s \"%s\" is not a valid regular expression" % (c, regex))
476 self.status.bbfile_config_priorities.append((cre, pri))
478 bb.msg.error(bb.msg.domain.Parsing, "invalid value for BBFILE_PRIORITY_%s: \"%s\"" % (c, priority))
481 def cook( self, configuration, args ):
483 We are building stuff here. We do the building
484 from here. By default we try to execute task
488 self.configuration = configuration
490 if self.configuration.verbose:
491 bb.msg.set_verbose(True)
493 if self.configuration.debug:
494 bb.msg.set_debug_level(self.configuration.debug)
496 bb.msg.set_debug_level(0)
498 if self.configuration.debug_domains:
499 bb.msg.set_debug_domains(self.configuration.debug_domains)
501 self.configuration.data = bb.data.init()
503 for f in self.configuration.file:
504 self.parseConfigurationFile( f )
506 self.parseConfigurationFile( os.path.join( "conf", "bitbake.conf" ) )
508 if not self.configuration.cmd:
509 self.configuration.cmd = bb.data.getVar("BB_DEFAULT_TASK", self.configuration.data)
511 # For backwards compatibility - REMOVE ME
512 if not self.configuration.cmd:
513 self.configuration.cmd = "build"
516 # Special updated configuration we use for firing events
518 self.configuration.event_data = bb.data.createCopy(self.configuration.data)
519 bb.data.update_data(self.configuration.event_data)
521 if self.configuration.show_environment:
522 self.showEnvironment()
525 # inject custom variables
526 if not bb.data.getVar("BUILDNAME", self.configuration.data):
527 bb.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), self.configuration.data)
528 bb.data.setVar("BUILDSTART", time.strftime('%m/%d/%Y %H:%M:%S',time.gmtime()),self.configuration.data)
530 buildname = bb.data.getVar("BUILDNAME", self.configuration.data)
532 if self.configuration.interactive:
533 self.interactiveMode()
535 if self.configuration.buildfile is not None:
536 bf = os.path.abspath( self.configuration.buildfile )
538 bbfile_data = bb.parse.handle(bf, self.configuration.data)
540 bb.msg.fatal(bb.msg.domain.Parsing, "Unable to open %s" % bf)
542 item = bb.data.getVar('PN', bbfile_data, 1)
544 self.tryBuildPackage(bf, item, self.configuration.cmd, bbfile_data, True)
545 except bb.build.EventException:
546 bb.msg.error(bb.msg.domain.Build, "Build of '%s' failed" % item )
548 sys.exit( self.stats.show() )
550 # initialise the parsing status now we know we will need deps
551 self.status = bb.cache.CacheData()
553 ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or ""
554 self.status.ignored_dependencies = Set( ignore.split() )
556 self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) )
560 if not pkgs_to_build:
562 pkgs_to_build.extend(args)
563 if not pkgs_to_build:
564 bbpkgs = bb.data.getVar('BBPKGS', self.configuration.data, 1)
566 pkgs_to_build = bbpkgs.split()
567 if not pkgs_to_build and not self.configuration.show_versions \
568 and not self.configuration.interactive \
569 and not self.configuration.show_environment:
570 print "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help'"
571 print "for usage information."
574 # Import Psyco if available and not disabled
575 if not self.configuration.disable_psyco:
579 bb.msg.note(1, bb.msg.domain.Collection, "Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance.")
581 psyco.bind( self.collect_bbfiles )
583 bb.msg.note(1, bb.msg.domain.Collection, "You have disabled Psyco. This decreases performance.")
586 bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files")
587 self.collect_bbfiles( self.myProgressCallback )
588 bb.msg.debug(1, bb.msg.domain.Collection, "parsing complete")
590 if self.configuration.parse_only:
591 bb.msg.note(1, bb.msg.domain.Collection, "Requested parsing .bb files only. Exiting.")
597 if self.configuration.show_versions:
600 if 'world' in pkgs_to_build:
601 self.buildWorldTargetList()
602 pkgs_to_build.remove('world')
603 for t in self.status.world_target:
604 pkgs_to_build.append(t)
606 if self.configuration.dot_graph:
607 self.generateDotGraph( pkgs_to_build, self.configuration.ignored_dot_deps )
610 bb.event.fire(bb.event.BuildStarted(buildname, pkgs_to_build, self.configuration.event_data))
612 taskdata = bb.taskdata.TaskData()
616 for k in pkgs_to_build:
617 taskdata.add_provider(self.configuration.data, self.status, k)
618 runlist.append([k, "do_%s" % self.configuration.cmd])
619 taskdata.add_unresolved(self.configuration.data, self.status)
620 except bb.providers.NoProvider:
623 rq = bb.runqueue.RunQueue()
624 rq.prepare_runqueue(self.configuration.data, self.status, taskdata, runlist)
626 failures = rq.execute_runqueue(self, self.configuration.data, self.status, taskdata, runlist)
627 except runqueue.TaskFailure, (fnid, fn, taskname):
628 bb.msg.error(bb.msg.domain.Build, "'%s, %s' failed" % (fn, taskname))
631 bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, self.configuration.event_data, failures))
633 sys.exit( self.stats.show() )
635 except KeyboardInterrupt:
636 bb.msg.note(1, bb.msg.domain.Collection, "KeyboardInterrupt - Build not completed.")
639 def get_bbfiles( self, path = os.getcwd() ):
640 """Get list of default .bb files by reading out the current directory"""
641 contents = os.listdir(path)
644 (root, ext) = os.path.splitext(f)
646 bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
649 def find_bbfiles( self, path ):
650 """Find all the .bb files in a directory (uses find)"""
651 findcmd = 'find ' + path + ' -name *.bb | grep -v SCCS/'
653 finddata = os.popen(findcmd)
656 return finddata.readlines()
658 def collect_bbfiles( self, progressCallback ):
659 """Collect all available .bb build files"""
660 self.cb = progressCallback
661 parsed, cached, skipped, masked = 0, 0, 0, 0
662 self.bb_cache = bb.cache.init(self)
664 files = (data.getVar( "BBFILES", self.configuration.data, 1 ) or "").split()
665 data.setVar("BBFILES", " ".join(files), self.configuration.data)
668 files = self.get_bbfiles()
671 bb.msg.error(bb.msg.domain.Collection, "no files to build.")
676 dirfiles = self.find_bbfiles(f)
680 newfiles += glob.glob(f) or [ f ]
682 bbmask = bb.data.getVar('BBMASK', self.configuration.data, 1) or ""
684 bbmask_compiled = re.compile(bbmask)
685 except sre_constants.error:
686 bb.msg.fatal(bb.msg.domain.Collection, "BBMASK is not a valid regular expression.")
688 for i in xrange( len( newfiles ) ):
690 if bbmask and bbmask_compiled.search(f):
691 bb.msg.debug(1, bb.msg.domain.Collection, "bbmake: skipping %s" % f, f)
694 bb.msg.debug(1, bb.msg.domain.Collection, "bbmake: parsing %s" % f, f)
696 # read a file's metadata
698 fromCache, skip = self.bb_cache.loadData(f, self)
701 bb.msg.debug(2, bb.msg.domain.Collection, "Skipping %s" % f, f)
702 self.bb_cache.skip(f)
704 elif fromCache: cached += 1
708 # allow metadata files to add items to BBFILES
709 #data.update_data(self.pkgdata[f])
710 addbbfiles = self.bb_cache.getVar('BBFILES', f, False) or None
712 for aof in addbbfiles.split():
713 if not files.count(aof):
714 if not os.path.isabs(aof):
715 aof = os.path.join(os.path.dirname(f),aof)
718 # now inform the caller
719 if self.cb is not None:
720 self.cb( i + 1, len( newfiles ), f, self.bb_cache, fromCache )
723 self.bb_cache.remove(f)
724 bb.msg.error(bb.msg.domain.Collection, "opening %s: %s" % (f, e), f)
726 except KeyboardInterrupt:
730 self.bb_cache.remove(f)
731 bb.msg.error(bb.msg.domain.Collection, "%s while parsing %s" % (e, f), f)
733 self.bb_cache.remove(f)
736 if self.cb is not None:
737 print "\r" # need newline after Handling Bitbake files message
738 bb.msg.note(1, bb.msg.domain.Collection, "Parsing finished. %d cached, %d parsed, %d skipped, %d masked." % ( cached, parsed, skipped, masked ))
742 #============================================================================#
744 #============================================================================#
747 parser = optparse.OptionParser( version = "BitBake Build Tool Core version %s, %%prog version %s" % ( bb.__version__, __version__ ),
748 usage = """%prog [options] [package ...]
750 Executes the specified task (default is 'build') for a given set of BitBake files.
751 It expects that BBFILES is defined, which is a space seperated list of files to
752 be executed. BBFILES does support wildcards.
753 Default BBFILES are the .bb files in the current directory.""" )
755 parser.add_option( "-b", "--buildfile", help = "execute the task against this .bb file, rather than a package from BBFILES.",
756 action = "store", dest = "buildfile", default = None )
758 parser.add_option( "-k", "--continue", help = "continue as much as possible after an error. While the target that failed, and those that depend on it, cannot be remade, the other dependencies of these targets can be processed all the same.",
759 action = "store_false", dest = "abort", default = True )
761 parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
762 action = "store_true", dest = "force", default = False )
764 parser.add_option( "-i", "--interactive", help = "drop into the interactive mode also called the BitBake shell.",
765 action = "store_true", dest = "interactive", default = False )
767 parser.add_option( "-c", "--cmd", help = "Specify task to execute. Note that this only executes the specified task for the providee and the packages it depends on, i.e. 'compile' does not implicitly call stage for the dependencies (IOW: use only if you know what you are doing). Depending on the base.bbclass a listtaks tasks is defined and will show available tasks",
768 action = "store", dest = "cmd" )
770 parser.add_option( "-r", "--read", help = "read the specified file before bitbake.conf",
771 action = "append", dest = "file", default = [] )
773 parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
774 action = "store_true", dest = "verbose", default = False )
776 parser.add_option( "-D", "--debug", help = "Increase the debug level. You can specify this more than once.",
777 action = "count", dest="debug", default = 0)
779 parser.add_option( "-n", "--dry-run", help = "don't execute, just go through the motions",
780 action = "store_true", dest = "dry_run", default = False )
782 parser.add_option( "-p", "--parse-only", help = "quit after parsing the BB files (developers only)",
783 action = "store_true", dest = "parse_only", default = False )
785 parser.add_option( "-d", "--disable-psyco", help = "disable using the psyco just-in-time compiler (not recommended)",
786 action = "store_true", dest = "disable_psyco", default = False )
788 parser.add_option( "-s", "--show-versions", help = "show current and preferred versions of all packages",
789 action = "store_true", dest = "show_versions", default = False )
791 parser.add_option( "-e", "--environment", help = "show the global or per-package environment (this is what used to be bbread)",
792 action = "store_true", dest = "show_environment", default = False )
794 parser.add_option( "-g", "--graphviz", help = "emit the dependency trees of the specified packages in the dot syntax",
795 action = "store_true", dest = "dot_graph", default = False )
797 parser.add_option( "-I", "--ignore-deps", help = """Stop processing at the given list of dependencies when generating dependency graphs. This can help to make the graph more appealing""",
798 action = "append", dest = "ignored_dot_deps", default = [] )
800 parser.add_option( "-l", "--log-domains", help = """Show debug logging for the specified logging domains""",
801 action = "append", dest = "debug_domains", default = [] )
804 options, args = parser.parse_args( sys.argv )
807 cooker.cook( BBConfiguration( options ), args[1:] )
811 if __name__ == "__main__":
812 print """WARNING, WARNING, WARNING
813 This is a Bitbake from the Unstable/Development Branch.
814 You might want to use the bitbake-1.6 stable branch (if you are not a BitBake developer or tester). I'm going to sleep 5 seconds now to make sure you see that."""