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
11 # This program is free software; you can redistribute it and/or modify it under
12 # the terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
16 # This program is distributed in the hope that it will be useful, but WITHOUT
17 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License along with
21 # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22 # Place, Suite 330, Boston, MA 02111-1307 USA.
24 import sys, os, getopt, glob, copy, os.path, re, time
25 sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
27 from bb import utils, data, parse, debug, event, fatal
29 import itertools, optparse
31 parsespin = itertools.cycle( r'|/-\\' )
36 #============================================================================#
38 #============================================================================#
39 class BBParsingStatus:
41 The initial idea for this status class is to use the data when it is
42 already loaded instead of loading it from various place over and over
47 self.cache_dirty = False
49 self.bbfile_priority = {}
50 self.bbfile_config_priorities = []
51 self.ignored_dependencies = None
52 self.possible_world = []
53 self.world_target = Set()
59 self.all_depends = Set()
61 def handle_bb_data(self, file_name, bb_data, cached):
63 We will fill the dictionaries with the stuff we
64 need for building the tree more fast
70 self.cache_dirty = True
72 pn = bb.data.getVar('PN', bb_data, True)
73 pv = bb.data.getVar('PV', bb_data, True)
74 pr = bb.data.getVar('PR', bb_data, True)
75 dp = int(bb.data.getVar('DEFAULT_PREFERENCE', bb_data, True) or "0")
76 provides = Set([pn] + (bb.data.getVar("PROVIDES", bb_data, 1) or "").split())
77 depends = (bb.data.getVar("DEPENDS", bb_data, True) or "").split()
80 # build PackageName to FileName lookup table
81 if pn not in self.pkg_pn:
83 self.pkg_pn[pn].append(file_name)
85 # build FileName to PackageName lookup table
86 self.pkg_fn[file_name] = pn
87 self.pkg_pvpr[file_name] = (pv,pr)
88 self.pkg_dp[file_name] = dp
90 # Build forward and reverse provider hashes
91 # Forward: virtual -> [filenames]
92 # Reverse: PN -> [virtuals]
93 if pn not in self.pn_provides:
94 self.pn_provides[pn] = Set()
95 self.pn_provides[pn] |= provides
97 for provide in provides:
98 if provide not in self.providers:
99 self.providers[provide] = []
100 self.providers[provide].append(file_name)
103 self.all_depends.add(dep)
105 # Collect files we may need for possible world-dep
107 if not bb.data.getVar('BROKEN', bb_data, True) and not bb.data.getVar('EXCLUDE_FROM_WORLD', bb_data, True):
108 self.possible_world.append(file_name)
111 #============================================================================#
113 #============================================================================#
116 Manage build statistics for one run
125 print "Build statistics:"
126 print " Attempted builds: %d" % self.attempt
128 print " Failed builds: %d" % self.fail
130 print " Dependencies not satisfied: %d" % self.deps
131 if self.fail or self.deps: return 1
135 #============================================================================#
137 #============================================================================#
138 class BBConfiguration( object ):
140 Manages build options and configurations for one run
142 def __init__( self, options ):
143 for key, val in options.__dict__.items():
144 setattr( self, key, val )
145 self.data = data.init()
147 #============================================================================#
149 #============================================================================#
152 Manages one bitbake build run
155 ParsingStatus = BBParsingStatus # make it visible from the shell
156 Statistics = BBStatistics # make it visible from the shell
158 def __init__( self ):
159 self.build_cache_fail = []
160 self.build_cache = []
161 self.building_list = []
163 self.consider_msgs_cache = []
165 self.stats = BBStatistics()
171 def tryBuildPackage( self, fn, item, the_data ):
172 """Build one package"""
173 bb.event.fire(bb.event.PkgStarted(item, the_data))
175 self.stats.attempt += 1
176 if self.configuration.force:
177 bb.data.setVarFlag('do_%s' % self.configuration.cmd, 'force', 1, the_data)
178 if not self.configuration.dry_run:
179 bb.build.exec_task('do_%s' % self.configuration.cmd, the_data)
180 bb.event.fire(bb.event.PkgSucceeded(item, the_data))
181 self.build_cache.append(fn)
183 except bb.build.FuncFailed:
185 bb.error("task stack execution failed")
186 bb.event.fire(bb.event.PkgFailed(item, the_data))
187 self.build_cache_fail.append(fn)
189 except bb.build.EventException, e:
192 bb.error("%s event exception, aborting" % bb.event.getName(event))
193 bb.event.fire(bb.event.PkgFailed(item, the_data))
194 self.build_cache_fail.append(fn)
197 def tryBuild( self, fn, virtual ):
198 """Build a provider and its dependencies"""
199 if fn in self.building_list:
200 bb.error("%s depends on itself (eventually)" % fn)
201 bb.error("upwards chain is: %s" % (" -> ".join(self.build_path)))
204 the_data = self.pkgdata[fn]
205 item = self.status.pkg_fn[fn]
207 self.building_list.append(fn)
209 pathstr = "%s (%s)" % (item, virtual)
210 self.build_path.append(pathstr)
212 depends_list = (bb.data.getVar('DEPENDS', the_data, 1) or "").split()
213 if self.configuration.verbose:
214 bb.note("current path: %s" % (" -> ".join(self.build_path)))
215 bb.note("dependencies for %s are: %s" % (item, " ".join(depends_list)))
220 depcmd = self.configuration.cmd
221 bbdepcmd = bb.data.getVarFlag('do_%s' % self.configuration.cmd, 'bbdepcmd', the_data)
222 if bbdepcmd is not None:
229 oldcmd = self.configuration.cmd
230 self.configuration.cmd = depcmd
232 for dependency in depends_list:
233 if dependency in self.status.ignored_dependencies:
237 if self.buildProvider( dependency ) == 0:
238 bb.error("dependency %s (for %s) not satisfied" % (dependency,item))
240 if self.configuration.abort:
244 self.configuration.cmd = oldcmd
250 if bb.build.stamp_is_current('do_%s' % self.configuration.cmd, the_data):
251 self.build_cache.append(fn)
254 return self.tryBuildPackage( fn, item, the_data )
257 self.building_list.remove(fn)
258 self.build_path.remove(pathstr)
260 def findBestProvider( self, pn, pkg_pn = None):
262 If there is a PREFERRED_VERSION, find the highest-priority bbfile
263 providing that version. If not, find the latest version provided by
264 an bbfile in the highest-priority set.
267 pkg_pn = self.status.pkg_pn
272 priority = self.status.bbfile_priority[f]
273 if priority not in priorities:
274 priorities[priority] = []
275 priorities[priority].append(f)
276 p_list = priorities.keys()
277 p_list.sort(lambda a, b: a - b)
280 tmp_pn = [priorities[p]] + tmp_pn
282 preferred_file = None
284 localdata = data.createCopy(self.configuration.data)
285 bb.data.setVar('OVERRIDES', "%s:%s" % (pn, data.getVar('OVERRIDES', localdata)), localdata)
286 bb.data.update_data(localdata)
288 preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, localdata, 1)
290 m = re.match('(.*)_(.*)', preferred_v)
292 preferred_v = m.group(1)
293 preferred_r = m.group(2)
297 for file_set in tmp_pn:
299 pv,pr = self.status.pkg_pvpr[f]
300 if preferred_v == pv and (preferred_r == pr or preferred_r == None):
302 preferred_ver = (pv, pr)
307 pv_str = '%s-%s' % (preferred_v, preferred_r)
310 if preferred_file is None:
311 bb.note("preferred version %s of %s not available" % (pv_str, pn))
313 bb.debug(1, "selecting %s as PREFERRED_VERSION %s of package %s" % (preferred_file, pv_str, pn))
317 # get highest priority file set
322 for file_name in files:
323 pv,pr = self.status.pkg_pvpr[file_name]
324 dp = self.status.pkg_dp[file_name]
326 if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pv, pr)) < 0)) or (dp > latest_p):
330 if preferred_file is None:
331 preferred_file = latest_f
332 preferred_ver = latest
334 return (latest,latest_f,preferred_ver, preferred_file)
336 def showVersions( self ):
337 pkg_pn = self.status.pkg_pn
338 preferred_versions = {}
342 for pn in pkg_pn.keys():
343 (last_ver,last_file,pref_ver,pref_file) = self.findBestProvider(pn)
344 preferred_versions[pn] = (pref_ver, pref_file)
345 latest_versions[pn] = (last_ver, last_file)
347 pkg_list = pkg_pn.keys()
351 pref = preferred_versions[p]
352 latest = latest_versions[p]
355 prefstr = pref[0][0] + "-" + pref[0][1]
359 print "%-30s %20s %20s" % (p, latest[0][0] + "-" + latest[0][1],
362 def showEnvironment( self ):
363 """Show the outer or per-package environment"""
364 if self.configuration.buildfile:
366 self.configuration.data, fromCache = self.load_bbfile( self.configuration.buildfile )
368 fatal("Unable to read %s: %s" % ( self.configuration.buildfile, e ))
371 # emit variables and shell functions
373 data.update_data( self.configuration.data )
374 data.emit_env(sys.__stdout__, self.configuration.data, True)
377 # emit the metadata which isnt valid shell
378 for e in self.configuration.data.keys():
379 if data.getVarFlag( e, 'python', self.configuration.data ):
380 sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, data.getVar(e, self.configuration.data, 1)))
382 def buildProvider( self, item ):
385 discriminated = False
387 if item not in self.status.providers:
388 bb.error("Nothing provides %s" % item)
391 all_p = self.status.providers[item]
394 if p in self.build_cache:
395 bb.debug(1, "already built %s in this run\n" % p)
399 preferred_versions = {}
401 # Collate providers by PN
404 pn = self.status.pkg_fn[p]
409 bb.debug(1, "providers for %s are: %s" % (item, pkg_pn.keys()))
411 for pn in pkg_pn.keys():
412 preferred_versions[pn] = self.findBestProvider(pn, pkg_pn)[2:4]
413 eligible.append(preferred_versions[pn][1])
416 if p in self.build_cache_fail:
417 bb.debug(1, "rejecting already-failed %s" % p)
420 if len(eligible) == 0:
421 bb.error("no eligible providers for %s" % item)
424 # look to see if one of them is already staged, or marked as preferred.
425 # if so, bump it to the head of the queue
427 the_data = self.pkgdata[p]
428 pn = bb.data.getVar('PN', the_data, 1)
429 pv = bb.data.getVar('PV', the_data, 1)
430 pr = bb.data.getVar('PR', the_data, 1)
431 tmpdir = bb.data.getVar('TMPDIR', the_data, 1)
432 stamp = '%s/stamps/%s-%s-%s.do_populate_staging' % (tmpdir, pn, pv, pr)
433 if os.path.exists(stamp):
434 (newvers, fn) = preferred_versions[pn]
435 if not fn in eligible:
436 # package was made ineligible by already-failed check
438 oldver = "%s-%s" % (pv, pr)
439 newver = '-'.join(newvers)
440 if (newver != oldver):
441 extra_chat = "; upgrading from %s to %s" % (oldver, newver)
444 if self.configuration.verbose:
445 bb.note("selecting already-staged %s to satisfy %s%s" % (pn, item, extra_chat))
447 eligible = [fn] + eligible
451 prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % item, self.configuration.data, 1)
453 self.preferred[item] = prefervar
455 if item in self.preferred:
457 pn = self.status.pkg_fn[p]
458 if self.preferred[item] == pn:
459 if self.configuration.verbose:
460 bb.note("selecting %s to satisfy %s due to PREFERRED_PROVIDERS" % (pn, item))
462 eligible = [p] + eligible
466 if len(eligible) > 1 and discriminated == False:
467 if item not in self.consider_msgs_cache:
470 providers_list.append(self.status.pkg_fn[fn])
471 bb.note("multiple providers are available (%s);" % ", ".join(providers_list))
472 bb.note("consider defining PREFERRED_PROVIDER_%s" % item)
473 self.consider_msgs_cache.append(item)
476 # run through the list until we find one that we can build
478 bb.debug(2, "selecting %s to satisfy %s" % (fn, item))
479 if self.tryBuild(fn, item):
482 bb.note("no buildable providers for %s" % item)
485 def buildDepgraph( self ):
486 all_depends = self.status.all_depends
487 pn_provides = self.status.pn_provides
489 def calc_bbfile_priority(filename):
490 for (regex, pri) in self.status.bbfile_config_priorities:
491 if regex.match(filename):
495 # Handle PREFERRED_PROVIDERS
496 for p in (bb.data.getVar('PREFERRED_PROVIDERS', self.configuration.data, 1) or "").split():
497 (providee, provider) = p.split(':')
498 if providee in self.preferred and self.preferred[providee] != provider:
499 bb.error("conflicting preferences for %s: both %s and %s specified" % (providee, provider, self.preferred[providee]))
500 self.preferred[providee] = provider
502 # Calculate priorities for each file
503 for p in self.pkgdata.keys():
504 self.status.bbfile_priority[p] = calc_bbfile_priority(p)
506 # Build package list for "bitbake world"
507 bb.debug(1, "collating packages for \"world\"")
508 for f in self.status.possible_world:
510 pn = self.status.pkg_fn[f]
512 for p in pn_provides[pn]:
513 if p.startswith('virtual/'):
514 bb.debug(2, "skipping %s due to %s provider starting with virtual/" % (f, p))
517 for pf in self.status.providers[p]:
518 if self.status.pkg_fn[pf] != pn:
519 bb.debug(2, "skipping %s due to both us and %s providing %s" % (f, pf, p))
523 self.status.world_target.add(pn)
525 # drop reference count now
526 self.status.possible_world = None
527 self.status.all_depends = None
529 def myProgressCallback( self, x, y, f, file_data, from_cache ):
530 # feed the status with new input
531 self.status.handle_bb_data(f, file_data, from_cache)
535 if os.isatty(sys.stdout.fileno()):
536 sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
540 sys.stdout.write("Parsing .bb files, please wait...")
543 sys.stdout.write("done.")
546 def interactiveMode( self ):
547 """Drop off into a shell"""
550 except ImportError, details:
551 bb.fatal("Sorry, shell not available (%s)" % details )
553 bb.data.update_data( self.configuration.data )
557 def parseConfigurationFile( self, afile ):
559 self.configuration.data = bb.parse.handle( afile, self.configuration.data )
561 bb.fatal( "Unable to open %s" % afile )
562 except bb.parse.ParseError, details:
563 bb.fatal( "Unable to parse %s (%s)" % (afile, details) )
565 def handleCollections( self, collections ):
566 """Handle collections"""
568 collection_list = collections.split()
569 for c in collection_list:
570 regex = bb.data.getVar("BBFILE_PATTERN_%s" % c, self.configuration.data, 1)
572 bb.error("BBFILE_PATTERN_%s not defined" % c)
574 priority = bb.data.getVar("BBFILE_PRIORITY_%s" % c, self.configuration.data, 1)
576 bb.error("BBFILE_PRIORITY_%s not defined" % c)
579 cre = re.compile(regex)
581 bb.error("BBFILE_PATTERN_%s \"%s\" is not a valid regular expression" % (c, regex))
585 self.status.bbfile_config_priorities.append((cre, pri))
587 bb.error("invalid value for BBFILE_PRIORITY_%s: \"%s\"" % (c, priority))
590 def cook( self, configuration, args ):
591 self.configuration = configuration
593 if not self.configuration.cmd:
594 self.configuration.cmd = "build"
596 if self.configuration.debug:
597 bb.debug_level = self.configuration.debug
599 self.configuration.data = bb.data.init()
601 for f in self.configuration.file:
602 self.parseConfigurationFile( f )
604 self.parseConfigurationFile( os.path.join( "conf", "bitbake.conf" ) )
606 if self.configuration.show_environment:
607 self.showEnvironment()
610 # inject custom variables
611 if not bb.data.getVar("BUILDNAME", self.configuration.data):
612 bb.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), self.configuration.data)
613 bb.data.setVar("BUILDSTART", time.strftime('%m/%d/%Y %H:%M:%S',time.gmtime()),self.configuration.data)
615 buildname = bb.data.getVar("BUILDNAME", self.configuration.data)
617 if self.configuration.interactive:
618 self.interactiveMode()
620 if self.configuration.buildfile is not None:
621 bf = os.path.abspath( self.configuration.buildfile )
623 bbfile_data = bb.parse.handle(bf, self.configuration.data)
625 bb.fatal("Unable to open %s" % bf)
627 item = bb.data.getVar('PN', bbfile_data, 1)
629 self.tryBuildPackage( bf, item, bbfile_data )
630 except bb.build.EventException:
631 bb.error( "Build of '%s' failed" % item )
633 sys.exit( self.stats.show() )
635 # initialise the parsing status now we know we will need deps
636 self.status = BBParsingStatus()
638 ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or ""
639 self.status.ignored_dependencies = Set( ignore.split() )
641 self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) )
645 if not pkgs_to_build:
647 pkgs_to_build.extend(args)
648 if not pkgs_to_build:
649 bbpkgs = bb.data.getVar('BBPKGS', self.configuration.data, 1)
651 pkgs_to_build = bbpkgs.split()
652 if not pkgs_to_build and not self.configuration.show_versions \
653 and not self.configuration.interactive \
654 and not self.configuration.show_environment:
655 print "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help'"
656 print "for usage information."
659 # Import Psyco if available and not disabled
660 if not self.configuration.disable_psyco:
665 bb.note("Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance.")
667 psyco.bind( self.collect_bbfiles )
669 bb.note("You have disabled Psyco. This decreases performance.")
672 bb.debug(1, "collecting .bb files")
673 self.collect_bbfiles( self.myProgressCallback )
674 bb.debug(1, "parsing complete")
677 if self.configuration.parse_only:
678 print "Requested parsing .bb files only. Exiting."
681 bb.data.update_data( self.configuration.data )
684 if self.configuration.show_versions:
687 if 'world' in pkgs_to_build:
688 pkgs_to_build.remove('world')
689 for t in self.status.world_target:
690 pkgs_to_build.append(t)
692 bb.event.fire(bb.event.BuildStarted(buildname, pkgs_to_build, self.configuration.data))
694 for k in pkgs_to_build:
697 if self.buildProvider( k ) == 0:
700 except bb.build.EventException:
701 bb.error("Build of " + k + " failed")
705 if self.configuration.abort:
708 bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, self.configuration.data))
710 sys.exit( self.stats.show() )
712 except KeyboardInterrupt:
713 print "\nNOTE: KeyboardInterrupt - Build not completed."
716 def get_bbfiles( self, path = os.getcwd() ):
717 """Get list of default .bb files by reading out the current directory"""
718 contents = os.listdir(path)
721 (root, ext) = os.path.splitext(f)
723 bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
726 def find_bbfiles( self, path ):
727 """Find all the .bb files in a directory (uses find)"""
728 findcmd = 'find ' + path + ' -name *.bb | grep -v SCCS/'
730 finddata = os.popen(findcmd)
733 return finddata.readlines()
735 def deps_clean(self, d):
736 depstr = data.getVar('__depends', d)
738 deps = depstr.split(" ")
740 (f,old_mtime_s) = dep.split("@")
741 old_mtime = int(old_mtime_s)
742 new_mtime = parse.cached_mtime(f)
743 if (new_mtime > old_mtime):
747 def load_bbfile( self, bbfile ):
748 """Load and parse one .bb build file"""
750 if not self.cache in [None, '']:
752 cache_mtime = data.init_db_mtime(self.cache, bbfile)
753 file_mtime = parse.cached_mtime(bbfile)
755 if file_mtime > cache_mtime:
756 #print " : '%s' dirty. reparsing..." % bbfile
759 #print " : '%s' clean. loading from cache..." % bbfile
760 cache_data = data.init_db( self.cache, bbfile, False )
761 if self.deps_clean(cache_data):
762 return cache_data, True
764 topdir = data.getVar('TOPDIR', self.configuration.data)
766 topdir = os.path.abspath(os.getcwd())
768 data.setVar('TOPDIR', topdir, self.configuration)
769 bbfile = os.path.abspath(bbfile)
770 bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
771 # expand tmpdir to include this topdir
772 data.setVar('TMPDIR', data.getVar('TMPDIR', self.configuration.data, 1) or "", self.configuration.data)
773 # set topdir to location of .bb file
775 #data.setVar('TOPDIR', topdir, cfg)
777 oldpath = os.path.abspath(os.getcwd())
779 bb = data.init_db(self.cache,bbfile, True, self.configuration.data)
781 parse.handle(bbfile, bb) # read .bb data
782 if not self.cache in [None, '']:
783 bb.commit(parse.cached_mtime(bbfile)) # write cache
789 def collect_bbfiles( self, progressCallback ):
790 """Collect all available .bb build files"""
791 self.cb = progressCallback
792 parsed, cached, skipped, masked = 0, 0, 0, 0
793 self.cache = bb.data.getVar( "CACHE", self.configuration.data, 1 )
794 self.pkgdata = data.pkgdata( not self.cache in [None, ''], self.cache, self.configuration.data )
796 if not self.cache in [None, '']:
797 if self.cb is not None:
798 print "NOTE: Using cache in '%s'" % self.cache
800 os.stat( self.cache )
802 bb.mkdirhier( self.cache )
804 if self.cb is not None:
805 print "NOTE: Not using a cache. Set CACHE = <directory> to enable."
806 files = (data.getVar( "BBFILES", self.configuration.data, 1 ) or "").split()
807 data.setVar("BBFILES", " ".join(files), self.configuration.data)
810 files = self.get_bbfiles()
813 bb.error("no files to build.")
818 dirfiles = self.find_bbfiles(f)
822 newfiles += glob.glob(f) or [ f ]
824 bbmask = bb.data.getVar('BBMASK', self.configuration.data, 1) or ""
826 bbmask_compiled = re.compile(bbmask)
827 except sre_constants.error:
828 bb.fatal("BBMASK is not a valid regular expression.")
830 for i in xrange( len( newfiles ) ):
832 if bbmask and bbmask_compiled.search(f):
833 bb.debug(1, "bbmake: skipping %s" % f)
836 debug(1, "bbmake: parsing %s" % f)
838 # read a file's metadata
840 bb_data, fromCache = self.load_bbfile(f)
841 if fromCache: cached += 1
844 if bb_data is not None:
845 # allow metadata files to add items to BBFILES
846 #data.update_data(self.pkgdata[f])
847 addbbfiles = data.getVar('BBFILES', bb_data) or None
849 for aof in addbbfiles.split():
850 if not files.count(aof):
851 if not os.path.isabs(aof):
852 aof = os.path.join(os.path.dirname(f),aof)
854 for var in bb_data.keys():
855 if data.getVarFlag(var, "handler", bb_data) and data.getVar(var, bb_data):
856 event.register(data.getVar(var, bb_data))
857 self.pkgdata[f] = bb_data
859 # now inform the caller
860 if self.cb is not None:
861 self.cb( i + 1, len( newfiles ), f, bb_data, fromCache )
864 bb.error("opening %s: %s" % (f, e))
866 except bb.parse.SkipPackage:
869 except KeyboardInterrupt:
872 bb.error("%s while parsing %s" % (e, f))
874 if self.cb is not None:
875 print "\rNOTE: Parsing finished. %d cached, %d parsed, %d skipped, %d masked." % ( cached, parsed, skipped, masked ),
877 #============================================================================#
879 #============================================================================#
881 if __name__ == "__main__":
883 parser = optparse.OptionParser( version = "BitBake Build Tool Core version %s, %%prog version %s" % ( bb.__version__, __version__ ),
884 usage = """%prog [options] [package ...]
886 Executes the specified task (default is 'build') for a given set of BitBake files.
887 It expects that BBFILES is defined, which is a space seperated list of files to
888 be executed. BBFILES does support wildcards.
889 Default BBFILES are the .bb files in the current directory.""" )
891 parser.add_option( "-b", "--buildfile", help = "execute the task against this .bb file, rather than a package from BBFILES.",
892 action = "store", dest = "buildfile", default = None )
894 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.",
895 action = "store_false", dest = "abort", default = True )
897 parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
898 action = "store_true", dest = "force", default = False )
900 parser.add_option( "-i", "--interactive", help = "drop into the interactive mode.",
901 action = "store_true", dest = "interactive", default = False )
903 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)",
904 action = "store", dest = "cmd", default = "build" )
906 parser.add_option( "-r", "--read", help = "read the specified file before bitbake.conf",
907 action = "append", dest = "file", default = [] )
909 parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
910 action = "store_true", dest = "verbose", default = False )
912 parser.add_option( "-D", "--debug", help = "Increase the debug level",
913 action = "count", dest="debug", default = 0)
915 parser.add_option( "-n", "--dry-run", help = "don't execute, just go through the motions",
916 action = "store_true", dest = "dry_run", default = False )
918 parser.add_option( "-p", "--parse-only", help = "quit after parsing the BB files (developers only)",
919 action = "store_true", dest = "parse_only", default = False )
921 parser.add_option( "-d", "--disable-psyco", help = "disable using the psyco just-in-time compiler (not recommended)",
922 action = "store_true", dest = "disable_psyco", default = False )
924 parser.add_option( "-s", "--show-versions", help = "show current and preferred versions of all packages",
925 action = "store_true", dest = "show_versions", default = False )
927 parser.add_option( "-e", "--environment", help = "show the global or per-package environment (this is what used to be bbread)",
928 action = "store_true", dest = "show_environment", default = False )
930 options, args = parser.parse_args( sys.argv )
933 cooker.cook( BBConfiguration( options ), args[1:] )