1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4 BitBake 'Make' implementations
6 Functions for reading BB files, building a dependency graph and
7 building a set of BB files while walking along the dependency graph.
9 Copyright (C) 2003, 2004 Mickey Lauer
10 Copyright (C) 2003, 2004 Phil Blundell
11 Copyright (C) 2003, 2004 Chris Larson
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License as published by the Free Software
15 Foundation; either version 2 of the License, or (at your option) any later
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License along with
23 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
24 Place, Suite 330, Boston, MA 02111-1307 USA.
26 This file is part of the BitBake build tools.
29 from bb import debug, digraph, data, fetch, fatal, error, note, event, parse
30 import copy, bb, re, sys, os, glob, sre_constants
36 ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
39 def get_bbfiles( path = os.getcwd() ):
40 """Get list of default .bb files by reading out the current directory"""
41 contents = os.listdir(path)
44 (root, ext) = os.path.splitext(f)
46 bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
49 def find_bbfiles( path ):
50 """Find all the .bb files in a directory (uses find)"""
51 findcmd = 'find ' + path + ' -name *.bb | grep -v SCCS/'
53 finddata = os.popen(findcmd)
56 return finddata.readlines()
59 depstr = data.getVar('__depends', d)
61 deps = depstr.split(" ")
63 (f,old_mtime_s) = dep.split("@")
64 old_mtime = int(old_mtime_s)
65 new_mtime = parse.cached_mtime(f)
66 if (new_mtime > old_mtime):
70 def load_bbfile( bbfile ):
71 """Load and parse one .bb build file"""
73 if not cache in [None, '']:
75 cache_mtime = data.init_db_mtime(cache, bbfile)
76 file_mtime = parse.cached_mtime(bbfile)
78 if file_mtime > cache_mtime:
79 #print " : '%s' dirty. reparsing..." % bbfile
82 #print " : '%s' clean. loading from cache..." % bbfile
83 cache_data = data.init_db( cache, bbfile, False )
84 if deps_clean(cache_data):
85 return cache_data, True
87 topdir = data.getVar('TOPDIR', cfg)
89 topdir = os.path.abspath(os.getcwd())
91 data.setVar('TOPDIR', topdir, cfg)
92 bbfile = os.path.abspath(bbfile)
93 bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
94 # expand tmpdir to include this topdir
95 data.setVar('TMPDIR', data.getVar('TMPDIR', cfg, 1) or "", cfg)
96 # set topdir to location of .bb file
98 #data.setVar('TOPDIR', topdir, cfg)
100 oldpath = os.path.abspath(os.getcwd())
102 bb = data.init_db(cache,bbfile, True, cfg)
104 parse.handle(bbfile, bb) # read .bb data
105 if not cache in [None, '']:
106 bb.commit(parse.cached_mtime(bbfile)) # write cache
112 def collect_bbfiles( progressCallback ):
113 """Collect all available .bb build files"""
115 parsed, cached, skipped, masked = 0, 0, 0, 0
117 cache = bb.data.getVar( "CACHE", cfg, 1 )
118 if not cache in [None, '']:
119 print "NOTE: Using cache in '%s'" % cache
123 bb.mkdirhier( cache )
124 else: print "NOTE: Not using a cache. Set CACHE = <directory> to enable."
125 files = (data.getVar( "BBFILES", cfg, 1 ) or "").split()
126 data.setVar("BBFILES", " ".join(files), cfg)
129 files = get_bbfiles()
132 bb.error("no files to build.")
137 dirfiles = find_bbfiles(f)
141 newfiles += glob.glob(f) or [ f ]
143 bbmask = bb.data.getVar('BBMASK', cfg, 1) or ""
145 bbmask_compiled = re.compile(bbmask)
146 except sre_constants.error:
147 bb.fatal("BBMASK is not a valid regular expression.")
149 for i in xrange( len( newfiles ) ):
151 if bbmask and bbmask_compiled.search(f):
152 bb.debug(1, "bbmake: skipping %s" % f)
155 progressCallback( i + 1, len( newfiles ), f )
156 debug(1, "bbmake: parsing %s" % f)
158 # read a file's metadata
160 pkgdata[f], fromCache = load_bbfile(f)
161 if fromCache: cached += 1
164 if pkgdata[f] is not None:
165 # allow metadata files to add items to BBFILES
166 #data.update_data(pkgdata[f])
167 addbbfiles = data.getVar('BBFILES', pkgdata[f]) or None
169 for aof in addbbfiles.split():
170 if not files.count(aof):
171 if not os.path.isabs(aof):
172 aof = os.path.join(os.path.dirname(f),aof)
174 for var in pkgdata[f].keys():
175 if data.getVarFlag(var, "handler", pkgdata[f]) and data.getVar(var, pkgdata[f]):
176 event.register(data.getVar(var, pkgdata[f]))
178 bb.error("opening %s: %s" % (f, e))
180 except bb.parse.SkipPackage:
183 except KeyboardInterrupt:
186 bb.error("%s while parsing %s" % (e, f))
187 print "\rNOTE: Parsing finished. %d cached, %d parsed, %d skipped, %d masked." % ( cached, parsed, skipped, masked ),
189 def explode_version(s):
192 alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$')
193 numeric_regexp = re.compile('^(\d+)(.*)$')
196 m = numeric_regexp.match(s)
197 r.append(int(m.group(1)))
200 if s[0] in ascii_letters:
201 m = alpha_regexp.match(s)
208 def vercmp_part(a, b):
209 va = explode_version(a)
210 vb = explode_version(b)
220 if ca == None and cb == None:
231 r = vercmp_part(va, vb)
233 r = vercmp_part(ra, rb)