1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4 OpenEmbedded 'Make' implementations
6 Functions for reading OE files, building a dependency graph and
7 building a set of OE files while walking along the dependency graph.
9 This file is part of the OpenEmbedded (http://openembedded.org) build infrastructure.
12 from oe import debug, digraph, data, fetch, fatal, error, note, event, parse
13 import copy, oe, re, sys, os, glob, sre_constants
15 import cPickle as pickle
18 print "NOTE: Importing cPickle failed. Falling back to a very slow implementation."
24 ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
27 def get_oefiles( path = os.getcwd() ):
28 """Get list of default .oe files by reading out the current directory"""
29 contents = os.listdir(path)
32 (root, ext) = os.path.splitext(f)
34 oefiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
37 def find_oefiles( path ):
38 """Find all the .oe files in a directory (uses find)"""
39 findcmd = 'find ' + path + ' -name *.oe | grep -v SCCS/'
41 finddata = os.popen(findcmd)
44 return finddata.readlines()
47 depstr = data.getVar('__depends', d)
49 deps = depstr.split(" ")
51 (f,old_mtime_s) = dep.split("@")
52 old_mtime = int(old_mtime_s)
53 new_mtime = parse.cached_mtime(f)
54 if (new_mtime > old_mtime):
58 def load_oefile( oefile ):
59 """Load and parse one .oe build file"""
62 cache_oefile = oefile.replace( '/', '_' )
65 cache_mtime = os.stat( "%s/%s" % ( cache, cache_oefile ) )[8]
68 file_mtime = parse.cached_mtime(oefile)
70 if file_mtime > cache_mtime:
71 #print " : '%s' dirty. reparsing..." % oefile
74 #print " : '%s' clean. loading from cache..." % oefile
75 cache_data = unpickle_oe( cache_oefile )
76 if deps_clean(cache_data):
77 return cache_data, True
79 oepath = data.getVar('OEPATH', cfg)
80 safeoepath = data.getVar('OEPATH', cfg)
81 topdir = data.getVar('TOPDIR', cfg)
83 topdir = os.path.abspath(os.getcwd())
85 data.setVar('TOPDIR', topdir, cfg)
86 oefile = os.path.abspath(oefile)
87 oefile_loc = os.path.abspath(os.path.dirname(oefile))
88 # expand tmpdir to include this topdir
89 data.setVar('TMPDIR', data.getVar('TMPDIR', cfg, 1) or "", cfg)
90 # add topdir to oepath
91 oepath = "%s:%s" % (topdir, oepath)
92 # set topdir to location of .oe file
94 #data.setVar('TOPDIR', topdir, cfg)
95 # add that topdir to oepath
96 oepath = "%s:%s" % (topdir, oepath)
98 oldpath = os.path.abspath(os.getcwd())
100 data.setVar('OEPATH', oepath, cfg)
101 oe = copy.deepcopy(cfg)
103 parse.handle(oefile, oe) # read .oe data
104 if cache is not None: pickle_oe( cache_oefile, oe) # write cache
109 data.setVar('OEPATH', safeoepath, cfg)
111 def pickle_oe( oefile, oe ):
112 p = pickle.Pickler( file( "%s/%s" % ( cache, oefile ), "wb" ), -1 )
115 def unpickle_oe( oefile ):
116 p = pickle.Unpickler( file( "%s/%s" % ( cache, oefile ), "rb" ) )
118 funcstr = data.getVar('__functions__', oe)
120 comp = compile(funcstr, "<pickled>", "exec")
121 exec comp in __builtins__
124 def collect_oefiles( progressCallback ):
125 """Collect all available .oe build files"""
127 parsed, cached, skipped = 0, 0, 0
129 cache = oe.data.getVar( "CACHE", cfg, 1 )
130 if cache is not None:
131 print "NOTE: Using cache in '%s'" % cache
135 oe.mkdirhier( cache )
136 else: print "NOTE: Not using a cache. Set CACHE = <directory> to enable."
137 files = (data.getVar( "OEFILES", cfg, 1 ) or "").split()
138 data.setVar("OEFILES", " ".join(files), cfg)
141 files = get_oefiles()
144 oe.error("no files to build.")
149 dirfiles = find_oefiles(f)
153 newfiles += glob.glob(f) or [ f ]
155 oemask = oe.data.getVar('OEMASK', cfg, 1) or ""
157 oemask_compiled = re.compile(oemask)
158 except sre_constants.error:
159 oe.fatal("OEMASK is not a valid regular expression.")
161 for i in xrange( len( newfiles ) ):
163 if oemask and re.search(oemask_compiled, f):
164 oe.debug(1, "oemake: skipping %s" % f)
166 progressCallback( i + 1, len( newfiles ), f )
167 debug(1, "oemake: parsing %s" % f)
169 # read a file's metadata
171 pkgdata[f], fromCache = load_oefile(f)
172 if fromCache: cached += 1
175 if pkgdata[f] is not None:
176 # allow metadata files to add items to OEFILES
177 #data.update_data(pkgdata[f])
178 addoefiles = data.getVar('OEFILES', pkgdata[f]) or None
180 for aof in addoefiles.split():
181 if not files.count(aof):
182 if not os.path.isabs(aof):
183 aof = os.path.join(os.path.dirname(f),aof)
185 for var in pkgdata[f].keys():
186 if data.getVarFlag(var, "handler", pkgdata[f]) and data.getVar(var, pkgdata[f]):
187 event.register(data.getVar(var, pkgdata[f]))
189 oe.error("opening %s: %s" % (f, e))
191 except oe.parse.SkipPackage:
193 print "\rNOTE: Parsing finished. %d cached, %d parsed, %d skipped." % ( cached, parsed, skipped ),
195 def explode_version(s):
198 alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$')
199 numeric_regexp = re.compile('^(\d+)(.*)$')
202 m = numeric_regexp.match(s)
203 r.append(int(m.group(1)))
206 if s[0] in ascii_letters:
207 m = alpha_regexp.match(s)
214 def vercmp_part(a, b):
215 va = explode_version(a)
216 vb = explode_version(b)
226 if ca == None and cb == None:
237 r = vercmp_part(va, vb)
239 r = vercmp_part(ra, rb)