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
116 global cache, pkgdata
117 cache = bb.data.getVar( "CACHE", cfg, 1 )
118 pkgdata = data.pkgdata( not cache in [None, ''], cache )
120 if not cache in [None, '']:
121 print "NOTE: Using cache in '%s'" % cache
125 bb.mkdirhier( cache )
126 else: print "NOTE: Not using a cache. Set CACHE = <directory> to enable."
127 files = (data.getVar( "BBFILES", cfg, 1 ) or "").split()
128 data.setVar("BBFILES", " ".join(files), cfg)
131 files = get_bbfiles()
134 bb.error("no files to build.")
139 dirfiles = find_bbfiles(f)
143 newfiles += glob.glob(f) or [ f ]
145 bbmask = bb.data.getVar('BBMASK', cfg, 1) or ""
147 bbmask_compiled = re.compile(bbmask)
148 except sre_constants.error:
149 bb.fatal("BBMASK is not a valid regular expression.")
151 for i in xrange( len( newfiles ) ):
153 if bbmask and bbmask_compiled.search(f):
154 bb.debug(1, "bbmake: skipping %s" % f)
157 progressCallback( i + 1, len( newfiles ), f )
158 debug(1, "bbmake: parsing %s" % f)
160 # read a file's metadata
162 bb_data, fromCache = load_bbfile(f)
163 if fromCache: cached += 1
166 if bb_data is not None:
167 # allow metadata files to add items to BBFILES
168 #data.update_data(pkgdata[f])
169 addbbfiles = data.getVar('BBFILES', bb_data) or None
171 for aof in addbbfiles.split():
172 if not files.count(aof):
173 if not os.path.isabs(aof):
174 aof = os.path.join(os.path.dirname(f),aof)
176 for var in bb_data.keys():
177 if data.getVarFlag(var, "handler", bb_data) and data.getVar(var, bb_data):
178 event.register(data.getVar(var, bb_data))
181 bb.error("opening %s: %s" % (f, e))
183 except bb.parse.SkipPackage:
186 except KeyboardInterrupt:
189 bb.error("%s while parsing %s" % (e, f))
190 print "\rNOTE: Parsing finished. %d cached, %d parsed, %d skipped, %d masked." % ( cached, parsed, skipped, masked ),
192 def explode_version(s):
195 alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$')
196 numeric_regexp = re.compile('^(\d+)(.*)$')
199 m = numeric_regexp.match(s)
200 r.append(int(m.group(1)))
203 if s[0] in ascii_letters:
204 m = alpha_regexp.match(s)
211 def vercmp_part(a, b):
212 va = explode_version(a)
213 vb = explode_version(b)
223 if ca == None and cb == None:
234 r = vercmp_part(va, vb)
236 r = vercmp_part(ra, rb)