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