summaryrefslogtreecommitdiffstats
path: root/bitbake-dev/lib/bb/build.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake-dev/lib/bb/build.py')
-rw-r--r--bitbake-dev/lib/bb/build.py394
1 files changed, 0 insertions, 394 deletions
diff --git a/bitbake-dev/lib/bb/build.py b/bitbake-dev/lib/bb/build.py
deleted file mode 100644
index 6d80b4b549..0000000000
--- a/bitbake-dev/lib/bb/build.py
+++ /dev/null
@@ -1,394 +0,0 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3#
4# BitBake 'Build' implementation
5#
6# Core code for function execution and task handling in the
7# BitBake build tools.
8#
9# Copyright (C) 2003, 2004 Chris Larson
10#
11# Based on Gentoo's portage.py.
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2 as
15# published by the Free Software Foundation.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25#
26#Based on functions from the base bb module, Copyright 2003 Holger Schurig
27
28from bb import data, event, mkdirhier, utils
29import bb, os, sys
30
31# When we execute a python function we'd like certain things
32# in all namespaces, hence we add them to __builtins__
33# If we do not do this and use the exec globals, they will
34# not be available to subfunctions.
35__builtins__['bb'] = bb
36__builtins__['os'] = os
37
38# events
39class FuncFailed(Exception):
40 """
41 Executed function failed
42 First parameter a message
43 Second paramter is a logfile (optional)
44 """
45
46class EventException(Exception):
47 """Exception which is associated with an Event."""
48
49 def __init__(self, msg, event):
50 self.args = msg, event
51
52class TaskBase(event.Event):
53 """Base class for task events"""
54
55 def __init__(self, t, d ):
56 self._task = t
57 self._package = bb.data.getVar("PF", d, 1)
58 event.Event.__init__(self)
59 self._message = "package %s: task %s: %s" % (bb.data.getVar("PF", d, 1), t, bb.event.getName(self)[4:])
60
61 def getTask(self):
62 return self._task
63
64 def setTask(self, task):
65 self._task = task
66
67 task = property(getTask, setTask, None, "task property")
68
69class TaskStarted(TaskBase):
70 """Task execution started"""
71
72class TaskSucceeded(TaskBase):
73 """Task execution completed"""
74
75class TaskFailed(TaskBase):
76 """Task execution failed"""
77 def __init__(self, msg, logfile, t, d ):
78 self.logfile = logfile
79 self.msg = msg
80 TaskBase.__init__(self, t, d)
81
82class InvalidTask(TaskBase):
83 """Invalid Task"""
84
85# functions
86
87def exec_func(func, d, dirs = None):
88 """Execute an BB 'function'"""
89
90 body = data.getVar(func, d)
91 if not body:
92 return
93
94 flags = data.getVarFlags(func, d)
95 for item in ['deps', 'check', 'interactive', 'python', 'cleandirs', 'dirs', 'lockfiles', 'fakeroot']:
96 if not item in flags:
97 flags[item] = None
98
99 ispython = flags['python']
100
101 cleandirs = (data.expand(flags['cleandirs'], d) or "").split()
102 for cdir in cleandirs:
103 os.system("rm -rf %s" % cdir)
104
105 if dirs:
106 dirs = data.expand(dirs, d)
107 else:
108 dirs = (data.expand(flags['dirs'], d) or "").split()
109 for adir in dirs:
110 mkdirhier(adir)
111
112 if len(dirs) > 0:
113 adir = dirs[-1]
114 else:
115 adir = data.getVar('B', d, 1)
116
117 # Save current directory
118 try:
119 prevdir = os.getcwd()
120 except OSError:
121 prevdir = data.getVar('TOPDIR', d, True)
122
123 # Setup logfiles
124 t = data.getVar('T', d, 1)
125 if not t:
126 bb.msg.fatal(bb.msg.domain.Build, "T not set")
127 mkdirhier(t)
128 # Gross hack, FIXME
129 import random
130 logfile = "%s/log.%s.%s.%s" % (t, func, str(os.getpid()),random.random())
131 runfile = "%s/run.%s.%s" % (t, func, str(os.getpid()))
132
133 # Change to correct directory (if specified)
134 if adir and os.access(adir, os.F_OK):
135 os.chdir(adir)
136
137 # Handle logfiles
138 si = file('/dev/null', 'r')
139 try:
140 if bb.msg.debug_level['default'] > 0 or ispython:
141 so = os.popen("tee \"%s\"" % logfile, "w")
142 else:
143 so = file(logfile, 'w')
144 except OSError, e:
145 bb.msg.error(bb.msg.domain.Build, "opening log file: %s" % e)
146 pass
147
148 se = so
149
150 # Dup the existing fds so we dont lose them
151 osi = [os.dup(sys.stdin.fileno()), sys.stdin.fileno()]
152 oso = [os.dup(sys.stdout.fileno()), sys.stdout.fileno()]
153 ose = [os.dup(sys.stderr.fileno()), sys.stderr.fileno()]
154
155 # Replace those fds with our own
156 os.dup2(si.fileno(), osi[1])
157 os.dup2(so.fileno(), oso[1])
158 os.dup2(se.fileno(), ose[1])
159
160 locks = []
161 lockfiles = (data.expand(flags['lockfiles'], d) or "").split()
162 for lock in lockfiles:
163 locks.append(bb.utils.lockfile(lock))
164
165 try:
166 # Run the function
167 if ispython:
168 exec_func_python(func, d, runfile, logfile)
169 else:
170 exec_func_shell(func, d, runfile, logfile, flags)
171
172 # Restore original directory
173 try:
174 os.chdir(prevdir)
175 except:
176 pass
177
178 finally:
179
180 # Unlock any lockfiles
181 for lock in locks:
182 bb.utils.unlockfile(lock)
183
184 # Restore the backup fds
185 os.dup2(osi[0], osi[1])
186 os.dup2(oso[0], oso[1])
187 os.dup2(ose[0], ose[1])
188
189 # Close our logs
190 si.close()
191 so.close()
192 se.close()
193
194 if os.path.exists(logfile) and os.path.getsize(logfile) == 0:
195 bb.msg.debug(2, bb.msg.domain.Build, "Zero size logfile %s, removing" % logfile)
196 os.remove(logfile)
197
198 # Close the backup fds
199 os.close(osi[0])
200 os.close(oso[0])
201 os.close(ose[0])
202
203def exec_func_python(func, d, runfile, logfile):
204 """Execute a python BB 'function'"""
205 import re, os
206
207 bbfile = bb.data.getVar('FILE', d, 1)
208 tmp = "def " + func + "():\n%s" % data.getVar(func, d)
209 tmp += '\n' + func + '()'
210
211 f = open(runfile, "w")
212 f.write(tmp)
213 comp = utils.better_compile(tmp, func, bbfile)
214 g = {} # globals
215 g['d'] = d
216 try:
217 utils.better_exec(comp, g, tmp, bbfile)
218 except:
219 (t,value,tb) = sys.exc_info()
220
221 if t in [bb.parse.SkipPackage, bb.build.FuncFailed]:
222 raise
223 bb.msg.error(bb.msg.domain.Build, "Function %s failed" % func)
224 raise FuncFailed("function %s failed" % func, logfile)
225
226def exec_func_shell(func, d, runfile, logfile, flags):
227 """Execute a shell BB 'function' Returns true if execution was successful.
228
229 For this, it creates a bash shell script in the tmp dectory, writes the local
230 data into it and finally executes. The output of the shell will end in a log file and stdout.
231
232 Note on directory behavior. The 'dirs' varflag should contain a list
233 of the directories you need created prior to execution. The last
234 item in the list is where we will chdir/cd to.
235 """
236
237 deps = flags['deps']
238 check = flags['check']
239 if check in globals():
240 if globals()[check](func, deps):
241 return
242
243 f = open(runfile, "w")
244 f.write("#!/bin/sh -e\n")
245 if bb.msg.debug_level['default'] > 0: f.write("set -x\n")
246 data.emit_env(f, d)
247
248 f.write("cd %s\n" % os.getcwd())
249 if func: f.write("%s\n" % func)
250 f.close()
251 os.chmod(runfile, 0775)
252 if not func:
253 bb.msg.error(bb.msg.domain.Build, "Function not specified")
254 raise FuncFailed("Function not specified for exec_func_shell")
255
256 # execute function
257 if flags['fakeroot']:
258 maybe_fakeroot = "PATH=\"%s\" fakeroot " % bb.data.getVar("PATH", d, 1)
259 else:
260 maybe_fakeroot = ''
261 lang_environment = "LC_ALL=C "
262 ret = os.system('%s%ssh -e %s' % (lang_environment, maybe_fakeroot, runfile))
263
264 if ret == 0:
265 return
266
267 bb.msg.error(bb.msg.domain.Build, "Function %s failed" % func)
268 raise FuncFailed("function %s failed" % func, logfile)
269
270
271def exec_task(task, d):
272 """Execute an BB 'task'
273
274 The primary difference between executing a task versus executing
275 a function is that a task exists in the task digraph, and therefore
276 has dependencies amongst other tasks."""
277
278 # Check whther this is a valid task
279 if not data.getVarFlag(task, 'task', d):
280 raise EventException("No such task", InvalidTask(task, d))
281
282 try:
283 bb.msg.debug(1, bb.msg.domain.Build, "Executing task %s" % task)
284 old_overrides = data.getVar('OVERRIDES', d, 0)
285 localdata = data.createCopy(d)
286 data.setVar('OVERRIDES', 'task-%s:%s' % (task[3:], old_overrides), localdata)
287 data.update_data(localdata)
288 data.expandKeys(localdata)
289 event.fire(TaskStarted(task, localdata), localdata)
290 exec_func(task, localdata)
291 event.fire(TaskSucceeded(task, localdata), localdata)
292 except FuncFailed, message:
293 # Try to extract the optional logfile
294 try:
295 (msg, logfile) = message
296 except:
297 logfile = None
298 msg = message
299 bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % message )
300 failedevent = TaskFailed(msg, logfile, task, d)
301 event.fire(failedevent, d)
302 raise EventException("Function failed in task: %s" % message, failedevent)
303
304 # make stamp, or cause event and raise exception
305 if not data.getVarFlag(task, 'nostamp', d) and not data.getVarFlag(task, 'selfstamp', d):
306 make_stamp(task, d)
307
308def extract_stamp(d, fn):
309 """
310 Extracts stamp format which is either a data dictonary (fn unset)
311 or a dataCache entry (fn set).
312 """
313 if fn:
314 return d.stamp[fn]
315 return data.getVar('STAMP', d, 1)
316
317def stamp_internal(task, d, file_name):
318 """
319 Internal stamp helper function
320 Removes any stamp for the given task
321 Makes sure the stamp directory exists
322 Returns the stamp path+filename
323 """
324 stamp = extract_stamp(d, file_name)
325 if not stamp:
326 return
327 stamp = "%s.%s" % (stamp, task)
328 mkdirhier(os.path.dirname(stamp))
329 # Remove the file and recreate to force timestamp
330 # change on broken NFS filesystems
331 if os.access(stamp, os.F_OK):
332 os.remove(stamp)
333 return stamp
334
335def make_stamp(task, d, file_name = None):
336 """
337 Creates/updates a stamp for a given task
338 (d can be a data dict or dataCache)
339 """
340 stamp = stamp_internal(task, d, file_name)
341 if stamp:
342 f = open(stamp, "w")
343 f.close()
344
345def del_stamp(task, d, file_name = None):
346 """
347 Removes a stamp for a given task
348 (d can be a data dict or dataCache)
349 """
350 stamp_internal(task, d, file_name)
351
352def add_tasks(tasklist, d):
353 task_deps = data.getVar('_task_deps', d)
354 if not task_deps:
355 task_deps = {}
356 if not 'tasks' in task_deps:
357 task_deps['tasks'] = []
358 if not 'parents' in task_deps:
359 task_deps['parents'] = {}
360
361 for task in tasklist:
362 task = data.expand(task, d)
363 data.setVarFlag(task, 'task', 1, d)
364
365 if not task in task_deps['tasks']:
366 task_deps['tasks'].append(task)
367
368 flags = data.getVarFlags(task, d)
369 def getTask(name):
370 if not name in task_deps:
371 task_deps[name] = {}
372 if name in flags:
373 deptask = data.expand(flags[name], d)
374 task_deps[name][task] = deptask
375 getTask('depends')
376 getTask('deptask')
377 getTask('rdeptask')
378 getTask('recrdeptask')
379 getTask('nostamp')
380 task_deps['parents'][task] = []
381 for dep in flags['deps']:
382 dep = data.expand(dep, d)
383 task_deps['parents'][task].append(dep)
384
385 # don't assume holding a reference
386 data.setVar('_task_deps', task_deps, d)
387
388def remove_task(task, kill, d):
389 """Remove an BB 'task'.
390
391 If kill is 1, also remove tasks that depend on this task."""
392
393 data.delVarFlag(task, 'task', d)
394