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 two graphs one for the DEPENDS and RDEPENDS. The current
190 implementation creates crappy graphs ;)
192 pkgs_to_build A list of packages that needs to be built
193 ignore_deps A list of names where processing of dependencies
194 should be stopped. e.g. dependencies that get
197 def myFilterProvider( providers, item):
199 Take a list of providers and filter according to environment
200 variables. In contrast to filterProviders we do not discriminate
201 and take PREFERRED_PROVIDER into account.
204 preferred_versions = {}
206 # Collate providers by PN
209 pn = self.status.pkg_fn[p]
214 bb.msg.debug(1, bb.msg.domain.Provider, "providers for %s are: %s" % (item, pkg_pn.keys()))
216 for pn in pkg_pn.keys():
217 preferred_versions[pn] = bb.providers.findBestProvider(pn, self.configuration.data, self.status, pkg_pn)[2:4]
218 eligible.append(preferred_versions[pn][1])
221 if p in self.build_cache_fail:
222 bb.msg.debug(1, bb.msg.domain.Provider, "rejecting already-failed %s" % p)
225 if len(eligible) == 0:
226 bb.msg.error(bb.msg.domain.Provider, "no eligible providers for %s" % item)
229 prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % item, self.configuration.data, 1)
231 # try the preferred provider first
234 if prefervar == self.status.pkg_fn[p]:
235 bb.msg.note(1, bb.msg.domain.Provider, "Selecting PREFERRED_PROVIDER %s" % prefervar)
237 eligible = [p] + eligible
242 # try to avoid adding the same rdepends over an over again
247 def add_depends(package_list):
249 Add all depends of all packages from this list
251 for package in package_list:
252 if package in seen_depends or package in ignore_deps:
255 seen_depends.append( package )
256 if not package in self.status.providers:
258 We have not seen this name -> error in
261 bb.msg.note(1, bb.msg.domain.Depends, "ERROR with provider: %(package)s" % vars() )
262 print >> depends_file, '"%(package)s" -> ERROR' % vars()
265 # get all providers for this package
266 providers = self.status.providers[package]
268 # now let us find the bestProvider for it
269 fn = myFilterProvider(providers, package)[0]
271 depends = bb.utils.explode_deps(self.bb_cache.getVar('DEPENDS', fn, True) or "")
272 version = self.bb_cache.getVar('PV', fn, True ) + '-' + self.bb_cache.getVar('PR', fn, True)
273 add_depends ( depends )
275 # now create the node
276 print >> depends_file, '"%(package)s" [label="%(package)s\\n%(version)s"]' % vars()
278 depends = filter( (lambda x: x not in ignore_deps), depends )
279 for depend in depends:
280 print >> depends_file, '"%(package)s" -> "%(depend)s"' % vars()
283 def add_all_depends( the_depends, the_rdepends ):
285 Add both DEPENDS and RDEPENDS. RDEPENDS will get dashed
288 package_list = the_depends + the_rdepends
289 for package in package_list:
290 if package in seen_rdepends or package in ignore_deps:
293 seen_rdepends.append( package )
295 # Let us find out if the package is a DEPENDS or RDEPENDS
296 # and we will set 'providers' with the avilable providers
298 if package in the_depends:
299 if not package in self.status.providers:
300 bb.msg.note(1, bb.msg.domain.Depends, "ERROR with provider: %(package)s" % vars() )
301 print >> alldepends_file, '"%(package)s" -> ERROR' % vars()
304 providers = self.status.providers[package]
305 elif package in the_rdepends:
306 if len(bb.providers.getRuntimeProviders(self.status, package)) == 0:
307 bb.msg.note(1, bb.msg.domain.Depends, "ERROR with rprovider: %(package)s" % vars() )
308 print >> alldepends_file, '"%(package)s" -> ERROR [style="dashed"]' % vars()
311 providers = bb.providers.getRuntimeProviders(self.status, package)
313 # something went wrong...
314 print "Complete ERROR! %s" % package
317 # now let us find the bestProvider for it
318 fn = myFilterProvider(providers, package)[0]
320 # Now we have a filename let us get the depends and RDEPENDS of it
321 depends = bb.utils.explode_deps(self.bb_cache.getVar('DEPENDS', fn, True) or "")
322 if fn in self.status.rundeps and package in self.status.rundeps[fn]:
323 rdepends= self.status.rundeps[fn][package].keys()
326 version = self.bb_cache.getVar('PV', fn, True ) + '-' + self.bb_cache.getVar('PR', fn, True)
328 # handle all the depends and rdepends of package
329 add_all_depends ( depends, rdepends )
331 # now create the node using package name
332 print >> alldepends_file, '"%(package)s" [label="%(package)s\\n%(version)s"]' % vars()
334 # remove the stuff we want to ignore and add the edges
335 depends = filter( (lambda x: x not in ignore_deps), depends )
336 rdepends = filter( (lambda x: x not in ignore_deps), rdepends )
337 for depend in depends:
338 print >> alldepends_file, '"%(package)s" -> "%(depend)s"' % vars()
339 for depend in rdepends:
340 print >> alldepends_file, '"%(package)s" -> "%(depend)s" [style=dashed]' % vars()
344 depends_file = file('depends.dot', 'w' )
345 print >> depends_file, "digraph depends {"
346 add_depends( pkgs_to_build )
347 print >> depends_file, "}"
349 # Add all depends now
350 alldepends_file = file('alldepends.dot', 'w' )
351 print >> alldepends_file, "digraph alldepends {"
352 add_all_depends( pkgs_to_build, [] )
353 print >> alldepends_file, "}"
355 def buildDepgraph( self ):
356 all_depends = self.status.all_depends
357 pn_provides = self.status.pn_provides
359 localdata = data.createCopy(self.configuration.data)
360 bb.data.update_data(localdata)
361 bb.data.expandKeys(localdata)
363 def calc_bbfile_priority(filename):
364 for (regex, pri) in self.status.bbfile_config_priorities:
365 if regex.match(filename):
369 # Handle PREFERRED_PROVIDERS
370 for p in (bb.data.getVar('PREFERRED_PROVIDERS', localdata, 1) or "").split():
371 (providee, provider) = p.split(':')
372 if providee in self.status.preferred and self.status.preferred[providee] != provider:
373 bb.msg.error(bb.msg.domain.Provider, "conflicting preferences for %s: both %s and %s specified" % (providee, provider, self.status.preferred[providee]))
374 self.status.preferred[providee] = provider
376 # Calculate priorities for each file
377 for p in self.status.pkg_fn.keys():
378 self.status.bbfile_priority[p] = calc_bbfile_priority(p)
380 def buildWorldTargetList(self):
382 Build package list for "bitbake world"
384 all_depends = self.status.all_depends
385 pn_provides = self.status.pn_provides
386 bb.msg.debug(1, bb.msg.domain.Parsing, "collating packages for \"world\"")
387 for f in self.status.possible_world:
389 pn = self.status.pkg_fn[f]
391 for p in pn_provides[pn]:
392 if p.startswith('virtual/'):
393 bb.msg.debug(2, bb.msg.domain.Parsing, "World build skipping %s due to %s provider starting with virtual/" % (f, p))
396 for pf in self.status.providers[p]:
397 if self.status.pkg_fn[pf] != pn:
398 bb.msg.debug(2, bb.msg.domain.Parsing, "World build skipping %s due to both us and %s providing %s" % (f, pf, p))
402 self.status.world_target.add(pn)
404 # drop reference count now
405 self.status.possible_world = None
406 self.status.all_depends = None
408 def myProgressCallback( self, x, y, f, from_cache ):
409 """Update any tty with the progress change"""
410 if os.isatty(sys.stdout.fileno()):
411 sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
415 sys.stdout.write("Parsing .bb files, please wait...")
418 sys.stdout.write("done.")
421 def interactiveMode( self ):
422 """Drop off into a shell"""
425 except ImportError, details:
426 bb.msg.fatal(bb.msg.domain.Parsing, "Sorry, shell not available (%s)" % details )
428 bb.data.update_data( self.configuration.data )
429 bb.data.expandKeys(localdata)
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)
544 if regexp.search(f) and os.path.isfile(f):
547 if len(matches) != 1:
548 bb.msg.error(bb.msg.domain.Parsing, "Unable to match %s (%s matches found):" % (self.configuration.buildfile, len(matches)))
550 bb.msg.error(bb.msg.domain.Parsing, " %s" % f)
554 bbfile_data = bb.parse.handle(bf, self.configuration.data)
556 item = bb.data.getVar('PN', bbfile_data, 1)
558 self.tryBuildPackage(bf, item, self.configuration.cmd, bbfile_data, True)
559 except bb.build.EventException:
560 bb.msg.error(bb.msg.domain.Build, "Build of '%s' failed" % item )
562 sys.exit( self.stats.show() )
564 # initialise the parsing status now we know we will need deps
565 self.status = bb.cache.CacheData()
567 ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or ""
568 self.status.ignored_dependencies = Set( ignore.split() )
570 self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) )
574 if not pkgs_to_build:
576 pkgs_to_build.extend(args)
577 if not pkgs_to_build:
578 bbpkgs = bb.data.getVar('BBPKGS', self.configuration.data, 1)
580 pkgs_to_build = bbpkgs.split()
581 if not pkgs_to_build and not self.configuration.show_versions \
582 and not self.configuration.interactive \
583 and not self.configuration.show_environment:
584 print "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help'"
585 print "for usage information."
588 # Import Psyco if available and not disabled
589 if not self.configuration.disable_psyco:
593 bb.msg.note(1, bb.msg.domain.Collection, "Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance.")
595 psyco.bind( self.parse_bbfiles )
597 bb.msg.note(1, bb.msg.domain.Collection, "You have disabled Psyco. This decreases performance.")
600 bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files")
601 (filelist, masked) = self.collect_bbfiles()
602 self.parse_bbfiles(filelist, masked, self.myProgressCallback)
603 bb.msg.debug(1, bb.msg.domain.Collection, "parsing complete")
605 if self.configuration.parse_only:
606 bb.msg.note(1, bb.msg.domain.Collection, "Requested parsing .bb files only. Exiting.")
612 if self.configuration.show_versions:
615 if 'world' in pkgs_to_build:
616 self.buildWorldTargetList()
617 pkgs_to_build.remove('world')
618 for t in self.status.world_target:
619 pkgs_to_build.append(t)
621 if self.configuration.dot_graph:
622 self.generateDotGraph( pkgs_to_build, self.configuration.ignored_dot_deps )
625 bb.event.fire(bb.event.BuildStarted(buildname, pkgs_to_build, self.configuration.event_data))
627 localdata = data.createCopy(self.configuration.data)
628 bb.data.update_data(localdata)
629 bb.data.expandKeys(localdata)
631 taskdata = bb.taskdata.TaskData(self.configuration.abort)
635 for k in pkgs_to_build:
636 taskdata.add_provider(localdata, self.status, k)
637 runlist.append([k, "do_%s" % self.configuration.cmd])
638 taskdata.add_unresolved(localdata, self.status)
639 except bb.providers.NoProvider:
642 rq = bb.runqueue.RunQueue()
643 rq.prepare_runqueue(self.configuration.data, self.status, taskdata, runlist)
645 failures = rq.execute_runqueue(self, self.configuration.data, self.status, taskdata, runlist)
646 except runqueue.TaskFailure, fnids:
648 bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid])
650 bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, self.configuration.event_data, failures))
652 sys.exit( self.stats.show() )
654 except KeyboardInterrupt:
655 bb.msg.note(1, bb.msg.domain.Collection, "KeyboardInterrupt - Build not completed.")
658 def get_bbfiles( self, path = os.getcwd() ):
659 """Get list of default .bb files by reading out the current directory"""
660 contents = os.listdir(path)
663 (root, ext) = os.path.splitext(f)
665 bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
668 def find_bbfiles( self, path ):
669 """Find all the .bb files in a directory (uses find)"""
670 findcmd = 'find ' + path + ' -name *.bb | grep -v SCCS/'
672 finddata = os.popen(findcmd)
675 return finddata.readlines()
677 def collect_bbfiles( self ):
678 """Collect all available .bb build files"""
679 parsed, cached, skipped, masked = 0, 0, 0, 0
680 self.bb_cache = bb.cache.init(self)
682 files = (data.getVar( "BBFILES", self.configuration.data, 1 ) or "").split()
683 data.setVar("BBFILES", " ".join(files), self.configuration.data)
686 files = self.get_bbfiles()
689 bb.msg.error(bb.msg.domain.Collection, "no files to build.")
694 dirfiles = self.find_bbfiles(f)
698 newfiles += glob.glob(f) or [ f ]
700 bbmask = bb.data.getVar('BBMASK', self.configuration.data, 1)
706 bbmask_compiled = re.compile(bbmask)
707 except sre_constants.error:
708 bb.msg.fatal(bb.msg.domain.Collection, "BBMASK is not a valid regular expression.")
711 for i in xrange( len( newfiles ) ):
713 if bbmask and bbmask_compiled.search(f):
714 bb.msg.debug(1, bb.msg.domain.Collection, "skipping masked file %s" % f)
719 return (finalfiles, masked)
721 def parse_bbfiles(self, filelist, masked, progressCallback = None):
722 parsed, cached, skipped = 0, 0, 0
723 for i in xrange( len( filelist ) ):
726 bb.msg.debug(1, bb.msg.domain.Collection, "parsing %s" % f)
728 # read a file's metadata
730 fromCache, skip = self.bb_cache.loadData(f, self.configuration.data)
733 bb.msg.debug(2, bb.msg.domain.Collection, "skipping %s" % f)
734 self.bb_cache.skip(f)
736 elif fromCache: cached += 1
740 # Disabled by RP as was no longer functional
741 # allow metadata files to add items to BBFILES
742 #data.update_data(self.pkgdata[f])
743 #addbbfiles = self.bb_cache.getVar('BBFILES', f, False) or None
745 # for aof in addbbfiles.split():
746 # if not files.count(aof):
747 # if not os.path.isabs(aof):
748 # aof = os.path.join(os.path.dirname(f),aof)
751 self.bb_cache.handle_data(f, self.status)
753 # now inform the caller
754 if progressCallback is not None:
755 progressCallback( i + 1, len( filelist ), f, fromCache )
758 self.bb_cache.remove(f)
759 bb.msg.error(bb.msg.domain.Collection, "opening %s: %s" % (f, e))
761 except KeyboardInterrupt:
765 self.bb_cache.remove(f)
766 bb.msg.error(bb.msg.domain.Collection, "%s while parsing %s" % (e, f))
768 self.bb_cache.remove(f)
771 if progressCallback is not None:
772 print "\r" # need newline after Handling Bitbake files message
773 bb.msg.note(1, bb.msg.domain.Collection, "Parsing finished. %d cached, %d parsed, %d skipped, %d masked." % ( cached, parsed, skipped, masked ))
777 #============================================================================#
779 #============================================================================#
782 parser = optparse.OptionParser( version = "BitBake Build Tool Core version %s, %%prog version %s" % ( bb.__version__, __version__ ),
783 usage = """%prog [options] [package ...]
785 Executes the specified task (default is 'build') for a given set of BitBake files.
786 It expects that BBFILES is defined, which is a space seperated list of files to
787 be executed. BBFILES does support wildcards.
788 Default BBFILES are the .bb files in the current directory.""" )
790 parser.add_option( "-b", "--buildfile", help = "execute the task against this .bb file, rather than a package from BBFILES.",
791 action = "store", dest = "buildfile", default = None )
793 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.",
794 action = "store_false", dest = "abort", default = True )
796 parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
797 action = "store_true", dest = "force", default = False )
799 parser.add_option( "-i", "--interactive", help = "drop into the interactive mode also called the BitBake shell.",
800 action = "store_true", dest = "interactive", default = False )
802 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",
803 action = "store", dest = "cmd" )
805 parser.add_option( "-r", "--read", help = "read the specified file before bitbake.conf",
806 action = "append", dest = "file", default = [] )
808 parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
809 action = "store_true", dest = "verbose", default = False )
811 parser.add_option( "-D", "--debug", help = "Increase the debug level. You can specify this more than once.",
812 action = "count", dest="debug", default = 0)
814 parser.add_option( "-n", "--dry-run", help = "don't execute, just go through the motions",
815 action = "store_true", dest = "dry_run", default = False )
817 parser.add_option( "-p", "--parse-only", help = "quit after parsing the BB files (developers only)",
818 action = "store_true", dest = "parse_only", default = False )
820 parser.add_option( "-d", "--disable-psyco", help = "disable using the psyco just-in-time compiler (not recommended)",
821 action = "store_true", dest = "disable_psyco", default = False )
823 parser.add_option( "-s", "--show-versions", help = "show current and preferred versions of all packages",
824 action = "store_true", dest = "show_versions", default = False )
826 parser.add_option( "-e", "--environment", help = "show the global or per-package environment (this is what used to be bbread)",
827 action = "store_true", dest = "show_environment", default = False )
829 parser.add_option( "-g", "--graphviz", help = "emit the dependency trees of the specified packages in the dot syntax",
830 action = "store_true", dest = "dot_graph", default = False )
832 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""",
833 action = "append", dest = "ignored_dot_deps", default = [] )
835 parser.add_option( "-l", "--log-domains", help = """Show debug logging for the specified logging domains""",
836 action = "append", dest = "debug_domains", default = [] )
839 options, args = parser.parse_args( sys.argv )
842 cooker.cook( BBConfiguration( options ), args[1:] )
846 if __name__ == "__main__":
847 print """WARNING, WARNING, WARNING
848 This is a Bitbake from the Unstable/Development Branch.
849 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."""