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 )
540 (filelist, masked) = self.collect_bbfiles()
541 regexp = re.compile(self.configuration.buildfile)
546 matches = matches + 1
548 bb.msg.fatal(bb.msg.domain.Parsing, "Unable to match %s (%s matches found)" % (self.configuration.buildfile, matches))
550 bbfile_data = bb.parse.handle(bf, self.configuration.data)
552 item = bb.data.getVar('PN', bbfile_data, 1)
554 self.tryBuildPackage(bf, item, self.configuration.cmd, bbfile_data, True)
555 except bb.build.EventException:
556 bb.msg.error(bb.msg.domain.Build, "Build of '%s' failed" % item )
558 sys.exit( self.stats.show() )
560 # initialise the parsing status now we know we will need deps
561 self.status = bb.cache.CacheData()
563 ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or ""
564 self.status.ignored_dependencies = Set( ignore.split() )
566 self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) )
570 if not pkgs_to_build:
572 pkgs_to_build.extend(args)
573 if not pkgs_to_build:
574 bbpkgs = bb.data.getVar('BBPKGS', self.configuration.data, 1)
576 pkgs_to_build = bbpkgs.split()
577 if not pkgs_to_build and not self.configuration.show_versions \
578 and not self.configuration.interactive \
579 and not self.configuration.show_environment:
580 print "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help'"
581 print "for usage information."
584 # Import Psyco if available and not disabled
585 if not self.configuration.disable_psyco:
589 bb.msg.note(1, bb.msg.domain.Collection, "Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance.")
591 psyco.bind( self.parse_bbfiles )
593 bb.msg.note(1, bb.msg.domain.Collection, "You have disabled Psyco. This decreases performance.")
596 bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files")
597 (filelist, masked) = self.collect_bbfiles()
598 self.parse_bbfiles(filelist, masked, self.myProgressCallback)
599 bb.msg.debug(1, bb.msg.domain.Collection, "parsing complete")
601 if self.configuration.parse_only:
602 bb.msg.note(1, bb.msg.domain.Collection, "Requested parsing .bb files only. Exiting.")
608 if self.configuration.show_versions:
611 if 'world' in pkgs_to_build:
612 self.buildWorldTargetList()
613 pkgs_to_build.remove('world')
614 for t in self.status.world_target:
615 pkgs_to_build.append(t)
617 if self.configuration.dot_graph:
618 self.generateDotGraph( pkgs_to_build, self.configuration.ignored_dot_deps )
621 bb.event.fire(bb.event.BuildStarted(buildname, pkgs_to_build, self.configuration.event_data))
623 taskdata = bb.taskdata.TaskData()
627 for k in pkgs_to_build:
628 taskdata.add_provider(self.configuration.data, self.status, k)
629 runlist.append([k, "do_%s" % self.configuration.cmd])
630 taskdata.add_unresolved(self.configuration.data, self.status)
631 except bb.providers.NoProvider:
634 rq = bb.runqueue.RunQueue()
635 rq.prepare_runqueue(self.configuration.data, self.status, taskdata, runlist)
637 failures = rq.execute_runqueue(self, self.configuration.data, self.status, taskdata, runlist)
638 except runqueue.TaskFailure, (fnid, fn, taskname):
639 bb.msg.error(bb.msg.domain.Build, "'%s, %s' failed" % (fn, taskname))
642 bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, self.configuration.event_data, failures))
644 sys.exit( self.stats.show() )
646 except KeyboardInterrupt:
647 bb.msg.note(1, bb.msg.domain.Collection, "KeyboardInterrupt - Build not completed.")
650 def get_bbfiles( self, path = os.getcwd() ):
651 """Get list of default .bb files by reading out the current directory"""
652 contents = os.listdir(path)
655 (root, ext) = os.path.splitext(f)
657 bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
660 def find_bbfiles( self, path ):
661 """Find all the .bb files in a directory (uses find)"""
662 findcmd = 'find ' + path + ' -name *.bb | grep -v SCCS/'
664 finddata = os.popen(findcmd)
667 return finddata.readlines()
669 def collect_bbfiles( self ):
670 """Collect all available .bb build files"""
671 parsed, cached, skipped, masked = 0, 0, 0, 0
672 self.bb_cache = bb.cache.init(self)
674 files = (data.getVar( "BBFILES", self.configuration.data, 1 ) or "").split()
675 data.setVar("BBFILES", " ".join(files), self.configuration.data)
678 files = self.get_bbfiles()
681 bb.msg.error(bb.msg.domain.Collection, "no files to build.")
686 dirfiles = self.find_bbfiles(f)
690 newfiles += glob.glob(f) or [ f ]
692 bbmask = bb.data.getVar('BBMASK', self.configuration.data, 1)
698 bbmask_compiled = re.compile(bbmask)
699 except sre_constants.error:
700 bb.msg.fatal(bb.msg.domain.Collection, "BBMASK is not a valid regular expression.")
703 for i in xrange( len( newfiles ) ):
705 if bbmask and bbmask_compiled.search(f):
706 bb.msg.debug(1, bb.msg.domain.Collection, "skipping masked file %s" % f)
711 return (finalfiles, masked)
713 def parse_bbfiles(self, filelist, masked, progressCallback = None):
714 parsed, cached, skipped = 0, 0, 0
715 for i in xrange( len( filelist ) ):
718 bb.msg.debug(1, bb.msg.domain.Collection, "parsing %s" % f)
720 # read a file's metadata
722 fromCache, skip = self.bb_cache.loadData(f, self)
725 bb.msg.debug(2, bb.msg.domain.Collection, "skipping %s" % f)
726 self.bb_cache.skip(f)
728 elif fromCache: cached += 1
732 # Disabled by RP as was no longer functional
733 # allow metadata files to add items to BBFILES
734 #data.update_data(self.pkgdata[f])
735 #addbbfiles = self.bb_cache.getVar('BBFILES', f, False) or None
737 # for aof in addbbfiles.split():
738 # if not files.count(aof):
739 # if not os.path.isabs(aof):
740 # aof = os.path.join(os.path.dirname(f),aof)
743 # now inform the caller
744 if progressCallback is not None:
745 progressCallback( i + 1, len( filelist ), f, self.bb_cache, fromCache )
748 self.bb_cache.remove(f)
749 bb.msg.error(bb.msg.domain.Collection, "opening %s: %s" % (f, e))
751 except KeyboardInterrupt:
755 self.bb_cache.remove(f)
756 bb.msg.error(bb.msg.domain.Collection, "%s while parsing %s" % (e, f))
758 self.bb_cache.remove(f)
761 if progressCallback is not None:
762 print "\r" # need newline after Handling Bitbake files message
763 bb.msg.note(1, bb.msg.domain.Collection, "Parsing finished. %d cached, %d parsed, %d skipped, %d masked." % ( cached, parsed, skipped, masked ))
767 #============================================================================#
769 #============================================================================#
772 parser = optparse.OptionParser( version = "BitBake Build Tool Core version %s, %%prog version %s" % ( bb.__version__, __version__ ),
773 usage = """%prog [options] [package ...]
775 Executes the specified task (default is 'build') for a given set of BitBake files.
776 It expects that BBFILES is defined, which is a space seperated list of files to
777 be executed. BBFILES does support wildcards.
778 Default BBFILES are the .bb files in the current directory.""" )
780 parser.add_option( "-b", "--buildfile", help = "execute the task against this .bb file, rather than a package from BBFILES.",
781 action = "store", dest = "buildfile", default = None )
783 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.",
784 action = "store_false", dest = "abort", default = True )
786 parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
787 action = "store_true", dest = "force", default = False )
789 parser.add_option( "-i", "--interactive", help = "drop into the interactive mode also called the BitBake shell.",
790 action = "store_true", dest = "interactive", default = False )
792 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",
793 action = "store", dest = "cmd" )
795 parser.add_option( "-r", "--read", help = "read the specified file before bitbake.conf",
796 action = "append", dest = "file", default = [] )
798 parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
799 action = "store_true", dest = "verbose", default = False )
801 parser.add_option( "-D", "--debug", help = "Increase the debug level. You can specify this more than once.",
802 action = "count", dest="debug", default = 0)
804 parser.add_option( "-n", "--dry-run", help = "don't execute, just go through the motions",
805 action = "store_true", dest = "dry_run", default = False )
807 parser.add_option( "-p", "--parse-only", help = "quit after parsing the BB files (developers only)",
808 action = "store_true", dest = "parse_only", default = False )
810 parser.add_option( "-d", "--disable-psyco", help = "disable using the psyco just-in-time compiler (not recommended)",
811 action = "store_true", dest = "disable_psyco", default = False )
813 parser.add_option( "-s", "--show-versions", help = "show current and preferred versions of all packages",
814 action = "store_true", dest = "show_versions", default = False )
816 parser.add_option( "-e", "--environment", help = "show the global or per-package environment (this is what used to be bbread)",
817 action = "store_true", dest = "show_environment", default = False )
819 parser.add_option( "-g", "--graphviz", help = "emit the dependency trees of the specified packages in the dot syntax",
820 action = "store_true", dest = "dot_graph", default = False )
822 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""",
823 action = "append", dest = "ignored_dot_deps", default = [] )
825 parser.add_option( "-l", "--log-domains", help = """Show debug logging for the specified logging domains""",
826 action = "append", dest = "debug_domains", default = [] )
829 options, args = parser.parse_args( sys.argv )
832 cooker.cook( BBConfiguration( options ), args[1:] )
836 if __name__ == "__main__":
837 print """WARNING, WARNING, WARNING
838 This is a Bitbake from the Unstable/Development Branch.
839 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."""