Rework the way we handle do_clean and do_mrproper so that the .oeclass that defines...
[bitbake.git] / bin / bitbake
1 #!/usr/bin/env python
2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4 #
5 # Copyright (C) 2003, 2004  Chris Larson
6 # Copyright (C) 2003, 2004  Phil Blundell
7 #
8 # This program is free software; you can redistribute it and/or modify it under
9 # the terms of the GNU General Public License as published by the Free Software
10 # Foundation; either version 2 of the License, or (at your option) any later
11 # version.
12
13 # This program is distributed in the hope that it will be useful, but WITHOUT
14 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License along with
18 # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 # Place, Suite 330, Boston, MA 02111-1307 USA. 
20
21 import sys, os, getopt, glob, copy, os.path, re
22 sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
23 import bb
24 from bb import make
25 from sets import Set
26 import itertools, optparse
27
28 parsespin = itertools.cycle( r'|/-\\' )
29
30 __version__ = 1.2
31 __build_cache_fail = []
32 __build_cache = []
33 __building_list = []
34 __build_path = []
35
36 __preferred = {}
37 __world_target = Set()
38 __ignored_dependencies = Set()
39
40 __stats = {}
41
42 bbfile_config_priorities = []
43 bbfile_priority = {}
44 bbdebug = 0
45
46 def handle_options( args ):
47     parser = optparse.OptionParser( version = "BitBake Build Tool Core version %s, %%prog version %s" % ( bb.__version__, __version__ ),
48     usage = """%prog [options] [package ...]
49
50 Executes the specified task (default is 'build') for a given set of BitBake files.
51 It expects that BBFILES is defined, which is a space seperated list of files to
52 be executed.  BBFILES does support wildcards.
53 Default BBFILES are the .bb files in the current directory.""" )
54
55     parser.add_option( "-b", "--buildfile", help = "execute the task against this .bb file, rather than a package from BBFILES.",
56                action = "store", dest = "buildfile", default = None )
57
58     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.",
59                action = "store_false", dest = "abort", default = True )
60
61     parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
62                action = "store_true", dest = "force", default = False )
63
64
65     parser.add_option( "-c", "--cmd", help = "Specify task to execute",
66                action = "store", dest = "cmd", default = "build" )
67
68     parser.add_option( "-r", "--read", help = "read the specified file before bitbake.conf",
69                action = "append", dest = "file", default = [] )
70
71     parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
72                action = "store_true", dest = "verbose", default = False )
73
74     parser.add_option( "-n", "--dry-run", help = "don't execute, just go through the motions",
75                action = "store_true", dest = "dry_run", default = False )
76
77     parser.add_option( "-p", "--parse-only", help = "quit after parsing the BB files (developers only)",
78                action = "store_true", dest = "parse_only", default = False )
79
80     parser.add_option( "-d", "--disable-psyco", help = "disable using the psyco just-in-time compiler (not recommended)",
81                action = "store_true", dest = "disable_psyco", default = False )
82
83     parser.add_option( "-s", "--show-versions", help = "show current and preferred versions of all packages",
84                action = "store_true", dest = "show_versions", default = False )
85
86     options, args = parser.parse_args( args )
87     return options, args[1:]
88
89 def try_build(fn, virtual):
90     if fn in __building_list:
91         bb.error("%s depends on itself (eventually)" % fn)
92         bb.error("upwards chain is: %s" % (" -> ".join(__build_path)))
93         return False
94
95     __building_list.append(fn)
96
97     the_data = make.pkgdata[fn]
98     item = bb.data.getVar('PN', the_data, 1)
99     pathstr = "%s (%s)" % (item, virtual)
100     __build_path.append(pathstr)
101
102     depends_list = (bb.data.getVar('DEPENDS', the_data, 1) or "").split()
103     if make.options.verbose:
104         bb.note("current path: %s" % (" -> ".join(__build_path)))
105         bb.note("dependencies for %s are: %s" % (item, " ".join(depends_list)))
106
107     try:
108         failed = False
109
110         depcmd = make.options.cmd
111         bbdepcmd = bb.data.getVarFlag('do_%s' % make.options.cmd, 'bbdepcmd', make.pkgdata[fn])
112         if bbdepcmd is not None:
113             if bbdepcmd == "":
114                 depcmd = None
115             else:
116                 depcmd = bbdepcmd
117
118         if depcmd:
119             oldcmd = make.options.cmd
120             make.options.cmd = depcmd
121
122         for d in depends_list:
123             if d in __ignored_dependencies:
124                 continue
125             if not depcmd:
126                 continue
127             if buildPackage(d) == 0:
128                 bb.error("dependency %s (for %s) not satisfied" % (d,item))
129                 failed = True
130                 if make.options.abort:
131                     break
132
133         if depcmd:
134             make.options.cmd = oldcmd
135
136         if failed:
137             __stats["deps"] += 1
138             return False
139
140         bb.event.fire(bb.event.PkgStarted(item, make.pkgdata[fn]))
141         try:
142             __stats["attempt"] += 1
143             if not make.options.dry_run:
144                 bb.build.exec_task('do_%s' % make.options.cmd, make.pkgdata[fn])
145             bb.event.fire(bb.event.PkgSucceeded(item, make.pkgdata[fn]))
146             __build_cache.append(fn)
147             return True
148         except bb.build.FuncFailed:
149             __stats["fail"] += 1
150             bb.error("task stack execution failed")
151             bb.event.fire(bb.event.PkgFailed(item, make.pkgdata[fn]))
152             __build_cache_fail.append(fn)
153             raise
154         except bb.build.EventException:
155             __stats["fail"] += 1
156             (type, value, traceback) = sys.exc_info()
157             e = value.event
158             bb.error("%s event exception, aborting" % bb.event.getName(e))
159             bb.event.fire(bb.event.PkgFailed(item, make.pkgdata[fn]))
160             __build_cache_fail.append(fn)
161             raise
162     finally:
163         __building_list.remove(fn)
164         __build_path.remove(pathstr)
165
166 def showVersions():
167     pkg_pn = {}
168     preferred_versions = {}
169     latest_versions = {}
170
171     for p in make.pkgdata.keys():
172         pn = bb.data.getVar('PN', make.pkgdata[p], 1)
173         if not pkg_pn.has_key(pn):
174             pkg_pn[pn] = []
175         pkg_pn[pn].append(p)
176     
177     # Sort by priority
178     for pn in pkg_pn.keys():
179         files = pkg_pn[pn]
180         priorities = {}
181         for f in files:
182             priority = bbfile_priority[f]
183             if not priorities.has_key(priority):
184                 priorities[priority] = []
185             priorities[priority].append(f)
186         p_list = priorities.keys()
187         p_list.sort(lambda a, b: a - b)
188         pkg_pn[pn] = []
189         for p in p_list:
190             pkg_pn[pn] = [ priorities[p] ] + pkg_pn[pn]
191
192     # If there is a PREFERRED_VERSION, find the highest-priority bbfile providing that
193     # version.  If not, find the latest version provided by an bbfile in the
194     # highest-priority set.
195     for pn in pkg_pn.keys():
196         preferred_file = None
197         
198         preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, make.cfg, 1)
199         if preferred_v:
200             preferred_r = None
201             m = re.match('(.*)_(.*)', preferred_v)
202             if m:
203                 preferred_v = m.group(1)
204                 preferred_r = m.group(2)
205                 
206             for file_set in pkg_pn[pn]:
207                 for f in file_set:
208                     the_data = make.pkgdata[f]
209                     pv = bb.data.getVar('PV', the_data, 1)
210                     pr = bb.data.getVar('PR', the_data, 1)
211                     if preferred_v == pv and (preferred_r == pr or preferred_r == None):
212                         preferred_file = f
213                         preferred_ver = (pv, pr)
214                         break
215                 if preferred_file:
216                     break
217             if preferred_r:
218                 pv_str = '%s-%s' % (preferred_v, preferred_r)
219             else:
220                 pv_str = preferred_v
221             if preferred_file is None:
222                 bb.note("preferred version %s of %s not available" % (pv_str, pn))
223             else:
224                 bb.debug(1, "selecting %s as PREFERRED_VERSION %s of package %s" % (preferred_file, pv_str, pn))
225                
226         # get highest priority file set
227         files = pkg_pn[pn][0]
228         latest = None
229         latest_p = 0
230         latest_f = None
231         for f in files:
232             the_data = make.pkgdata[f]
233             pv = bb.data.getVar('PV', the_data, 1)
234             pr = bb.data.getVar('PR', the_data, 1)
235             dp = int(bb.data.getVar('DEFAULT_PREFERENCE', the_data, 1) or "0")
236
237             if (latest is None) or ((latest_p == dp) and (make.vercmp(latest, (pv, pr)) < 0)) or (dp > latest_p):
238                 latest = (pv, pr)
239                 latest_f = f
240                 latest_p = dp
241         if preferred_file is None:
242             preferred_file = latest_f
243             preferred_ver = latest
244             
245         preferred_versions[pn] = (preferred_ver, preferred_file)
246         latest_versions[pn] = (latest, latest_f)
247
248     pkg_list = pkg_pn.keys()
249     pkg_list.sort()
250     
251     for p in pkg_list:
252         pref = preferred_versions[p]
253         latest = latest_versions[p]
254
255         if pref != latest:
256             prefstr = pref[0][0] + "-" + pref[0][1]
257         else:
258             prefstr = ""
259
260         print "%-30s %20s %20s" % (p, latest[0][0] + "-" + latest[0][1],
261                                    prefstr)
262
263 def buildPackage(item):
264     fn = None
265
266     discriminated = False
267
268     if not providers.has_key(item):
269         bb.error("Nothing provides %s" % item)
270         return 0
271
272     all_p = providers[item]
273
274     for p in all_p:
275         if p in __build_cache:
276             bb.debug(1, "already built %s in this run\n" % p)
277             return 1
278
279     eligible = []
280     preferred_versions = {}
281
282     # Collate providers by PN
283     pkg_pn = {}
284     for p in all_p:
285         the_data = make.pkgdata[p]
286         pn = bb.data.getVar('PN', the_data, 1)
287         if not pkg_pn.has_key(pn):
288             pkg_pn[pn] = []
289         pkg_pn[pn].append(p)
290
291     bb.debug(1, "providers for %s are: %s" % (item, pkg_pn.keys()))
292
293     # Sort by priority
294     for pn in pkg_pn.keys():
295         files = pkg_pn[pn]
296         priorities = {}
297         for f in files:
298             priority = bbfile_priority[f]
299             if not priorities.has_key(priority):
300                 priorities[priority] = []
301             priorities[priority].append(f)
302         p_list = priorities.keys()
303         p_list.sort(lambda a, b: a - b)
304         pkg_pn[pn] = []
305         for p in p_list:
306             pkg_pn[pn] = [ priorities[p] ] + pkg_pn[pn]
307
308     # If there is a PREFERRED_VERSION, find the highest-priority bbfile providing that
309     # version.  If not, find the latest version provided by an bbfile in the
310     # highest-priority set.
311     for pn in pkg_pn.keys():
312         preferred_file = None
313         
314         preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, make.cfg, 1)
315         if preferred_v:
316             preferred_r = None
317             m = re.match('(.*)_(.*)', preferred_v)
318             if m:
319                 preferred_v = m.group(1)
320                 preferred_r = m.group(2)
321                 
322             for file_set in pkg_pn[pn]:
323                 for f in file_set:
324                     the_data = make.pkgdata[f]
325                     pv = bb.data.getVar('PV', the_data, 1)
326                     pr = bb.data.getVar('PR', the_data, 1)
327                     if preferred_v == pv and (preferred_r == pr or preferred_r == None):
328                         preferred_file = f
329                         preferred_ver = (pv, pr)
330                         break
331                 if preferred_file:
332                     break
333             if preferred_r:
334                 pv_str = '%s-%s' % (preferred_v, preferred_r)
335             else:
336                 pv_str = preferred_v
337             if preferred_file is None:
338                 bb.note("preferred version %s of %s not available" % (pv_str, pn))
339             else:
340                 bb.debug(1, "selecting %s as PREFERRED_VERSION %s of package %s" % (preferred_file, pv_str, pn))
341                 
342         if preferred_file is None:
343             # get highest priority file set
344             files = pkg_pn[pn][0]
345             latest = None
346             latest_p = 0
347             latest_f = None
348             for f in files:
349                 the_data = make.pkgdata[f]
350                 pv = bb.data.getVar('PV', the_data, 1)
351                 pr = bb.data.getVar('PR', the_data, 1)
352                 dp = int(bb.data.getVar('DEFAULT_PREFERENCE', the_data, 1) or "0")
353
354                 if (latest is None) or ((latest_p == dp) and (make.vercmp(latest, (pv, pr)) < 0)) or (dp > latest_p):
355                     latest = (pv, pr)
356                     latest_f = f
357                     latest_p = dp
358             preferred_file = latest_f
359             preferred_ver = latest
360             
361             bb.debug(1, "selecting %s as latest version of provider %s" % (preferred_file, pn))
362
363         preferred_versions[pn] = (preferred_ver, preferred_file)
364         eligible.append(preferred_file)
365
366     for p in eligible:
367         if p in __build_cache_fail:
368             bb.debug(1, "rejecting already-failed %s" % p)
369             eligible.remove(p)
370
371     if len(eligible) == 0:
372         bb.error("no eligible providers for %s" % item)
373         return 0
374
375     # look to see if one of them is already staged, or marked as preferred.
376     # if so, bump it to the head of the queue
377     for p in all_p:
378         the_data = make.pkgdata[p]
379         pn = bb.data.getVar('PN', the_data, 1)
380         pv = bb.data.getVar('PV', the_data, 1)
381         pr = bb.data.getVar('PR', the_data, 1)
382         tmpdir = bb.data.getVar('TMPDIR', the_data, 1)
383         stamp = '%s/stamps/%s-%s-%s.do_populate_staging' % (tmpdir, pn, pv, pr)
384         if os.path.exists(stamp):
385             (newvers, fn) = preferred_versions[pn]
386             if not fn in eligible:
387                 # package was made ineligible by already-failed check
388                 continue
389             oldver = "%s-%s" % (pv, pr)
390             newver = '-'.join(newvers)
391             if (newver != oldver):
392                 extra_chat = "; upgrading from %s to %s" % (oldver, newver)
393             else:
394                 extra_chat = ""
395             if make.options.verbose:
396                 bb.note("selecting already-staged %s to satisfy %s%s" % (pn, item, extra_chat))
397             eligible.remove(fn)
398             eligible = [fn] + eligible
399             discriminated = True
400             break
401
402     prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % item, make.cfg, 1)
403     if prefervar:
404         __preferred[item] = prefervar
405
406     if __preferred.has_key(item):
407         for p in eligible:
408             the_data = make.pkgdata[p]
409             pn = bb.data.getVar('PN', the_data, 1)
410             if __preferred[item] == pn:
411                 if make.options.verbose:
412                     bb.note("selecting %s to satisfy %s due to PREFERRED_PROVIDERS" % (pn, item))
413                 eligible.remove(p)
414                 eligible = [p] + eligible
415                 discriminated = True
416                 break
417
418     if len(eligible) > 1 and discriminated == False:
419         providers_list = []
420         for fn in eligible:
421             providers_list.append(bb.data.getVar('PN', make.pkgdata[fn], 1))
422         bb.note("multiple providers are available (%s);" % ", ".join(providers_list))
423         bb.note("consider defining PREFERRED_PROVIDER_%s" % item)
424
425     # run through the list until we find one that we can build
426     for fn in eligible:
427         bb.debug(2, "selecting %s to satisfy %s" % (fn, item))
428         if try_build(fn, item):
429             return 1
430
431     bb.note("no buildable providers for %s" % item)
432     return 0
433
434 def build_depgraph():
435     all_depends = Set()
436     pn_provides = {}
437
438     def progress(p):
439         if bbdebug or progress.p == p: return 
440         progress.p = p
441         if os.isatty(sys.stdout.fileno()):
442             sys.stdout.write("\rNOTE: Building provider hash: [%s%s] (%02d%%)" % ( "#" * (p/5), " " * ( 20 - p/5 ), p ) )
443             sys.stdout.flush()
444         else:
445             if p == 0:
446                 sys.stdout.write("NOTE: Building provider hash, please wait...\n")
447             if p == 100:
448                 sys.stdout.write("done.\n")
449     progress.p = 0
450
451     def calc_bbfile_priority(filename):
452         for (regex, pri) in bbfile_config_priorities:
453             if regex.match(filename):
454                 return pri
455         return 0
456
457     # Handle PREFERRED_PROVIDERS
458     for p in (bb.data.getVar('PREFERRED_PROVIDERS', make.cfg, 1) or "").split():
459         (providee, provider) = p.split(':')
460         if __preferred.has_key(providee) and __preferred[providee] != provider:
461             bb.error("conflicting preferences for %s: both %s and %s specified" % (providee, provider, __preferred[providee]))
462         __preferred[providee] = provider
463
464     # Calculate priorities for each file
465     for p in make.pkgdata.keys():
466         bbfile_priority[p] = calc_bbfile_priority(p)
467     
468     n = len(make.pkgdata.keys())
469     i = 0
470
471     op = -1
472
473     bb.debug(1, "BBMAKE building providers hashes")
474
475     # Build forward and reverse provider hashes
476     # Forward: virtual -> [filenames]
477     # Reverse: PN -> [virtuals]
478     for f in make.pkgdata.keys():
479         d = make.pkgdata[f]
480
481         pn = bb.data.getVar('PN', d, 1)
482         provides = Set([pn] + (bb.data.getVar("PROVIDES", d, 1) or "").split())
483
484         if not pn_provides.has_key(pn):
485             pn_provides[pn] = Set()
486         pn_provides[pn] |= provides
487
488         for provide in provides:
489             if not providers.has_key(provide):
490                 providers[provide] = []
491             providers[provide].append(f)
492
493         deps = (bb.data.getVar("DEPENDS", d, 1) or "").split()
494         for dep in deps:
495             all_depends.add(dep)
496
497         i += 1
498         p = (100 * i) / n
499         if p != op:
500             op = p
501             progress(p)
502
503     if bbdebug == 0:
504         sys.stdout.write("\n")
505
506     # Build package list for "bitbake world"
507     bb.debug(1, "BBMAKE collating packages for \"world\"")
508     for f in make.pkgdata.keys():
509         d = make.pkgdata[f]
510         if bb.data.getVar('BROKEN', d, 1) or bb.data.getVar('EXCLUDE_FROM_WORLD', d, 1):
511             bb.debug(2, "BBMAKE skipping %s due to BROKEN/EXCLUDE_FROM_WORLD" % f)
512             continue
513         terminal = True
514         pn = bb.data.getVar('PN', d, 1)
515         for p in pn_provides[pn]:
516             if p.startswith('virtual/'):
517                 bb.debug(2, "BBMAKE skipping %s due to %s provider starting with virtual/" % (f, p))
518                 terminal = False
519                 break
520             for pf in providers[p]:
521                 if bb.data.getVar('PN', make.pkgdata[pf], 1) != pn:
522                     bb.debug(2, "BBMAKE skipping %s due to both us and %s providing %s" % (f, pf, p))
523                     terminal = False
524                     break
525         if terminal:
526             __world_target.add(pn)
527
528 def myProgressCallback( x, y, f ):
529     if bbdebug > 0:
530         return
531     if os.isatty(sys.stdout.fileno()):
532         sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
533         sys.stdout.flush()
534     else:
535         if x == 1:
536             sys.stdout.write("Parsing .bb files, please wait...")
537             sys.stdout.flush()
538         if x == y:
539             sys.stdout.write("done.")
540             sys.stdout.flush()
541
542 def executeOneBB( fn ):
543         try:
544             d = bb.parse.handle(fn, make.cfg)
545         except IOError:
546             bb.fatal("Unable to open %s" % fn)
547
548         name = bb.data.getVar('PN', d, 1)
549         bb.event.fire(bb.event.PkgStarted(name, d))
550         try:
551             __stats["attempt"] += 1
552             if not make.options.dry_run:
553                 bb.build.exec_task('do_%s' % make.options.cmd, d)
554             bb.event.fire(bb.event.PkgSucceeded(name, d))
555             __build_cache.append(fn)
556         except bb.build.FuncFailed:
557             __stats["fail"] += 1
558             bb.error("task stack execution failed")
559             bb.event.fire(bb.event.PkgFailed(name, d))
560             __build_cache_fail.append(fn)
561         except bb.build.EventException:
562             __stats["fail"] += 1
563             (type, value, traceback) = sys.exc_info()
564             e = value.event
565             bb.error("%s event exception, aborting" % bb.event.getName(e))
566             bb.event.fire(bb.event.PkgFailed(name, d))
567             __build_cache_fail.append(fn)
568
569 #
570 # main
571 #
572
573 __stats["attempt"] = 0
574 __stats["success"] = 0
575 __stats["fail"] = 0
576 __stats["deps"] = 0
577
578 def printStats( ):
579     print "Build statistics:"
580     print "  Attempted builds: %d" % __stats["attempt"]
581     if __stats["fail"] != 0:
582         print "  Failed builds: %d" % __stats["fail"]
583     if __stats["deps"] != 0:
584         print "  Dependencies not satisfied: %d" % __stats["deps"]
585     if __stats["fail"] != 0 or __stats["deps"] != 0:
586         sys.exit(1)
587     sys.exit(0)
588
589 if __name__ == "__main__":
590
591     if "BBDEBUG" in os.environ:
592         bbdebug = int(os.environ["BBDEBUG"])
593
594     make.options, args = handle_options( sys.argv )
595
596     if not make.options.cmd:
597         make.options.cmd = "build"
598
599
600     make.pkgdata = {}
601     make.cfg = bb.data.init()
602     providers = {}
603
604     for f in make.options.file:
605         try:
606             make.cfg = bb.parse.handle(f, make.cfg)
607         except IOError:
608             bb.fatal("Unable to open %s" % f)
609
610     try:
611         make.cfg = bb.parse.handle(os.path.join('conf', 'bitbake.conf'), make.cfg)
612     except IOError:
613         bb.fatal("Unable to open %s" % os.path.join('conf', 'bitbake.conf'))
614
615     if not bb.data.getVar("BUILDNAME", make.cfg):
616         bb.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), make.cfg)
617
618     buildname = bb.data.getVar("BUILDNAME", make.cfg)
619
620     bf = make.options.buildfile
621     if bf:
622         executeOneBB( bf )
623         printStats()
624
625     ignore = bb.data.getVar("ASSUME_PROVIDED", make.cfg, 1) or ""
626     __ignored_dependencies = ignore.split()
627
628     collections = bb.data.getVar("BBFILE_COLLECTIONS", make.cfg, 1)
629     if collections:
630         collection_list = collections.split()
631         for c in collection_list:
632             regex = bb.data.getVar("BBFILE_PATTERN_%s" % c, make.cfg, 1)
633             if regex == None:
634                 bb.error("BBFILE_PATTERN_%s not defined" % c)
635                 continue
636             priority = bb.data.getVar("BBFILE_PRIORITY_%s" % c, make.cfg, 1)
637             if priority == None:
638                 bb.error("BBFILE_PRIORITY_%s not defined" % c)
639                 continue
640             try:
641                 cre = re.compile(regex)
642             except re.error:
643                 bb.error("BBFILE_PATTERN_%s \"%s\" is not a valid regular expression" % (c, regex))
644                 continue
645             try:
646                 pri = int(priority)
647                 bbfile_config_priorities.append((cre, pri))
648             except ValueError:
649                 bb.error("invalid value for BBFILE_PRIORITY_%s: \"%s\"" % (c, priority))
650
651     pkgs_to_build = None
652     if args:
653         if not pkgs_to_build:
654             pkgs_to_build = []
655         pkgs_to_build.extend(args)
656     if not pkgs_to_build:
657             bbpkgs = bb.data.getVar('BBPKGS', make.cfg, 1)
658             if bbpkgs:
659                     pkgs_to_build = bbpkgs.split()
660     if not pkgs_to_build and not make.options.show_versions:
661             print "Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help'"
662             print "for usage information."
663             sys.exit(0)
664
665
666     # Import Psyco if available and not disabled
667     if not make.options.disable_psyco:
668         try:
669             import psyco
670         except ImportError:
671             if bbdebug == 0:
672                 bb.note("Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance.")
673         else:
674             psyco.bind( make.collect_bbfiles )
675     else:
676         bb.note("You have disabled Psyco. This decreases performance.")
677
678     try:
679         bb.debug(1, "BBMAKE collecting .bb files")
680         make.collect_bbfiles( myProgressCallback )
681         bb.debug(1, "BBMAKE parsing complete")
682         if bbdebug == 0:
683             print
684         if make.options.parse_only:
685             print "Requested parsing .bb files only.  Exiting."
686             sys.exit(0)
687
688         build_depgraph()
689
690         if make.options.show_versions:
691             showVersions()
692             sys.exit(0)
693             
694         if 'world' in pkgs_to_build:
695             pkgs_to_build.remove('world')
696             for t in __world_target:
697                 pkgs_to_build.append(t)
698
699         bb.event.fire(bb.event.BuildStarted(buildname, pkgs_to_build, make.cfg))
700
701         for k in pkgs_to_build:
702             failed = False
703             try:
704                 if buildPackage(k) == 0:
705                     # already diagnosed
706                     failed = True
707             except bb.build.EventException:
708                 bb.error("Build of " + k + " failed")
709                 failed = True
710
711             if failed:
712                 if make.options.abort:
713                     sys.exit(1)
714
715         bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, make.cfg))
716
717         printStats()
718
719     except KeyboardInterrupt:
720         print "\nNOTE: KeyboardInterrupt - Build not completed."
721         sys.exit(1)