summaryrefslogtreecommitdiffstats
path: root/build/lib/bb/make.py
diff options
context:
space:
mode:
Diffstat (limited to 'build/lib/bb/make.py')
-rw-r--r--build/lib/bb/make.py263
1 files changed, 263 insertions, 0 deletions
diff --git a/build/lib/bb/make.py b/build/lib/bb/make.py
new file mode 100644
index 000000000..62437be36
--- /dev/null
+++ b/build/lib/bb/make.py
@@ -0,0 +1,263 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+"""
+BitBake 'Make' implementations
+
+Functions for reading BB files, building a dependency graph and
+building a set of BB files while walking along the dependency graph.
+
+Copyright (C) 2003, 2004 Mickey Lauer
+Copyright (C) 2003, 2004 Phil Blundell
+Copyright (C) 2003, 2004 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.
+
+This file is part of the BitBake build tools.
+"""
+
+from bb import debug, digraph, data, fetch, fatal, error, note, event, parse
+import copy, bb, re, sys, os, glob, sre_constants
+try:
+ import cPickle as pickle
+except ImportError:
+ import pickle
+ print "NOTE: Importing cPickle failed. Falling back to a very slow implementation."
+
+pkgdata = {}
+cfg = data.init()
+cache = None
+digits = "0123456789"
+ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+mtime_cache = {}
+
+def get_bbfiles( 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( 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(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( bbfile ):
+ """Load and parse one .bb build file"""
+
+ if not cache in [None, '']:
+ cache_bbfile = bbfile.replace( '/', '_' )
+
+ try:
+ cache_mtime = os.stat( "%s/%s" % ( cache, cache_bbfile ) )[8]
+ except OSError:
+ cache_mtime = 0
+ 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 = unpickle_bb( cache_bbfile )
+ if deps_clean(cache_data):
+ return cache_data, True
+
+ bbpath = data.getVar('BBPATH', cfg)
+ safebbpath = data.getVar('BBPATH', cfg)
+ topdir = data.getVar('TOPDIR', cfg)
+ if not topdir:
+ topdir = os.path.abspath(os.getcwd())
+ # set topdir to here
+ data.setVar('TOPDIR', topdir, cfg)
+ 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', cfg, 1) or "", cfg)
+ # add topdir to bbpath
+ # bbpath = "%s:%s" % (topdir, bbpath)
+ # set topdir to location of .bb file
+ topdir = bbfile_loc
+ #data.setVar('TOPDIR', topdir, cfg)
+ # add that topdir to bbpath
+ bbpath = "%s:%s" % (topdir, bbpath)
+ # go there
+ oldpath = os.path.abspath(os.getcwd())
+ os.chdir(topdir)
+ data.setVar('BBPATH', bbpath, cfg)
+ bb = copy.deepcopy(cfg)
+ try:
+ parse.handle(bbfile, bb) # read .bb data
+ if not cache in [None, '']: pickle_bb( cache_bbfile, bb) # write cache
+ os.chdir(oldpath)
+ return bb, False
+ finally:
+ os.chdir(oldpath)
+ data.setVar('BBPATH', safebbpath, cfg)
+
+def pickle_bb( bbfile, bb ):
+ p = pickle.Pickler( file( "%s/%s" % ( cache, bbfile ), "wb" ), -1 )
+ p.dump( bb )
+
+def unpickle_bb( bbfile ):
+ p = pickle.Unpickler( file( "%s/%s" % ( cache, bbfile ), "rb" ) )
+ bb = p.load()
+ funcstr = data.getVar('__functions__', bb)
+ if funcstr:
+ comp = compile(funcstr, "<pickled>", "exec")
+ exec comp in __builtins__
+ return bb
+
+def collect_bbfiles( progressCallback ):
+ """Collect all available .bb build files"""
+
+ parsed, cached, skipped, masked = 0, 0, 0, 0
+ global cache
+ cache = bb.data.getVar( "CACHE", cfg, 1 )
+ if not cache in [None, '']:
+ print "NOTE: Using cache in '%s'" % cache
+ try:
+ os.stat( cache )
+ except OSError:
+ bb.mkdirhier( cache )
+ else: print "NOTE: Not using a cache. Set CACHE = <directory> to enable."
+ files = (data.getVar( "BBFILES", cfg, 1 ) or "").split()
+ data.setVar("BBFILES", " ".join(files), cfg)
+
+ if not len(files):
+ files = get_bbfiles()
+
+ if not len(files):
+ bb.error("no files to build.")
+
+ newfiles = []
+ for f in files:
+ if os.path.isdir(f):
+ dirfiles = find_bbfiles(f)
+ if dirfiles:
+ newfiles += dirfiles
+ continue
+ newfiles += glob.glob(f) or [ f ]
+
+ bbmask = bb.data.getVar('BBMASK', cfg, 1) or ""
+ try:
+ bbmask_compiled = re.compile(bbmask)
+ except sre_constants.error:
+ bb.fatal("BBMASK is not a valid regular expression.")
+
+ for i in xrange( len( newfiles ) ):
+ f = newfiles[i]
+ if bbmask and bbmask_compiled.search(f):
+ bb.debug(1, "bbmake: skipping %s" % f)
+ masked += 1
+ continue
+ progressCallback( i + 1, len( newfiles ), f )
+ debug(1, "bbmake: parsing %s" % f)
+
+ # read a file's metadata
+ try:
+ pkgdata[f], fromCache = load_bbfile(f)
+ if fromCache: cached += 1
+ else: parsed += 1
+ deps = None
+ if pkgdata[f] is not None:
+ # allow metadata files to add items to BBFILES
+ #data.update_data(pkgdata[f])
+ addbbfiles = data.getVar('BBFILES', pkgdata[f]) or None
+ if addbbfiles:
+ for aof in addbbfiles.split():
+ if not files.count(aof):
+ if not os.path.isabs(aof):
+ aof = os.path.join(os.path.dirname(f),aof)
+ files.append(aof)
+ for var in pkgdata[f].keys():
+ if data.getVarFlag(var, "handler", pkgdata[f]) and data.getVar(var, pkgdata[f]):
+ event.register(data.getVar(var, pkgdata[f]))
+ except IOError, e:
+ bb.error("opening %s: %s" % (f, e))
+ pass
+ except bb.parse.SkipPackage:
+ skipped += 1
+ pass
+ except KeyboardInterrupt:
+ raise
+ except Exception, e:
+ bb.error("%s while parsing %s" % (e, f))
+ print "\rNOTE: Parsing finished. %d cached, %d parsed, %d skipped, %d masked." % ( cached, parsed, skipped, masked ),
+
+def explode_version(s):
+ import string
+ r = []
+ alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$')
+ numeric_regexp = re.compile('^(\d+)(.*)$')
+ while (s != ''):
+ if s[0] in digits:
+ m = numeric_regexp.match(s)
+ r.append(int(m.group(1)))
+ s = m.group(2)
+ continue
+ if s[0] in ascii_letters:
+ m = alpha_regexp.match(s)
+ r.append(m.group(1))
+ s = m.group(2)
+ continue
+ s = s[1:]
+ return r
+
+def vercmp_part(a, b):
+ va = explode_version(a)
+ vb = explode_version(b)
+ while True:
+ if va == []:
+ ca = None
+ else:
+ ca = va.pop(0)
+ if vb == []:
+ cb = None
+ else:
+ cb = vb.pop(0)
+ if ca == None and cb == None:
+ return 0
+ if ca > cb:
+ return 1
+ if ca < cb:
+ return -1
+
+def vercmp(ta, tb):
+ (va, ra) = ta
+ (vb, rb) = tb
+
+ r = vercmp_part(va, vb)
+ if (r == 0):
+ r = vercmp_part(ra, rb)
+ return r