summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/build.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/build.py')
-rw-r--r--bitbake/lib/bb/build.py226
1 files changed, 118 insertions, 108 deletions
diff --git a/bitbake/lib/bb/build.py b/bitbake/lib/bb/build.py
index 1d6742b6e6..6d80b4b549 100644
--- a/bitbake/lib/bb/build.py
+++ b/bitbake/lib/bb/build.py
@@ -25,8 +25,8 @@
25# 25#
26#Based on functions from the base bb module, Copyright 2003 Holger Schurig 26#Based on functions from the base bb module, Copyright 2003 Holger Schurig
27 27
28from bb import data, fetch, event, mkdirhier, utils 28from bb import data, event, mkdirhier, utils
29import bb, os 29import bb, os, sys
30 30
31# When we execute a python function we'd like certain things 31# When we execute a python function we'd like certain things
32# in all namespaces, hence we add them to __builtins__ 32# in all namespaces, hence we add them to __builtins__
@@ -37,7 +37,11 @@ __builtins__['os'] = os
37 37
38# events 38# events
39class FuncFailed(Exception): 39class FuncFailed(Exception):
40 """Executed function failed""" 40 """
41 Executed function failed
42 First parameter a message
43 Second paramter is a logfile (optional)
44 """
41 45
42class EventException(Exception): 46class EventException(Exception):
43 """Exception which is associated with an Event.""" 47 """Exception which is associated with an Event."""
@@ -50,7 +54,9 @@ class TaskBase(event.Event):
50 54
51 def __init__(self, t, d ): 55 def __init__(self, t, d ):
52 self._task = t 56 self._task = t
53 event.Event.__init__(self, d) 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:])
54 60
55 def getTask(self): 61 def getTask(self):
56 return self._task 62 return self._task
@@ -68,6 +74,10 @@ class TaskSucceeded(TaskBase):
68 74
69class TaskFailed(TaskBase): 75class TaskFailed(TaskBase):
70 """Task execution failed""" 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)
71 81
72class InvalidTask(TaskBase): 82class InvalidTask(TaskBase):
73 """Invalid Task""" 83 """Invalid Task"""
@@ -104,42 +114,116 @@ def exec_func(func, d, dirs = None):
104 else: 114 else:
105 adir = data.getVar('B', d, 1) 115 adir = data.getVar('B', d, 1)
106 116
117 # Save current directory
107 try: 118 try:
108 prevdir = os.getcwd() 119 prevdir = os.getcwd()
109 except OSError: 120 except OSError:
110 prevdir = data.getVar('TOPDIR', d, True) 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)
111 if adir and os.access(adir, os.F_OK): 134 if adir and os.access(adir, os.F_OK):
112 os.chdir(adir) 135 os.chdir(adir)
113 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
114 locks = [] 160 locks = []
115 lockfiles = (data.expand(flags['lockfiles'], d) or "").split() 161 lockfiles = (data.expand(flags['lockfiles'], d) or "").split()
116 for lock in lockfiles: 162 for lock in lockfiles:
117 locks.append(bb.utils.lockfile(lock)) 163 locks.append(bb.utils.lockfile(lock))
118 164
119 if flags['python']: 165 try:
120 exec_func_python(func, d) 166 # Run the function
121 else: 167 if ispython:
122 exec_func_shell(func, d, flags) 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
123 177
124 for lock in locks: 178 finally:
125 bb.utils.unlockfile(lock)
126 179
127 if os.path.exists(prevdir): 180 # Unlock any lockfiles
128 os.chdir(prevdir) 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()
129 193
130def exec_func_python(func, d): 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):
131 """Execute a python BB 'function'""" 204 """Execute a python BB 'function'"""
132 import re 205 import re, os
133 206
134 bbfile = bb.data.getVar('FILE', d, 1) 207 bbfile = bb.data.getVar('FILE', d, 1)
135 tmp = "def " + func + "():\n%s" % data.getVar(func, d) 208 tmp = "def " + func + "():\n%s" % data.getVar(func, d)
136 tmp += '\n' + func + '()' 209 tmp += '\n' + func + '()'
210
211 f = open(runfile, "w")
212 f.write(tmp)
137 comp = utils.better_compile(tmp, func, bbfile) 213 comp = utils.better_compile(tmp, func, bbfile)
138 g = {} # globals 214 g = {} # globals
139 g['d'] = d 215 g['d'] = d
140 utils.better_exec(comp, g, tmp, bbfile) 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)
141 225
142def exec_func_shell(func, d, flags): 226def exec_func_shell(func, d, runfile, logfile, flags):
143 """Execute a shell BB 'function' Returns true if execution was successful. 227 """Execute a shell BB 'function' Returns true if execution was successful.
144 228
145 For this, it creates a bash shell script in the tmp dectory, writes the local 229 For this, it creates a bash shell script in the tmp dectory, writes the local
@@ -149,23 +233,13 @@ def exec_func_shell(func, d, flags):
149 of the directories you need created prior to execution. The last 233 of the directories you need created prior to execution. The last
150 item in the list is where we will chdir/cd to. 234 item in the list is where we will chdir/cd to.
151 """ 235 """
152 import sys
153 236
154 deps = flags['deps'] 237 deps = flags['deps']
155 check = flags['check'] 238 check = flags['check']
156 interact = flags['interactive']
157 if check in globals(): 239 if check in globals():
158 if globals()[check](func, deps): 240 if globals()[check](func, deps):
159 return 241 return
160 242
161 global logfile
162 t = data.getVar('T', d, 1)
163 if not t:
164 return 0
165 mkdirhier(t)
166 logfile = "%s/log.%s.%s" % (t, func, str(os.getpid()))
167 runfile = "%s/run.%s.%s" % (t, func, str(os.getpid()))
168
169 f = open(runfile, "w") 243 f = open(runfile, "w")
170 f.write("#!/bin/sh -e\n") 244 f.write("#!/bin/sh -e\n")
171 if bb.msg.debug_level['default'] > 0: f.write("set -x\n") 245 if bb.msg.debug_level['default'] > 0: f.write("set -x\n")
@@ -177,91 +251,21 @@ def exec_func_shell(func, d, flags):
177 os.chmod(runfile, 0775) 251 os.chmod(runfile, 0775)
178 if not func: 252 if not func:
179 bb.msg.error(bb.msg.domain.Build, "Function not specified") 253 bb.msg.error(bb.msg.domain.Build, "Function not specified")
180 raise FuncFailed() 254 raise FuncFailed("Function not specified for exec_func_shell")
181
182 # open logs
183 si = file('/dev/null', 'r')
184 try:
185 if bb.msg.debug_level['default'] > 0:
186 so = os.popen("tee \"%s\"" % logfile, "w")
187 else:
188 so = file(logfile, 'w')
189 except OSError, e:
190 bb.msg.error(bb.msg.domain.Build, "opening log file: %s" % e)
191 pass
192
193 se = so
194
195 if not interact:
196 # dup the existing fds so we dont lose them
197 osi = [os.dup(sys.stdin.fileno()), sys.stdin.fileno()]
198 oso = [os.dup(sys.stdout.fileno()), sys.stdout.fileno()]
199 ose = [os.dup(sys.stderr.fileno()), sys.stderr.fileno()]
200
201 # replace those fds with our own
202 os.dup2(si.fileno(), osi[1])
203 os.dup2(so.fileno(), oso[1])
204 os.dup2(se.fileno(), ose[1])
205 255
206 # execute function 256 # execute function
207 prevdir = os.getcwd()
208 if flags['fakeroot']: 257 if flags['fakeroot']:
209 maybe_fakeroot = "PATH=\"%s\" fakeroot " % bb.data.getVar("PATH", d, 1) 258 maybe_fakeroot = "PATH=\"%s\" fakeroot " % bb.data.getVar("PATH", d, 1)
210 else: 259 else:
211 maybe_fakeroot = '' 260 maybe_fakeroot = ''
212 lang_environment = "LC_ALL=C " 261 lang_environment = "LC_ALL=C "
213 ret = os.system('%s%ssh -e %s' % (lang_environment, maybe_fakeroot, runfile)) 262 ret = os.system('%s%ssh -e %s' % (lang_environment, maybe_fakeroot, runfile))
214 try:
215 os.chdir(prevdir)
216 except:
217 pass
218
219 if not interact:
220 # restore the backups
221 os.dup2(osi[0], osi[1])
222 os.dup2(oso[0], oso[1])
223 os.dup2(ose[0], ose[1])
224 263
225 # close our logs 264 if ret == 0:
226 si.close()
227 so.close()
228 se.close()
229
230 if os.path.exists(logfile) and os.path.getsize(logfile) == 0:
231 bb.msg.debug(2, bb.msg.domain.Build, "Zero size logfile %s, removing" % logfile)
232 os.remove(logfile)
233
234 # close the backup fds
235 os.close(osi[0])
236 os.close(oso[0])
237 os.close(ose[0])
238
239 if ret==0:
240 if bb.msg.debug_level['default'] > 0:
241 os.remove(runfile)
242# os.remove(logfile)
243 return 265 return
244 else: 266
245 bb.msg.error(bb.msg.domain.Build, "function %s failed" % func) 267 bb.msg.error(bb.msg.domain.Build, "Function %s failed" % func)
246 if data.getVar("BBINCLUDELOGS", d): 268 raise FuncFailed("function %s failed" % func, logfile)
247 bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile)
248 number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d)
249 if number_of_lines:
250 os.system('tail -n%s %s' % (number_of_lines, logfile))
251 elif os.path.exists(logfile):
252 f = open(logfile, "r")
253 while True:
254 l = f.readline()
255 if l == '':
256 break
257 l = l.rstrip()
258 print '| %s' % l
259 f.close()
260 else:
261 bb.msg.error(bb.msg.domain.Build, "There was no logfile output")
262 else:
263 bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile)
264 raise FuncFailed( logfile )
265 269
266 270
267def exec_task(task, d): 271def exec_task(task, d):
@@ -282,14 +286,20 @@ def exec_task(task, d):
282 data.setVar('OVERRIDES', 'task-%s:%s' % (task[3:], old_overrides), localdata) 286 data.setVar('OVERRIDES', 'task-%s:%s' % (task[3:], old_overrides), localdata)
283 data.update_data(localdata) 287 data.update_data(localdata)
284 data.expandKeys(localdata) 288 data.expandKeys(localdata)
285 event.fire(TaskStarted(task, localdata)) 289 event.fire(TaskStarted(task, localdata), localdata)
286 exec_func(task, localdata) 290 exec_func(task, localdata)
287 event.fire(TaskSucceeded(task, localdata)) 291 event.fire(TaskSucceeded(task, localdata), localdata)
288 except FuncFailed, reason: 292 except FuncFailed, message:
289 bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % reason ) 293 # Try to extract the optional logfile
290 failedevent = TaskFailed(task, d) 294 try:
291 event.fire(failedevent) 295 (msg, logfile) = message
292 raise EventException("Function failed in task: %s" % reason, failedevent) 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)
293 303
294 # make stamp, or cause event and raise exception 304 # make stamp, or cause event and raise exception
295 if not data.getVarFlag(task, 'nostamp', d) and not data.getVarFlag(task, 'selfstamp', d): 305 if not data.getVarFlag(task, 'nostamp', d) and not data.getVarFlag(task, 'selfstamp', d):