Revamp bits of the variable set from filename
[bitbake.git] / bin / oe / parse / OEHandler.py
1 """class for handling .oe files
2
3    Reads the file and obtains its metadata"""
4
5 import re, oe, string, os, sys
6 import oe
7 import oe.fetch
8 from oe import debug, data, fetch, fatal
9
10 from oe.parse.ConfHandler import include, localpath, obtain, init
11
12 __func_start_regexp__    = re.compile( r"((?P<py>python)\s*)*(?P<func>\w+)\s*\(\s*\)\s*{$" )
13 __inherit_regexp__       = re.compile( r"inherit\s+(.+)" )
14 __export_func_regexp__   = re.compile( r"EXPORT_FUNCTIONS\s+(.+)" )
15 __addtask_regexp__       = re.compile("addtask\s+(?P<func>\w+)\s*((before\s*(?P<before>((.*(?=after))|(.*))))|(after\s*(?P<after>((.*(?=before))|(.*)))))*")
16 __addhandler_regexp__       = re.compile( r"addhandler\s+(.+)" )
17
18 __infunc__ = ""
19 __body__   = []
20 __oepath_found__ = 0
21 __classname__ = ""
22 classes = [ None, ]
23
24 def supports(fn):
25         localfn = localpath(fn)
26         return localfn[-3:] == ".oe" or localfn[-8:] == ".oeclass"
27
28 __inherit_cache = []
29 def inherit(files, d):
30         fn = ""
31         lineno = 0
32         for f in files:
33                 file = data.expand(f, d)
34                 if file[0] != "/" and file[-8:] != ".oeclass":
35                         file = "classes/%s.oeclass" % file
36
37                 if not file in __inherit_cache:
38                         debug(2, "%s:%d: inheriting %s" % (fn, lineno, file))
39                         __inherit_cache.append(file)
40                         include(fn, file, d)
41
42
43 def handle(fn, d = {}):
44         global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __infunc__, __body__, __oepath_found__
45         __body__ = []
46         __oepath_found__ = 0
47         __infunc__ = ""
48         __classname__ = ""
49
50         (root, ext) = os.path.splitext(os.path.basename(fn))
51         if ext == ".oeclass":
52                 __classname__ = root
53                 classes.append(__classname__)
54
55         init(d)
56         data.inheritFromOS(2, d)
57         fn = obtain(fn, d)
58         oepath = ['.']
59         if not os.path.isabs(fn):
60                 f = None
61                 voepath = data.getVar("OEPATH", d)
62                 if voepath:
63                         oepath += voepath.split(":")
64                 for p in oepath:
65                         p = data.expand(p, d)
66                         if os.access(os.path.join(p, fn), os.R_OK):
67                                 f = open(os.path.join(p, fn), 'r')
68                 if f is None:
69                         raise IOError("file not found")
70         else:
71                 f = open(fn,'r')
72
73         if ext != ".oeclass":
74                 vars_from_fn(fn, d)
75                 import string
76                 i = string.split(data.getVar("INHERIT", d, 1) or "")
77                 if not "base" in i and __classname__ != "base":
78                         i[0:0] = ["base"]
79                 inherit(i, d)
80
81         lineno = 0
82         while 1:
83                 lineno = lineno + 1
84                 s = f.readline()
85                 if not s: break
86                 w = s.strip()
87                 if not w: continue              # skip empty lines
88                 s = s.rstrip()
89                 if s[0] == '#': continue        # skip comments
90                 while s[-1] == '\\':
91                         s2 = f.readline()[:-1].strip()
92                         s = s[:-1] + s2
93                 feeder(lineno, s, fn, d)
94         if ext == ".oeclass":
95                 classes.remove(__classname__)
96         else:
97                 set_automatic_vars(fn, d)
98                 set_additional_vars(fn, d)
99                 data.update_data(d)
100         return d
101
102 def feeder(lineno, s, fn, d):
103         global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __infunc__, __body__, __oepath_found__, classes, oe
104         if __infunc__:
105                 if s == '}':
106                         __body__.append('')
107                         data.setVar(__infunc__, string.join(__body__, '\n'), d)
108                         data.setVarFlag(__infunc__, "func", 1, d)
109                         __infunc__ = ""
110                         __body__ = []
111                 else:
112                         __body__.append(s)
113                 return
114                         
115         m = __func_start_regexp__.match(s)
116         if m:
117                 __infunc__ = m.group("func")
118                 key = __infunc__
119                 if data.getVar(key, d):
120                         # clean up old version of this piece of metadata, as its
121                         # flags could cause problems
122                         data.setVarFlag(key, 'python', None, d)
123                 if m.group("py") is not None:
124                         data.setVarFlag(key, "python", "1", d)
125                 else:
126                         data.setVarFlag(key, "python", None, d)
127                 return
128
129         __word__ = re.compile(r"\S+")
130
131         m = __export_func_regexp__.match(s)
132         if m:
133                 fns = m.group(1)
134                 n = __word__.findall(fns)
135                 for f in n:
136                         allvars = []
137                         allvars.append(f)
138                         allvars.append("%s_%s" % (classes[-1], f))
139
140                         vars = [[ allvars[0], allvars[1] ]]
141                         if len(classes) > 1 and classes[-2] is not None:
142                                 allvars.append("%s_%s" % (classes[-2], f))
143                                 vars = []
144                                 vars.append([allvars[2], allvars[1]])
145                                 vars.append([allvars[0], allvars[2]])
146
147                         for (var, calledvar) in vars:
148                                 if data.getVar(var, d) and not data.getVarFlag(var, 'export_func', d):
149                                         continue
150
151                                 # clean up after possible old flags
152                                 if data.getVar(var, d):
153                                         data.setVarFlag(var, 'python', None, d)
154                                         data.setVarFlag(var, 'func', None, d)
155
156                                 for flag in [ "func", "python", "dirs" ]:
157                                         __dirty = 0
158 #                                       if data.getVarFlag(var, flag, d):
159 #                                               __dirty = var
160                                         if data.getVarFlag(calledvar, flag, d):
161                                                 data.setVarFlag(var, flag, data.getVarFlag(calledvar, flag, d), d)
162
163                                 if data.getVarFlag(calledvar, "python", d):
164                                         data.setVar(var, "\treturn exec_func('%s', d)\n" % calledvar, d)
165                                 else:
166                                         data.setVar(var, "\t%s\n" % calledvar, d)
167                                 data.setVarFlag(var, 'export_func', '1', d)
168
169                 return
170
171         m = __addtask_regexp__.match(s)
172         if m:
173                 func = m.group("func")
174                 before = m.group("before")
175                 after = m.group("after")
176                 if func is None:
177                         return
178                 var = "do_" + func
179
180                 data.setVarFlag(var, "task", 1, d)
181
182                 if after is not None:
183                         # set up deps for function
184                         data.setVarFlag(var, "deps", after.split(), d)
185                 if before is not None:
186                         # set up things that depend on this func 
187                         data.setVarFlag(var, "postdeps", before.split(), d)
188                 return
189
190         m = __addhandler_regexp__.match(s)
191         if m:
192                 fns = m.group(1)
193                 hs = __word__.findall(fns)
194                 for h in hs:
195                         data.setVarFlag(h, "handler", 1, d)
196                 return
197
198         m = __inherit_regexp__.match(s)
199         if m:
200
201                 files = m.group(1)
202                 n = __word__.findall(files)
203                 inherit(n, d)
204                 return
205
206         from oe.parse import ConfHandler
207         return ConfHandler.feeder(lineno, s, fn, d)
208
209 __pkgsplit_cache__={}
210
211 def vars_from_fn(mypkg, d, store=2, silent=1):
212         """Obtain PN,PV,PR variables from filename.
213            If store is 0, do not store variables into the data store.
214            If 1, store variables into data store only if not already set.
215            If 2, store variables into data store regardless.
216
217         >>> pkgsplit('')
218         >>> pkgsplit('x')
219         >>> pkgsplit('x-')
220         >>> pkgsplit('-1')
221         >>> pkgsplit('glibc-1.2-8.9-r7')
222         >>> pkgsplit('glibc-2.2.5-r7')
223         ['glibc', '2.2.5', 'r7']
224         >>> pkgsplit('foo-1.2-1')
225         >>> pkgsplit('Mesa-3.0')
226         ['Mesa', '3.0', 'r0']
227         """
228
229         def isvalid(type, str):
230                 if type == "PR":
231                         if str[0] != 'r':
232                                 return 0
233                 return 1
234
235         map = { 0: "CATEGORY", 1: "PN", 2: "PV", 3: "PR" }
236         splitmap = [ 'CATEGORY', 'PN', 'PV', 'PR' ]
237         heh = [ "PR", "PV", "PN" ]
238         try:
239                 return __pkgsplit_cache__[mypkg]
240         except KeyError:
241                 pass
242
243         pkgsplit = [None, None, None, None]
244         myfile = os.path.splitext(os.path.basename(mypkg))
245         mydir = os.path.basename(os.path.dirname(mypkg))
246         pkgsplit[splitmap.index('CATEGORY')] = mydir
247         if store != 0:
248                 getval = data.getVar('CATEGORY', d) or None 
249                 if store == 2 or not getval:
250                         data.setVar('CATEGORY', mydir, d)
251
252         myparts = string.split(myfile[0],'-')
253         basepos = 0
254         for i in heh:
255                 ind = heh.index(i)
256                 loc = int.__neg__(ind + 1) + basepos
257                 splitloc = len(heh) - basepos - ind
258                 getval = data.getVar(i, d) or None 
259                 if not isvalid(i, myparts[loc]):
260                         basepos += 1
261                         continue
262                 if ind == len(heh) - 1:
263                         str = string.join(myparts[0:loc + basepos], "-")
264                 else:
265                         str = myparts[loc]
266                 pkgsplit[splitloc] = str
267                 if store != 0:
268                         if store == 1 and getval:
269                                 continue
270                         data.setVar(i, str, d)
271         __pkgsplit_cache__[mypkg] = pkgsplit
272         return pkgsplit
273
274 def set_automatic_vars(file, d):
275         """Deduce per-package environment variables"""
276
277         debug(2, "setting automatic vars")
278 #       pkg = oe.catpkgsplit(file)
279 #       pkg = vars_from_fn(file, d)
280 #       if None in pkg:
281 #               fatal("package file not in valid format")
282 #       if not data.getVar('CATEGORY', d):
283 #               if pkg[0] is None:
284 #                       fatal("package file not in valid format")
285 #               data.setVar('CATEGORY', pkg[0], d)
286 #       if not data.getVar('PN', d):
287 #               if pkg[1] is None:
288 #                       fatal("package file not in valid format")
289 #               data.setVar('PN', pkg[1], d)
290 #       if not data.getVar('PV', d):
291 #               if pkg[2] is None:
292 #                       fatal("package file not in valid format")
293 #               data.setVar('PV', pkg[2], d)
294 #       if not data.getVar('PR', d):
295 #               if pkg[3] is None:
296 #                       fatal("package file not in valid format")
297 #               data.setVar('PR', pkg[3], d)
298
299         data.setVar('P', '${PN}-${PV}', d)
300         data.setVar('PF', '${P}-${PR}', d)
301
302         for t in [ os.path.dirname(file), '${TOPDIR}/${CATEGORY}' ]:
303                 if data.getVar('FILESDIR', d):
304                         break
305                 print "t is %s" % t
306                 for s in [ '${PF}', 
307                           '${PN}-${PV}',
308                           'files',
309                           '']:
310                         path = data.expand(os.path.join(t, s), d)
311                         if not os.path.isabs(path):
312                                 path = os.path.abspath(path)
313                         print "checking %s" % path
314                         if os.access(path, os.R_OK):
315                                 data.setVar('FILESDIR', path, d)
316                                 break
317
318         if not data.getVar('WORKDIR', d):
319                 data.setVar('WORKDIR', '${TMPDIR}/${CATEGORY}/${PF}', d)
320         if not data.getVar('T', d):
321                 data.setVar('T', '${WORKDIR}/temp', d)
322         if not data.getVar('D', d):
323                 data.setVar('D', '${WORKDIR}/image', d)
324         if not data.getVar('S', d):
325                 data.setVar('S', '${WORKDIR}/${P}', d)
326         if not data.getVar('SLOT', d):
327                 data.setVar('SLOT', '0', d)
328         data.inheritFromOS(3, d)
329
330 def set_additional_vars(file, d):
331         """Deduce rest of variables, e.g. ${A} out of ${SRC_URI}"""
332
333         debug(2,"set_additional_vars")
334
335         data.inheritFromOS(4, d)
336         src_uri = data.getVar('SRC_URI', d)
337         if not src_uri:
338                 return
339         src_uri = data.expand(src_uri, d)
340
341         # Do we already have something in A?
342         a = data.getVar('A', d)
343         if a:
344                 a = data.expand(a, d).split()
345         else:
346                 a = []
347
348         from oe import fetch
349         try:
350                 fetch.init(src_uri.split())
351         except fetch.NoMethodError:
352                 pass
353
354         a += fetch.localpaths()
355         del fetch
356         data.setVar('A', string.join(a), d)
357
358
359 # Add us to the handlers list
360 from oe.parse import handlers
361 handlers.append({'supports': supports, 'handle': handle, 'init': init})
362 del handlers