d3cd38f246cdad5e069a18701ca15f8a2d932c7c
[vuplus_bitbake] / bin / oe / make.py
1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3 """
4 OpenEmbedded 'Make' implementations
5
6 Functions for reading OE files, building a dependency graph and
7 building a set of OE files while walking along the dependency graph.
8
9 This file is part of the OpenEmbedded (http://openembedded.org) build infrastructure.
10 """
11
12 from oe import debug, digraph, data, fetch, fatal, error, note, event, parse
13 import copy, oe, re, sys, os, glob, sre_constants
14 try:
15     import cPickle as pickle
16 except ImportError:
17     import pickle
18     print "NOTE: Importing cPickle failed. Falling back to a very slow implementation."
19
20 pkgdata = {}
21 cfg = {}
22 cache = None
23 digits = "0123456789"
24 ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
25 mtime_cache = {}
26
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)
30     oefiles = []
31     for f in contents:
32         (root, ext) = os.path.splitext(f)
33         if ext == ".oe":
34             oefiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
35     return oefiles
36
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/'
40     try:
41         finddata = os.popen(findcmd)
42     except OSError:
43         return []
44     return finddata.readlines()
45
46 def deps_clean(d):
47     depstr = data.getVar('__depends', d)
48     if depstr:
49         deps = depstr.split(" ")
50         for dep in deps:
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):
55                 return False
56     return True
57
58 def load_oefile( oefile ):
59     """Load and parse one .oe build file"""
60
61     if cache is not None:
62         cache_oefile = oefile.replace( '/', '_' )
63
64         try:
65             cache_mtime = os.stat( "%s/%s" % ( cache, cache_oefile ) )[8]
66         except OSError:
67             cache_mtime = 0
68         file_mtime = parse.cached_mtime(oefile)
69
70         if file_mtime > cache_mtime:
71             #print " : '%s' dirty. reparsing..." % oefile
72             pass
73         else:
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
78
79     oepath = data.getVar('OEPATH', cfg)
80     safeoepath = data.getVar('OEPATH', cfg)
81     topdir = data.getVar('TOPDIR', cfg)
82     if not topdir:
83         topdir = os.path.abspath(os.getcwd())
84         # set topdir to here
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
93     topdir = oefile_loc
94     #data.setVar('TOPDIR', topdir, cfg)
95     # add that topdir to oepath
96     oepath = "%s:%s" % (topdir, oepath)
97     # go there
98     oldpath = os.path.abspath(os.getcwd())
99     os.chdir(topdir)
100     data.setVar('OEPATH', oepath, cfg)
101     oe = copy.deepcopy(cfg)
102     try:
103         parse.handle(oefile, oe) # read .oe data
104         if cache is not None: pickle_oe( cache_oefile, oe) # write cache
105         os.chdir(oldpath)
106         return oe, False
107     finally:
108         os.chdir(oldpath)
109         data.setVar('OEPATH', safeoepath, cfg)
110
111 def pickle_oe( oefile, oe ):
112     p = pickle.Pickler( file( "%s/%s" % ( cache, oefile ), "wb" ), -1 )
113     p.dump( oe )
114
115 def unpickle_oe( oefile ):
116     p = pickle.Unpickler( file( "%s/%s" % ( cache, oefile ), "rb" ) )
117     oe = p.load()
118     funcstr = data.getVar('__functions__', oe)
119     if funcstr:
120         comp = compile(funcstr, "<pickled>", "exec")
121         exec comp in __builtins__
122     return oe
123
124 def collect_oefiles( progressCallback ):
125     """Collect all available .oe build files"""
126
127     parsed, cached, skipped = 0, 0, 0
128     global cache
129     cache = oe.data.getVar( "CACHE", cfg, 1 )
130     if cache is not None:
131         print "NOTE: Using cache in '%s'" % cache
132         try:
133             os.stat( cache )
134         except OSError:
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)
139
140     if not len(files):
141         files = get_oefiles()
142
143     if not len(files):
144         oe.error("no files to build.")
145
146     newfiles = []
147     for f in files:
148         if os.path.isdir(f):
149             dirfiles = find_oefiles(f)
150             if dirfiles:
151                 newfiles += dirfiles
152                 continue
153         newfiles += glob.glob(f) or [ f ]
154
155     oemask = oe.data.getVar('OEMASK', cfg, 1) or ""
156     try:
157         oemask_compiled = re.compile(oemask)
158     except sre_constants.error:
159         oe.fatal("OEMASK is not a valid regular expression.")
160
161     for i in xrange( len( newfiles ) ):
162         f = newfiles[i]
163         if oemask and re.search(oemask_compiled, f):
164               oe.debug(1, "oemake: skipping %s" % f)
165               continue
166         progressCallback( i + 1, len( newfiles ), f )
167         debug(1, "oemake: parsing %s" % f)
168
169         # read a file's metadata
170         try:
171             pkgdata[f], fromCache = load_oefile(f)
172             if fromCache: cached += 1
173             else: parsed += 1
174             deps = None
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
179                 if addoefiles:
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)
184                             files.append(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]))
188         except IOError, e:
189             oe.error("opening %s: %s" % (f, e))
190             pass
191         except oe.parse.SkipPackage:
192             skipped += 1
193     print "\rNOTE: Parsing finished. %d cached, %d parsed, %d skipped." % ( cached, parsed, skipped ), 
194
195 def explode_version(s):
196     import string
197     r = []
198     alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$')
199     numeric_regexp = re.compile('^(\d+)(.*)$')
200     while (s != ''):
201         if s[0] in digits:
202             m = numeric_regexp.match(s)
203             r.append(int(m.group(1)))
204             s = m.group(2)
205             continue
206         if s[0] in ascii_letters:
207             m = alpha_regexp.match(s)
208             r.append(m.group(1))
209             s = m.group(2)
210             continue
211         s = s[1:]
212     return r
213
214 def vercmp_part(a, b):
215     va = explode_version(a)
216     vb = explode_version(b)
217     while True:
218         if va == []:
219             ca = None
220         else:
221             ca = va.pop(0)
222         if vb == []:
223             cb = None
224         else:
225             cb = vb.pop(0)
226         if ca == None and cb == None:
227             return 0
228         if ca > cb:
229             return 1
230         if ca < cb:
231             return -1
232
233 def vercmp(ta, tb):
234     (va, ra) = ta
235     (vb, rb) = tb
236
237     r = vercmp_part(va, vb)
238     if (r == 0):
239         r = vercmp_part(ra, rb)
240     return r