diff options
| author | Richard Purdie <richard@openedhand.com> | 2005-08-31 10:47:56 +0000 |
|---|---|---|
| committer | Richard Purdie <richard@openedhand.com> | 2005-08-31 10:47:56 +0000 |
| commit | f54da734eb7b69e8e34de505bd89a13479e230e0 (patch) | |
| tree | f796bea6f5683dfe3d591ca5390d12fd78e59c96 /bitbake/bin | |
| parent | 4b46c1f6e891b1ddd5968536440b888661fade3e (diff) | |
| download | openembedded-core-f54da734eb7b69e8e34de505bd89a13479e230e0.tar.gz openembedded-core-f54da734eb7b69e8e34de505bd89a13479e230e0.tar.bz2 openembedded-core-f54da734eb7b69e8e34de505bd89a13479e230e0.zip | |
Initial population
git-svn-id: https://svn.o-hand.com/repos/poky@2 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'bitbake/bin')
| -rwxr-xr-x | bitbake/bin/bbimage | 154 | ||||
| -rwxr-xr-x | bitbake/bin/bitbake | 927 | ||||
| -rw-r--r-- | bitbake/bin/bitbakec | bin | 0 -> 27715 bytes | |||
| -rwxr-xr-x | bitbake/bin/bitdoc | 529 |
4 files changed, 1610 insertions, 0 deletions
diff --git a/bitbake/bin/bbimage b/bitbake/bin/bbimage new file mode 100755 index 0000000000..df6caa28ed --- /dev/null +++ b/bitbake/bin/bbimage @@ -0,0 +1,154 @@ +#!/usr/bin/env python +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (C) 2003 Chris Larson +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 59 Temple +# Place, Suite 330, Boston, MA 02111-1307 USA. + +import sys, os +sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib')) +import bb +from bb import * + +__version__ = 1.0 +type = "jffs2" +cfg_bb = data.init() +cfg_oespawn = data.init() + + +def usage(): + print "Usage: bbimage [options ...]" + print "Creates an image for a target device from a root filesystem," + print "obeying configuration parameters from the BitBake" + print "configuration files, thereby easing handling of deviceisms." + print "" + print " %s\t\t%s" % ("-r [arg], --root [arg]", "root directory (default=${IMAGE_ROOTFS})") + print " %s\t\t%s" % ("-t [arg], --type [arg]", "image type (jffs2[default], cramfs)") + print " %s\t\t%s" % ("-n [arg], --name [arg]", "image name (override IMAGE_NAME variable)") + print " %s\t\t%s" % ("-v, --version", "output version information and exit") + sys.exit(0) + +def version(): + print "BitBake Build Tool Core version %s" % bb.__version__ + print "BBImage version %s" % __version__ + +def emit_bb(d, base_d = {}): + for v in d.keys(): + if d[v] != base_d[v]: + data.emit_var(v, d) + +def getopthash(l): + h = {} + for (opt, val) in l: + h[opt] = val + return h + +import getopt +try: + (opts, args) = getopt.getopt(sys.argv[1:], 'vr:t:e:n:', [ 'version', 'root=', 'type=', 'bbfile=', 'name=' ]) +except getopt.GetoptError: + usage() + +# handle opts +opthash = getopthash(opts) + +if '--version' in opthash or '-v' in opthash: + version() + sys.exit(0) + +try: + cfg_bb = parse.handle(os.path.join('conf', 'bitbake.conf'), cfg_bb) +except IOError: + fatal("Unable to open bitbake.conf") + +# sanity check +if cfg_bb is None: + fatal("Unable to open/parse %s" % os.path.join('conf', 'bitbake.conf')) + usage(1) + +rootfs = None +extra_files = [] + +if '--root' in opthash: + rootfs = opthash['--root'] +if '-r' in opthash: + rootfs = opthash['-r'] + +if '--type' in opthash: + type = opthash['--type'] +if '-t' in opthash: + type = opthash['-t'] + +if '--bbfile' in opthash: + extra_files.append(opthash['--bbfile']) +if '-e' in opthash: + extra_files.append(opthash['-e']) + +for f in extra_files: + try: + cfg_bb = parse.handle(f, cfg_bb) + except IOError: + print "unable to open %s" % f + +if not rootfs: + rootfs = data.getVar('IMAGE_ROOTFS', cfg_bb, 1) + +if not rootfs: + bb.fatal("IMAGE_ROOTFS not defined") + +data.setVar('IMAGE_ROOTFS', rootfs, cfg_bb) + +from copy import copy, deepcopy +localdata = data.createCopy(cfg_bb) + +overrides = data.getVar('OVERRIDES', localdata) +if not overrides: + bb.fatal("OVERRIDES not defined.") +data.setVar('OVERRIDES', '%s:%s' % (overrides, type), localdata) +data.update_data(localdata) +data.setVar('OVERRIDES', overrides, localdata) + +if '-n' in opthash: + data.setVar('IMAGE_NAME', opthash['-n'], localdata) +if '--name' in opthash: + data.setVar('IMAGE_NAME', opthash['--name'], localdata) + +topdir = data.getVar('TOPDIR', localdata, 1) or os.getcwd() + +cmd = data.getVar('IMAGE_CMD', localdata, 1) +if not cmd: + bb.fatal("IMAGE_CMD not defined") + +outdir = data.getVar('DEPLOY_DIR_IMAGE', localdata, 1) +if not outdir: + bb.fatal('DEPLOY_DIR_IMAGE not defined') +mkdirhier(outdir) + +#depends = data.getVar('IMAGE_DEPENDS', localdata, 1) or "" +#if depends: +# bb.note("Spawning bbmake to satisfy dependencies: %s" % depends) +# ret = os.system('bbmake %s' % depends) +# if ret != 0: +# bb.error("executing bbmake to satisfy dependencies") + +bb.note("Executing %s" % cmd) +data.setVar('image_cmd', cmd, localdata) +data.setVarFlag('image_cmd', 'func', 1, localdata) +try: + bb.build.exec_func('image_cmd', localdata) +except bb.build.FuncFailed: + sys.exit(1) +#ret = os.system(cmd) +#sys.exit(ret) diff --git a/bitbake/bin/bitbake b/bitbake/bin/bitbake new file mode 100755 index 0000000000..d327a69ab8 --- /dev/null +++ b/bitbake/bin/bitbake @@ -0,0 +1,927 @@ +#!/usr/bin/env python +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (C) 2003, 2004 Chris Larson +# Copyright (C) 2003, 2004 Phil Blundell +# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer +# Copyright (C) 2005 Holger Hans Peter Freyther +# Copyright (C) 2005 ROAD GmbH +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 59 Temple +# Place, Suite 330, Boston, MA 02111-1307 USA. + +import sys, os, getopt, glob, copy, os.path, re, time +sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib')) +import bb +from bb import utils, data, parse, debug, event, fatal +from sets import Set +import itertools, optparse + +parsespin = itertools.cycle( r'|/-\\' ) +bbdebug = 0 + +__version__ = "1.3.2" + +#============================================================================# +# BBParsingStatus +#============================================================================# +class BBParsingStatus: + """ + The initial idea for this status class is to use the data when it is + already loaded instead of loading it from various place over and over + again. + """ + + def __init__(self): + self.cache_dirty = False + self.providers = {} + self.bbfile_priority = {} + self.bbfile_config_priorities = [] + self.ignored_depedencies = None + self.possible_world = [] + self.world_target = Set() + self.pkg_pn = {} + self.pkg_fn = {} + self.pkg_pvpr = {} + self.pkg_dp = {} + self.pn_provides = {} + self.all_depends = Set() + + def handle_bb_data(self, file_name, bb_data, cached): + """ + We will fill the dictionaries with the stuff we + need for building the tree more fast + """ + if bb_data == None: + return + + if not cached: + self.cache_dirty = True + + pn = bb.data.getVar('PN', bb_data, True) + pv = bb.data.getVar('PV', bb_data, True) + pr = bb.data.getVar('PR', bb_data, True) + dp = int(bb.data.getVar('DEFAULT_PREFERENCE', bb_data, True) or "0") + provides = Set([pn] + (bb.data.getVar("PROVIDES", bb_data, 1) or "").split()) + depends = (bb.data.getVar("DEPENDS", bb_data, True) or "").split() + + + # build PackageName to FileName lookup table + if pn not in self.pkg_pn: + self.pkg_pn[pn] = [] + self.pkg_pn[pn].append(file_name) + + # build FileName to PackageName lookup table + self.pkg_fn[file_name] = pn + self.pkg_pvpr[file_name] = (pv,pr) + self.pkg_dp[file_name] = dp + + # Build forward and reverse provider hashes + # Forward: virtual -> [filenames] + # Reverse: PN -> [virtuals] + if pn not in self.pn_provides: + self.pn_provides[pn] = Set() + self.pn_provides[pn] |= provides + + for provide in provides: + if provide not in self.providers: + self.providers[provide] = [] + self.providers[provide].append(file_name) + + for dep in depends: + self.all_depends.add(dep) + + # Collect files we may need for possible world-dep + # calculations + if not bb.data.getVar('BROKEN', bb_data, True) and not bb.data.getVar('EXCLUDE_FROM_WORLD', bb_data, True): + self.possible_world.append(file_name) + + +#============================================================================# +# BBStatistics +#============================================================================# +class BBStatistics: + """ + Manage build statistics for one run + """ + def __init__(self ): + self.attempt = 0 + self.success = 0 + self.fail = 0 + self.deps = 0 + + def show( self ): + print "Build statistics:" + print " Attempted builds: %d" % self.attempt + if self.fail: + print " Failed builds: %d" % self.fail + if self.deps: + print " Dependencies not satisfied: %d" % self.deps + if self.fail or self.deps: return 1 + else: return 0 + + +#============================================================================# +# BBOptions +#============================================================================# +class BBConfiguration( object ): + """ + Manages build options and configurations for one run + """ + def __init__( self, options ): + for key, val in options.__dict__.items(): + setattr( self, key, val ) + self.data = data.init() + +#============================================================================# +# BBCooker +#============================================================================# +class BBCooker: + """ + Manages one bitbake build run + """ + + ParsingStatus = BBParsingStatus # make it visible from the shell + Statistics = BBStatistics # make it visible from the shell + + def __init__( self ): + self.build_cache_fail = [] + self.build_cache = [] + self.building_list = [] + self.build_path = [] + self.consider_msgs_cache = [] + self.preferred = {} + self.stats = BBStatistics() + self.status = None + + self.pkgdata = None + self.cache = None + + def tryBuildPackage( self, fn, item, the_data ): + """Build one package""" + bb.event.fire(bb.event.PkgStarted(item, the_data)) + try: + self.stats.attempt += 1 + if self.configuration.force: + bb.data.setVarFlag('do_%s' % self.configuration.cmd, 'force', 1, the_data) + if not self.configuration.dry_run: + bb.build.exec_task('do_%s' % self.configuration.cmd, the_data) + bb.event.fire(bb.event.PkgSucceeded(item, the_data)) + self.build_cache.append(fn) + return True + except bb.build.FuncFailed: + self.stats.fail += 1 + bb.error("task stack execution failed") + bb.event.fire(bb.event.PkgFailed(item, the_data)) + self.build_cache_fail.append(fn) + raise + except bb.build.EventException, e: + self.stats.fail += 1 + event = e.args[1] + bb.error("%s event exception, aborting" % bb.event.getName(event)) + bb.event.fire(bb.event.PkgFailed(item, the_data)) + self.build_cache_fail.append(fn) + raise + + def tryBuild( self, fn, virtual ): + """Build a provider and its dependencies""" + if fn in self.building_list: + bb.error("%s depends on itself (eventually)" % fn) + bb.error("upwards chain is: %s" % (" -> ".join(self.build_path))) + return False + + the_data = self.pkgdata[fn] + item = self.status.pkg_fn[fn] + + self.building_list.append(fn) + + pathstr = "%s (%s)" % (item, virtual) + self.build_path.append(pathstr) + + depends_list = (bb.data.getVar('DEPENDS', the_data, 1) or "").split() + if self.configuration.verbose: + bb.note("current path: %s" % (" -> ".join(self.build_path))) + bb.note("dependencies for %s are: %s" % (item, " ".join(depends_list))) + + try: + failed = False + + depcmd = self.configuration.cmd + bbdepcmd = bb.data.getVarFlag('do_%s' % self.configuration.cmd, 'bbdepcmd', the_data) + if bbdepcmd is not None: + if bbdepcmd == "": + depcmd = None + else: + depcmd = bbdepcmd + + if depcmd: + oldcmd = self.configuration.cmd + self.configuration.cmd = depcmd + + for dependency in depends_list: + if dependency in self.status.ignored_dependencies: + continue + if not depcmd: + continue + if self.buildProvider( dependency ) == 0: + bb.error("dependency %s (for %s) not satisfied" % (dependency,item)) + failed = True + if self.configuration.abort: + break + + if depcmd: + self.configuration.cmd = oldcmd + + if failed: + self.stats.deps += 1 + return False + + if bb.build.stamp_is_current('do_%s' % self.configuration.cmd, the_data): + self.build_cache.append(fn) + return True + + return self.tryBuildPackage( fn, item, the_data ) + + finally: + self.building_list.remove(fn) + self.build_path.remove(pathstr) + + def findBestProvider( self, pn, pkg_pn = None): + """ + If there is a PREFERRED_VERSION, find the highest-priority bbfile + providing that version. If not, find the latest version provided by + an bbfile in the highest-priority set. + """ + if not pkg_pn: + pkg_pn = self.status.pkg_pn + + files = pkg_pn[pn] + priorities = {} + for f in files: + priority = self.status.bbfile_priority[f] + if priority not in priorities: + priorities[priority] = [] + priorities[priority].append(f) + p_list = priorities.keys() + p_list.sort(lambda a, b: a - b) + tmp_pn = [] + for p in p_list: + tmp_pn = [priorities[p]] + tmp_pn + + preferred_file = None + + preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, self.configuration.data, 1) + if preferred_v: + m = re.match('(.*)_(.*)', preferred_v) + if m: + preferred_v = m.group(1) + preferred_r = m.group(2) + else: + preferred_r = None + + for file_set in tmp_pn: + for f in file_set: + pv,pr = self.status.pkg_pvpr[f] + if preferred_v == pv and (preferred_r == pr or preferred_r == None): + preferred_file = f + preferred_ver = (pv, pr) + break + if preferred_file: + break; + if preferred_r: + pv_str = '%s-%s' % (preferred_v, preferred_r) + else: + pv_str = preferred_v + if preferred_file is None: + bb.note("preferred version %s of %s not available" % (pv_str, pn)) + else: + bb.debug(1, "selecting %s as PREFERRED_VERSION %s of package %s" % (preferred_file, pv_str, pn)) + + # get highest priority file set + files = tmp_pn[0] + latest = None + latest_p = 0 + latest_f = None + for file_name in files: + pv,pr = self.status.pkg_pvpr[file_name] + dp = self.status.pkg_dp[file_name] + + if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pv, pr)) < 0)) or (dp > latest_p): + latest = (pv, pr) + latest_f = file_name + latest_p = dp + if preferred_file is None: + preferred_file = latest_f + preferred_ver = latest + + return (latest,latest_f,preferred_ver, preferred_file) + + def showVersions( self ): + pkg_pn = self.status.pkg_pn + preferred_versions = {} + latest_versions = {} + + # Sort by priority + for pn in pkg_pn.keys(): + (last_ver,last_file,pref_ver,pref_file) = self.findBestProvider(pn) + preferred_versions[pn] = (pref_ver, pref_file) + latest_versions[pn] = (last_ver, last_file) + + pkg_list = pkg_pn.keys() + pkg_list.sort() + + for p in pkg_list: + pref = preferred_versions[p] + latest = latest_versions[p] + + if pref != latest: + prefstr = pref[0][0] + "-" + pref[0][1] + else: + prefstr = "" + + print "%-30s %20s %20s" % (p, latest[0][0] + "-" + latest[0][1], + prefstr) + + def showEnvironment( self ): + """Show the outer or per-package environment""" + if self.configuration.buildfile: + try: + self.configuration.data, fromCache = self.load_bbfile( self.configuration.buildfile ) + except IOError, e: + fatal("Unable to read %s: %s" % ( self.configuration.buildfile, e )) + except Exception, e: + fatal("%s" % e) + # emit variables and shell functions + try: + data.update_data( self.configuration.data ) + data.emit_env(sys.__stdout__, self.configuration.data, True) + except Exception, e: + fatal("%s" % e) + # emit the metadata which isnt valid shell + for e in self.configuration.data.keys(): + if data.getVarFlag( e, 'python', self.configuration.data ): + sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, data.getVar(e, self.configuration.data, 1))) + + def buildProvider( self, item ): + fn = None + + discriminated = False + + if item not in self.status.providers: + bb.error("Nothing provides %s" % item) + return 0 + + all_p = self.status.providers[item] + + for p in all_p: + if p in self.build_cache: + bb.debug(1, "already built %s in this run\n" % p) + return 1 + + eligible = [] + preferred_versions = {} + + # Collate providers by PN + pkg_pn = {} + for p in all_p: + pn = self.status.pkg_fn[p] + if pn not in pkg_pn: + pkg_pn[pn] = [] + pkg_pn[pn].append(p) + + bb.debug(1, "providers for %s are: %s" % (item, pkg_pn.keys())) + + for pn in pkg_pn.keys(): + preferred_versions[pn] = self.findBestProvider(pn, pkg_pn)[2:4] + eligible.append(preferred_versions[pn][1]) + + for p in eligible: + if p in self.build_cache_fail: + bb.debug(1, "rejecting already-failed %s" % p) + eligible.remove(p) + + if len(eligible) == 0: + bb.error("no eligible providers for %s" % item) + return 0 + + # look to see if one of them is already staged, or marked as preferred. + # if so, bump it to the head of the queue + for p in all_p: + the_data = self.pkgdata[p] + pn = bb.data.getVar('PN', the_data, 1) + pv = bb.data.getVar('PV', the_data, 1) + pr = bb.data.getVar('PR', the_data, 1) + tmpdir = bb.data.getVar('TMPDIR', the_data, 1) + stamp = '%s/stamps/%s-%s-%s.do_populate_staging' % (tmpdir, pn, pv, pr) + if os.path.exists(stamp): + (newvers, fn) = preferred_versions[pn] + if not fn in eligible: + # package was made ineligible by already-failed check + continue + oldver = "%s-%s" % (pv, pr) + newver = '-'.join(newvers) + if (newver != oldver): + extra_chat = "; upgrading from %s to %s" % (oldver, newver) + else: + extra_chat = "" + if self.configuration.verbose: + bb.note("selecting already-staged %s to satisfy %s%s" % (pn, item, extra_chat)) + eligible.remove(fn) + eligible = [fn] + eligible + discriminated = True + break + + prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % item, self.configuration.data, 1) + if prefervar: + self.preferred[item] = prefervar + + if item in self.preferred: + for p in eligible: + pn = self.status.pkg_fn[p] + if self.preferred[item] == pn: + if self.configuration.verbose: + bb.note("selecting %s to satisfy %s due to PREFERRED_PROVIDERS" % (pn, item)) + eligible.remove(p) + eligible = [p] + eligible + discriminated = True + break + + if len(eligible) > 1 and discriminated == False: + if item not in self.consider_msgs_cache: + providers_list = [] + for fn in eligible: + providers_list.append(self.status.pkg_fn[fn]) + bb.note("multiple providers are available (%s);" % ", ".join(providers_list)) + bb.note("consider defining PREFERRED_PROVIDER_%s" % item) + self.consider_msgs_cache.append(item) + + + # run through the list until we find one that we can build + for fn in eligible: + bb.debug(2, "selecting %s to satisfy %s" % (fn, item)) + if self.tryBuild(fn, item): + return 1 + + bb.note("no buildable providers for %s" % item) + return 0 + + def buildDepgraph( self ): + all_depends = self.status.all_depends + pn_provides = self.status.pn_provides + + def calc_bbfile_priority(filename): + for (regex, pri) in self.status.bbfile_config_priorities: + if regex.match(filename): + return pri + return 0 + + # Handle PREFERRED_PROVIDERS + for p in (bb.data.getVar('PREFERRED_PROVIDERS', self.configuration.data, 1) or "").split(): + (providee, provider) = p.split(':') + if providee in self.preferred and self.preferred[providee] != provider: + bb.error("conflicting preferences for %s: both %s and %s specified" % (providee, provider, self.preferred[providee])) + self.preferred[providee] = provider + + # Calculate priorities for each file + for p in self.pkgdata.keys(): + self.status.bbfile_priority[p] = calc_bbfile_priority(p) + + # Build package list for "bitbake world" + bb.debug(1, "collating packages for \"world\"") + for f in self.status.possible_world: + terminal = True + pn = self.status.pkg_fn[f] + + for p in pn_provides[pn]: + if p.startswith('virtual/'): + bb.debug(2, "skipping %s due to %s provider starting with virtual/" % (f, p)) + terminal = False + break + for pf in self.status.providers[p]: + if self.status.pkg_fn[pf] != pn: + bb.debug(2, "skipping %s due to both us and %s providing %s" % (f, pf, p)) + terminal = False + break + if terminal: + self.status.world_target.add(pn) + + # drop reference count now + self.status.possible_world = None + self.status.all_depends = None + + def myProgressCallback( self, x, y, f, file_data, from_cache ): + # feed the status with new input + self.status.handle_bb_data(f, file_data, from_cache) + + if bbdebug > 0: + return + if os.isatty(sys.stdout.fileno()): + sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) ) + sys.stdout.flush() + else: + if x == 1: + sys.stdout.write("Parsing .bb files, please wait...") + sys.stdout.flush() + if x == y: + sys.stdout.write("done.") + sys.stdout.flush() + + def interactiveMode( self ): + """Drop off into a shell""" + try: + from bb import shell + except ImportError, details: + bb.fatal("Sorry, shell not available (%s)" % details ) + else: + bb.data.update_data( self.configuration.data ) + shell.start( self ) + sys.exit( 0 ) + + def parseConfigurationFile( self, afile ): + try: + self.configuration.data = bb.parse.handle( afile, self.configuration.data ) + except IOError: + bb.fatal( "Unable to open %s" % afile ) + except bb.parse.ParseError, details: + bb.fatal( "Unable to parse %s (%s)" % (afile, details) ) + + def handleCollections( self, collections ): + """Handle collections""" + if collections: + collection_list = collections.split() + for c in collection_list: + regex = bb.data.getVar("BBFILE_PATTERN_%s" % c, self.configuration.data, 1) + if regex == None: + bb.error("BBFILE_PATTERN_%s not defined" % c) + continue + priority = bb.data.getVar("BBFILE_PRIORITY_%s" % c, self.configuration.data, 1) + if priority == None: + bb.error("BBFILE_PRIORITY_%s not defined" % c) + continue + try: + cre = re.compile(regex) + except re.error: + bb.error("BBFILE_PATTERN_%s \"%s\" is not a valid regular expression" % (c, regex)) + continue + try: + pri = int(priority) + self.status.bbfile_config_priorities.append((cre, pri)) + except ValueError: + bb.error("invalid value for BBFILE_PRIORITY_%s: \"%s\"" % (c, priority)) + + + def cook( self, configuration, args ): + self.configuration = configuration + + if not self.configuration.cmd: + self.configuration.cmd = "build" + + if self.configuration.debug: + bb.debug_level = self.configuration.debug + + self.configuration.data = bb.data.init() + + for f in self.configuration.file: + self.parseConfigurationFile( f ) + + self.parseConfigurationFile( os.path.join( "conf", "bitbake.conf" ) ) + + if self.configuration.show_environment: + self.showEnvironment() + sys.exit( 0 ) + + # inject custom variables + if not bb.data.getVar("BUILDNAME", self.configuration.data): + bb.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), self.configuration.data) + bb.data.setVar("BUILDSTART", time.strftime('%m/%d/%Y %H:%M:%S',time.gmtime()),self.configuration.data) + + buildname = bb.data.getVar("BUILDNAME", self.configuration.data) + + if self.configuration.interactive: + self.interactiveMode() + + if self.configuration.buildfile is not None: + bf = os.path.abspath( self.configuration.buildfile ) + try: + bbfile_data = bb.parse.handle(bf, self.configuration.data) + except IOError: + bb.fatal("Unable to open %s" % bf) + + item = bb.data.getVar('PN', bbfile_data, 1) + try: + self.tryBuildPackage( bf, item, bbfile_data ) + except bb.build.EventException: + bb.error( "Build of '%s' failed" % item ) + + sys.exit( self.stats.show() ) + + # initialise the parsing status now we know we will need deps + self.status = BBParsingStatus() + + ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or "" + self.status.ignored_dependencies = Set( ignore.split() ) + + self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) ) + + pkgs_to_build = None + if args: + if not pkgs_to_build: + pkgs_to_build = [] + pkgs_to_build.extend(args) + if not pkgs_to_build: + bbpkgs = bb.data.getVar('BBPKGS', self.configuration.data, 1) + if bbpkgs: + pkgs_to_build = bbpkgs.split() + if not pkgs_to_build and not self.configuration.show_versions \ + and not self.configuration.interactive \ + and not self.configuration.show_environment: + print "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help'" + print "for usage information." + sys.exit(0) + + # Import Psyco if available and not disabled + if not self.configuration.disable_psyco: + try: + import psyco + except ImportError: + if bbdebug == 0: + bb.note("Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance.") + else: + psyco.bind( self.collect_bbfiles ) + else: + bb.note("You have disabled Psyco. This decreases performance.") + + try: + bb.debug(1, "collecting .bb files") + self.collect_bbfiles( self.myProgressCallback ) + bb.debug(1, "parsing complete") + if bbdebug == 0: + print + if self.configuration.parse_only: + print "Requested parsing .bb files only. Exiting." + return + + bb.data.update_data( self.configuration.data ) + self.buildDepgraph() + + if self.configuration.show_versions: + self.showVersions() + sys.exit( 0 ) + if 'world' in pkgs_to_build: + pkgs_to_build.remove('world') + for t in self.status.world_target: + pkgs_to_build.append(t) + + bb.event.fire(bb.event.BuildStarted(buildname, pkgs_to_build, self.configuration.data)) + + for k in pkgs_to_build: + failed = False + try: + if self.buildProvider( k ) == 0: + # already diagnosed + failed = True + except bb.build.EventException: + bb.error("Build of " + k + " failed") + failed = True + + if failed: + if self.configuration.abort: + sys.exit(1) + + bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, self.configuration.data)) + + sys.exit( self.stats.show() ) + + except KeyboardInterrupt: + print "\nNOTE: KeyboardInterrupt - Build not completed." + sys.exit(1) + + def get_bbfiles( self, path = os.getcwd() ): + """Get list of default .bb files by reading out the current directory""" + contents = os.listdir(path) + bbfiles = [] + for f in contents: + (root, ext) = os.path.splitext(f) + if ext == ".bb": + bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f))) + return bbfiles + + def find_bbfiles( self, path ): + """Find all the .bb files in a directory (uses find)""" + findcmd = 'find ' + path + ' -name *.bb | grep -v SCCS/' + try: + finddata = os.popen(findcmd) + except OSError: + return [] + return finddata.readlines() + + def deps_clean(self, d): + depstr = data.getVar('__depends', d) + if depstr: + deps = depstr.split(" ") + for dep in deps: + (f,old_mtime_s) = dep.split("@") + old_mtime = int(old_mtime_s) + new_mtime = parse.cached_mtime(f) + if (new_mtime > old_mtime): + return False + return True + + def load_bbfile( self, bbfile ): + """Load and parse one .bb build file""" + + if not self.cache in [None, '']: + # get the times + cache_mtime = data.init_db_mtime(self.cache, bbfile) + file_mtime = parse.cached_mtime(bbfile) + + if file_mtime > cache_mtime: + #print " : '%s' dirty. reparsing..." % bbfile + pass + else: + #print " : '%s' clean. loading from cache..." % bbfile + cache_data = data.init_db( self.cache, bbfile, False ) + if self.deps_clean(cache_data): + return cache_data, True + + topdir = data.getVar('TOPDIR', self.configuration.data) + if not topdir: + topdir = os.path.abspath(os.getcwd()) + # set topdir to here + data.setVar('TOPDIR', topdir, self.configuration) + bbfile = os.path.abspath(bbfile) + bbfile_loc = os.path.abspath(os.path.dirname(bbfile)) + # expand tmpdir to include this topdir + data.setVar('TMPDIR', data.getVar('TMPDIR', self.configuration.data, 1) or "", self.configuration.data) + # set topdir to location of .bb file + topdir = bbfile_loc + #data.setVar('TOPDIR', topdir, cfg) + # go there + oldpath = os.path.abspath(os.getcwd()) + os.chdir(topdir) + bb = data.init_db(self.cache,bbfile, True, self.configuration.data) + try: + parse.handle(bbfile, bb) # read .bb data + if not self.cache in [None, '']: + bb.commit(parse.cached_mtime(bbfile)) # write cache + os.chdir(oldpath) + return bb, False + finally: + os.chdir(oldpath) + + def collect_bbfiles( self, progressCallback ): + """Collect all available .bb build files""" + self.cb = progressCallback + pa |
