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.configuration.data)
129 item = self.status.pkg_fn[fn]
131 if bb.build.stamp_is_current('do_%s' % self.configuration.cmd, the_data) and not self.configuration.force:
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.configuration.data)
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 data.expandKeys( self.configuration.data )
183 for e in self.configuration.data.keys():
184 if data.getVarFlag( e, 'python', self.configuration.data ):
185 sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, data.getVar(e, self.configuration.data, 1)))
187 def generateDotGraph( self, pkgs_to_build, ignore_deps ):
189 Generate a task dependency graph.
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 for dep in ignore_deps:
197 self.status.ignored_dependencies.add(dep)
199 localdata = data.createCopy(self.configuration.data)
200 bb.data.update_data(localdata)
201 bb.data.expandKeys(localdata)
202 taskdata = bb.taskdata.TaskData(self.configuration.abort)
206 for k in pkgs_to_build:
207 taskdata.add_provider(localdata, self.status, k)
208 runlist.append([k, "do_%s" % self.configuration.cmd])
209 taskdata.add_unresolved(localdata, self.status)
210 except bb.providers.NoProvider:
212 rq = bb.runqueue.RunQueue()
213 rq.prepare_runqueue(self.configuration.data, self.status, taskdata, runlist)
216 depends_file = file('depends.dot', 'w' )
217 tdepends_file = file('task-depends.dot', 'w' )
218 print >> depends_file, "digraph depends {"
219 print >> tdepends_file, "digraph depends {"
220 rq.prio_map.reverse()
221 for task1 in range(len(rq.runq_fnid)):
222 task = rq.prio_map[task1]
223 taskname = rq.runq_task[task]t
224 fnid = rq.runq_fnid[task]
225 fn = taskdata.fn_index[fnid]
226 pn = self.status.pkg_fn[fn]
227 version = self.bb_cache.getVar('PV', fn, True ) + '-' + self.bb_cache.getVar('PR', fn, True)
228 print >> tdepends_file, '"%s.%s" [label="%s %s\\n%s\\n%s"]' % (pn, taskname, pn, taskname, version, fn)
229 for dep in rq.runq_depends[task]:
230 depfn = taskdata.fn_index[rq.runq_fnid[dep]]
231 deppn = self.status.pkg_fn[depfn]
232 print >> tdepends_file, '"%s.%s" -> "%s.%s"' % (pn, rq.runq_task[task], deppn, rq.runq_task[dep])
233 if fnid not in seen_fnids:
234 seen_fnids.append(fnid)
236 print >> depends_file, '"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn)
237 for depend in self.status.deps[fn]:
238 print >> depends_file, '"%s" -> "%s"' % (pn, depend)
239 rdepends = self.status.rundeps[fn]
240 for package in rdepends:
241 for rdepend in rdepends[package]:
242 print >> depends_file, '"%s" -> "%s" [style=dashed]' % (package, rdepend)
243 packages.append(package)
244 rrecs = self.status.runrecs[fn]
245 for package in rrecs:
246 for rdepend in rrecs[package]:
247 print >> depends_file, '"%s" -> "%s" [style=dashed]' % (package, rdepend)
248 if not package in packages:
249 packages.append(package)
250 for package in packages:
252 print >> depends_file, '"%s" [label="%s(%s) %s\\n%s"]' % (package, package, pn, version, fn)
253 for depend in self.status.deps[fn]:
254 print >> depends_file, '"%s" -> "%s"' % (package, depend)
255 # Prints a flattened form of the above where subpackages of a package are merged into the main pn
256 #print >> depends_file, '"%s" [label="%s %s\\n%s\\n%s"]' % (pn, pn, taskname, version, fn)
257 #for rdep in taskdata.rdepids[fnid]:
258 # print >> depends_file, '"%s" -> "%s" [style=dashed]' % (pn, taskdata.run_names_index[rdep])
259 #for dep in taskdata.depids[fnid]:
260 # print >> depends_file, '"%s" -> "%s"' % (pn, taskdata.build_names_index[dep])
261 print >> depends_file, "}"
262 print >> tdepends_file, "}"
263 bb.msg.note(1, bb.msg.domain.Collection, "Dependencies saved to 'depends.dot'")
264 bb.msg.note(1, bb.msg.domain.Collection, "Task dependencies saved to 'task-depends.dot'")
266 def buildDepgraph( self ):
267 all_depends = self.status.all_depends
268 pn_provides = self.status.pn_provides
270 localdata = data.createCopy(self.configuration.data)
271 bb.data.update_data(localdata)
272 bb.data.expandKeys(localdata)
274 def calc_bbfile_priority(filename):
275 for (regex, pri) in self.status.bbfile_config_priorities:
276 if regex.match(filename):
280 # Handle PREFERRED_PROVIDERS
281 for p in (bb.data.getVar('PREFERRED_PROVIDERS', localdata, 1) or "").split():
282 (providee, provider) = p.split(':')
283 if providee in self.status.preferred and self.status.preferred[providee] != provider:
284 bb.msg.error(bb.msg.domain.Provider, "conflicting preferences for %s: both %s and %s specified" % (providee, provider, self.status.preferred[providee]))
285 self.status.preferred[providee] = provider
287 # Calculate priorities for each file
288 for p in self.status.pkg_fn.keys():
289 self.status.bbfile_priority[p] = calc_bbfile_priority(p)
291 def buildWorldTargetList(self):
293 Build package list for "bitbake world"
295 all_depends = self.status.all_depends
296 pn_provides = self.status.pn_provides
297 bb.msg.debug(1, bb.msg.domain.Parsing, "collating packages for \"world\"")
298 for f in self.status.possible_world:
300 pn = self.status.pkg_fn[f]
302 for p in pn_provides[pn]:
303 if p.startswith('virtual/'):
304 bb.msg.debug(2, bb.msg.domain.Parsing, "World build skipping %s due to %s provider starting with virtual/" % (f, p))
307 for pf in self.status.providers[p]:
308 if self.status.pkg_fn[pf] != pn:
309 bb.msg.debug(2, bb.msg.domain.Parsing, "World build skipping %s due to both us and %s providing %s" % (f, pf, p))
313 self.status.world_target.add(pn)
315 # drop reference count now
316 self.status.possible_world = None
317 self.status.all_depends = None
319 def myProgressCallback( self, x, y, f, from_cache ):
320 """Update any tty with the progress change"""
321 if os.isatty(sys.stdout.fileno()):
322 sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
326 sys.stdout.write("Parsing .bb files, please wait...")
329 sys.stdout.write("done.")
332 def interactiveMode( self ):
333 """Drop off into a shell"""
336 except ImportError, details:
337 bb.msg.fatal(bb.msg.domain.Parsing, "Sorry, shell not available (%s)" % details )
339 bb.data.update_data( self.configuration.data )
340 bb.data.expandKeys(localdata)
344 def parseConfigurationFile( self, afile ):
346 self.configuration.data = bb.parse.handle( afile, self.configuration.data )
348 # Add the handlers we inherited by INHERIT
349 # we need to do this manually as it is not guranteed
350 # we will pick up these classes... as we only INHERIT
351 # on .inc and .bb files but not on .conf
352 data = bb.data.createCopy( self.configuration.data )
353 inherits = ["base"] + (bb.data.getVar('INHERIT', data, True ) or "").split()
354 for inherit in inherits:
355 data = bb.parse.handle( os.path.join('classes', '%s.bbclass' % inherit ), data, True )
357 # FIXME: This assumes that we included at least one .inc file
358 for var in bb.data.keys(data):
359 if bb.data.getVarFlag(var, 'handler', data):
360 bb.event.register(var,bb.data.getVar(var, data))
363 bb.msg.fatal(bb.msg.domain.Parsing, "Unable to open %s" % afile )
364 except bb.parse.ParseError, details:
365 bb.msg.fatal(bb.msg.domain.Parsing, "Unable to parse %s (%s)" % (afile, details) )
367 def handleCollections( self, collections ):
368 """Handle collections"""
370 collection_list = collections.split()
371 for c in collection_list:
372 regex = bb.data.getVar("BBFILE_PATTERN_%s" % c, self.configuration.data, 1)
374 bb.msg.error(bb.msg.domain.Parsing, "BBFILE_PATTERN_%s not defined" % c)
376 priority = bb.data.getVar("BBFILE_PRIORITY_%s" % c, self.configuration.data, 1)
378 bb.msg.error(bb.msg.domain.Parsing, "BBFILE_PRIORITY_%s not defined" % c)
381 cre = re.compile(regex)
383 bb.msg.error(bb.msg.domain.Parsing, "BBFILE_PATTERN_%s \"%s\" is not a valid regular expression" % (c, regex))
387 self.status.bbfile_config_priorities.append((cre, pri))
389 bb.msg.error(bb.msg.domain.Parsing, "invalid value for BBFILE_PRIORITY_%s: \"%s\"" % (c, priority))
392 def cook( self, configuration, args ):
394 We are building stuff here. We do the building
395 from here. By default we try to execute task
399 self.configuration = configuration
401 if self.configuration.verbose:
402 bb.msg.set_verbose(True)
404 if self.configuration.debug:
405 bb.msg.set_debug_level(self.configuration.debug)
407 bb.msg.set_debug_level(0)
409 if self.configuration.debug_domains:
410 bb.msg.set_debug_domains(self.configuration.debug_domains)
412 self.configuration.data = bb.data.init()
414 for f in self.configuration.file:
415 self.parseConfigurationFile( f )
417 self.parseConfigurationFile( os.path.join( "conf", "bitbake.conf" ) )
419 if not self.configuration.cmd:
420 self.configuration.cmd = bb.data.getVar("BB_DEFAULT_TASK", self.configuration.data)
422 # For backwards compatibility - REMOVE ME
423 if not self.configuration.cmd:
424 self.configuration.cmd = "build"
427 # Special updated configuration we use for firing events
429 self.configuration.event_data = bb.data.createCopy(self.configuration.data)
430 bb.data.update_data(self.configuration.event_data)
432 if self.configuration.show_environment:
433 self.showEnvironment()
436 # inject custom variables
437 if not bb.data.getVar("BUILDNAME", self.configuration.data):
438 bb.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), self.configuration.data)
439 bb.data.setVar("BUILDSTART", time.strftime('%m/%d/%Y %H:%M:%S',time.gmtime()),self.configuration.data)
441 buildname = bb.data.getVar("BUILDNAME", self.configuration.data)
443 if self.configuration.interactive:
444 self.interactiveMode()
446 if self.configuration.buildfile is not None:
447 bf = os.path.abspath( self.configuration.buildfile )
451 (filelist, masked) = self.collect_bbfiles()
452 regexp = re.compile(self.configuration.buildfile)
455 if regexp.search(f) and os.path.isfile(f):
458 if len(matches) != 1:
459 bb.msg.error(bb.msg.domain.Parsing, "Unable to match %s (%s matches found):" % (self.configuration.buildfile, len(matches)))
461 bb.msg.error(bb.msg.domain.Parsing, " %s" % f)
465 bbfile_data = bb.parse.handle(bf, self.configuration.data)
467 item = bb.data.getVar('PN', bbfile_data, 1)
469 self.tryBuildPackage(bf, item, self.configuration.cmd, bbfile_data, True)
470 except bb.build.EventException:
471 bb.msg.error(bb.msg.domain.Build, "Build of '%s' failed" % item )
473 sys.exit( self.stats.show() )
475 # initialise the parsing status now we know we will need deps
476 self.status = bb.cache.CacheData()
478 ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or ""
479 self.status.ignored_dependencies = Set( ignore.split() )
481 self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) )
485 if not pkgs_to_build:
487 pkgs_to_build.extend(args)
488 if not pkgs_to_build:
489 bbpkgs = bb.data.getVar('BBPKGS', self.configuration.data, 1)
491 pkgs_to_build = bbpkgs.split()
492 if not pkgs_to_build and not self.configuration.show_versions \
493 and not self.configuration.interactive \
494 and not self.configuration.show_environment:
495 print "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help'"
496 print "for usage information."
499 # Import Psyco if available and not disabled
500 if not self.configuration.disable_psyco:
504 bb.msg.note(1, bb.msg.domain.Collection, "Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance.")
506 psyco.bind( self.parse_bbfiles )
508 bb.msg.note(1, bb.msg.domain.Collection, "You have disabled Psyco. This decreases performance.")
511 bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files")
512 (filelist, masked) = self.collect_bbfiles()
513 self.parse_bbfiles(filelist, masked, self.myProgressCallback)
514 bb.msg.debug(1, bb.msg.domain.Collection, "parsing complete")
516 if self.configuration.parse_only:
517 bb.msg.note(1, bb.msg.domain.Collection, "Requested parsing .bb files only. Exiting.")
523 if self.configuration.show_versions:
526 if 'world' in pkgs_to_build:
527 self.buildWorldTargetList()
528 pkgs_to_build.remove('world')
529 for t in self.status.world_target:
530 pkgs_to_build.append(t)
532 if self.configuration.dot_graph:
533 self.generateDotGraph( pkgs_to_build, self.configuration.ignored_dot_deps )
536 bb.event.fire(bb.event.BuildStarted(buildname, pkgs_to_build, self.configuration.event_data))
538 localdata = data.createCopy(self.configuration.data)
539 bb.data.update_data(localdata)
540 bb.data.expandKeys(localdata)
542 taskdata = bb.taskdata.TaskData(self.configuration.abort)
546 for k in pkgs_to_build:
547 taskdata.add_provider(localdata, self.status, k)
548 runlist.append([k, "do_%s" % self.configuration.cmd])
549 taskdata.add_unresolved(localdata, self.status)
550 except bb.providers.NoProvider:
553 rq = bb.runqueue.RunQueue()
554 rq.prepare_runqueue(self.configuration.data, self.status, taskdata, runlist)
556 failures = rq.execute_runqueue(self, self.configuration.data, self.status, taskdata, runlist)
557 except runqueue.TaskFailure, fnids:
559 bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid])
561 bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, self.configuration.event_data, failures))
563 sys.exit( self.stats.show() )
565 except KeyboardInterrupt:
566 bb.msg.note(1, bb.msg.domain.Collection, "KeyboardInterrupt - Build not completed.")
569 def get_bbfiles( self, path = os.getcwd() ):
570 """Get list of default .bb files by reading out the current directory"""
571 contents = os.listdir(path)
574 (root, ext) = os.path.splitext(f)
576 bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
579 def find_bbfiles( self, path ):
580 """Find all the .bb files in a directory (uses find)"""
581 findcmd = 'find ' + path + ' -name *.bb | grep -v SCCS/'
583 finddata = os.popen(findcmd)
586 return finddata.readlines()
588 def collect_bbfiles( self ):
589 """Collect all available .bb build files"""
590 parsed, cached, skipped, masked = 0, 0, 0, 0
591 self.bb_cache = bb.cache.init(self)
593 files = (data.getVar( "BBFILES", self.configuration.data, 1 ) or "").split()
594 data.setVar("BBFILES", " ".join(files), self.configuration.data)
597 files = self.get_bbfiles()
600 bb.msg.error(bb.msg.domain.Collection, "no files to build.")
605 dirfiles = self.find_bbfiles(f)
609 newfiles += glob.glob(f) or [ f ]
611 bbmask = bb.data.getVar('BBMASK', self.configuration.data, 1)
617 bbmask_compiled = re.compile(bbmask)
618 except sre_constants.error:
619 bb.msg.fatal(bb.msg.domain.Collection, "BBMASK is not a valid regular expression.")
622 for i in xrange( len( newfiles ) ):
624 if bbmask and bbmask_compiled.search(f):
625 bb.msg.debug(1, bb.msg.domain.Collection, "skipping masked file %s" % f)
630 return (finalfiles, masked)
632 def parse_bbfiles(self, filelist, masked, progressCallback = None):
633 parsed, cached, skipped = 0, 0, 0
634 for i in xrange( len( filelist ) ):
637 bb.msg.debug(1, bb.msg.domain.Collection, "parsing %s" % f)
639 # read a file's metadata
641 fromCache, skip = self.bb_cache.loadData(f, self.configuration.data)
644 bb.msg.debug(2, bb.msg.domain.Collection, "skipping %s" % f)
645 self.bb_cache.skip(f)
647 elif fromCache: cached += 1
651 # Disabled by RP as was no longer functional
652 # allow metadata files to add items to BBFILES
653 #data.update_data(self.pkgdata[f])
654 #addbbfiles = self.bb_cache.getVar('BBFILES', f, False) or None
656 # for aof in addbbfiles.split():
657 # if not files.count(aof):
658 # if not os.path.isabs(aof):
659 # aof = os.path.join(os.path.dirname(f),aof)
662 self.bb_cache.handle_data(f, self.status)
664 # now inform the caller
665 if progressCallback is not None:
666 progressCallback( i + 1, len( filelist ), f, fromCache )
669 self.bb_cache.remove(f)
670 bb.msg.error(bb.msg.domain.Collection, "opening %s: %s" % (f, e))
672 except KeyboardInterrupt:
676 self.bb_cache.remove(f)
677 bb.msg.error(bb.msg.domain.Collection, "%s while parsing %s" % (e, f))
679 self.bb_cache.remove(f)
682 if progressCallback is not None:
683 print "\r" # need newline after Handling Bitbake files message
684 bb.msg.note(1, bb.msg.domain.Collection, "Parsing finished. %d cached, %d parsed, %d skipped, %d masked." % ( cached, parsed, skipped, masked ))
688 #============================================================================#
690 #============================================================================#
693 parser = optparse.OptionParser( version = "BitBake Build Tool Core version %s, %%prog version %s" % ( bb.__version__, __version__ ),
694 usage = """%prog [options] [package ...]
696 Executes the specified task (default is 'build') for a given set of BitBake files.
697 It expects that BBFILES is defined, which is a space seperated list of files to
698 be executed. BBFILES does support wildcards.
699 Default BBFILES are the .bb files in the current directory.""" )
701 parser.add_option( "-b", "--buildfile", help = "execute the task against this .bb file, rather than a package from BBFILES.",
702 action = "store", dest = "buildfile", default = None )
704 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.",
705 action = "store_false", dest = "abort", default = True )
707 parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
708 action = "store_true", dest = "force", default = False )
710 parser.add_option( "-i", "--interactive", help = "drop into the interactive mode also called the BitBake shell.",
711 action = "store_true", dest = "interactive", default = False )
713 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",
714 action = "store", dest = "cmd" )
716 parser.add_option( "-r", "--read", help = "read the specified file before bitbake.conf",
717 action = "append", dest = "file", default = [] )
719 parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
720 action = "store_true", dest = "verbose", default = False )
722 parser.add_option( "-D", "--debug", help = "Increase the debug level. You can specify this more than once.",
723 action = "count", dest="debug", default = 0)
725 parser.add_option( "-n", "--dry-run", help = "don't execute, just go through the motions",
726 action = "store_true", dest = "dry_run", default = False )
728 parser.add_option( "-p", "--parse-only", help = "quit after parsing the BB files (developers only)",
729 action = "store_true", dest = "parse_only", default = False )
731 parser.add_option( "-d", "--disable-psyco", help = "disable using the psyco just-in-time compiler (not recommended)",
732 action = "store_true", dest = "disable_psyco", default = False )
734 parser.add_option( "-s", "--show-versions", help = "show current and preferred versions of all packages",
735 action = "store_true", dest = "show_versions", default = False )
737 parser.add_option( "-e", "--environment", help = "show the global or per-package environment (this is what used to be bbread)",
738 action = "store_true", dest = "show_environment", default = False )
740 parser.add_option( "-g", "--graphviz", help = "emit the dependency trees of the specified packages in the dot syntax",
741 action = "store_true", dest = "dot_graph", default = False )
743 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""",
744 action = "append", dest = "ignored_dot_deps", default = [] )
746 parser.add_option( "-l", "--log-domains", help = """Show debug logging for the specified logging domains""",
747 action = "append", dest = "debug_domains", default = [] )
750 options, args = parser.parse_args( sys.argv )
753 cooker.cook( BBConfiguration( options ), args[1:] )
757 if __name__ == "__main__":
758 print """WARNING, WARNING, WARNING
759 This is a Bitbake from the Unstable/Development Branch.
760 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."""