# ex:ts=4:sw=4:sts=4:et # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- # # BitBake 'Build' implementation # # Core code for function execution and task handling in the # BitBake build tools. # # Copyright (C) 2003, 2004 Chris Larson # # Based on Gentoo's portage.py. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # #Based on functions from the base bb module, Copyright 2003 Holger Schurig from bb import data, fetch, event, mkdirhier, utils import bb, os # events class FuncFailed(Exception): """Executed function failed""" class EventException(Exception): """Exception which is associated with an Event.""" def __init__(self, msg, event): self.args = msg, event class TaskBase(event.Event): """Base class for task events""" def __init__(self, t, d ): self._task = t event.Event.__init__(self, d) def getTask(self): return self._task def setTask(self, task): self._task = task task = property(getTask, setTask, None, "task property") class TaskStarted(TaskBase): """Task execution started""" class TaskSucceeded(TaskBase): """Task execution completed""" class TaskFailed(TaskBase): """Task execution failed""" class InvalidTask(TaskBase): """Invalid Task""" # functions def exec_func(func, d, dirs = None): """Execute an BB 'function'""" body = data.getVar(func, d) if not body: return if not dirs: dirs = (data.getVarFlag(func, 'dirs', d) or "").split() for adir in dirs: adir = data.expand(adir, d) mkdirhier(adir) if len(dirs) > 0: adir = dirs[-1] else: adir = data.getVar('B', d, 1) adir = data.expand(adir, d) try: prevdir = os.getcwd() except OSError: prevdir = data.expand('${TOPDIR}', d) if adir and os.access(adir, os.F_OK): os.chdir(adir) if data.getVarFlag(func, "python", d): exec_func_python(func, d) else: exec_func_shell(func, d) if os.path.exists(prevdir): os.chdir(prevdir) def exec_func_python(func, d): """Execute a python BB 'function'""" import re, os tmp = "def " + func + "():\n%s" % data.getVar(func, d) tmp += '\n' + func + '()' comp = utils.better_compile(tmp, func, bb.data.getVar('FILE', d, 1) ) prevdir = os.getcwd() g = {} # globals g['bb'] = bb g['os'] = os g['d'] = d utils.better_exec(comp,g,tmp, bb.data.getVar('FILE',d,1)) if os.path.exists(prevdir): os.chdir(prevdir) def exec_func_shell(func, d): """Execute a shell BB 'function' Returns true if execution was successful. For this, it creates a bash shell script in the tmp dectory, writes the local data into it and finally executes. The output of the shell will end in a log file and stdout. Note on directory behavior. The 'dirs' varflag should contain a list of the directories you need created prior to execution. The last item in the list is where we will chdir/cd to. """ import sys deps = data.getVarFlag(func, 'deps', d) check = data.getVarFlag(func, 'check', d) interact = data.getVarFlag(func, 'interactive', d) if check in globals(): if globals()[check](func, deps): return global logfile t = data.getVar('T', d, 1) if not t: return 0 mkdirhier(t) logfile = "%s/log.%s.%s" % (t, func, str(os.getpid())) runfile = "%s/run.%s.%s" % (t, func, str(os.getpid())) f = open(runfile, "w") f.write("#!/bin/sh -e\n") if bb.msg.debug_level['default'] > 0: f.write("set -x\n") data.emit_env(f, d) f.write("cd %s\n" % os.getcwd()) if func: f.write("%s\n" % func) f.close() os.chmod(runfile, 0775) if not func: bb.msg.error(bb.msg.domain.Build, "Function not specified") raise FuncFailed() # open logs si = file('/dev/null', 'r') try: if bb.msg.debug_level['default'] > 0: so = os.popen("tee \"%s\"" % logfile, "w") else: so = file(logfile, 'w') except OSError, e: bb.msg.error(bb.msg.domain.Build, "opening log file: %s" % e) pass se = so if not interact: # dup the existing fds so we dont lose them osi = [os.dup(sys.stdin.fileno()), sys.stdin.fileno()] oso = [os.dup(sys.stdout.fileno()), sys.stdout.fileno()] ose = [os.dup(sys.stderr.fileno()), sys.stderr.fileno()] # replace those fds with our own os.dup2(si.fileno(), osi[1]) os.dup2(so.fileno(), oso[1]) os.dup2(se.fileno(), ose[1]) # execute function prevdir = os.getcwd() if data.getVarFlag(func, "fakeroot", d): maybe_fakeroot = "PATH=\"%s\" fakeroot " % bb.data.getVar("PATH", d, 1) else: maybe_fakeroot = '' lang_environment = "LC_ALL=C " ret = os.system('%s%ssh -e %s' % (lang_environment, maybe_fakeroot, runfile)) try: os.chdir(prevdir) except: pass if not interact: # restore the backups os.dup2(osi[0], osi[1]) os.dup2(oso[0], oso[1]) os.dup2(ose[02016-01-17toaster.bbclass: Separate artifact dump from image file dumpElliot Smith 2015-12-22toaster.bbclass: fix TypeError when parsing build statsElliot Smith 2015-12-18buildstats-summary/toaster: Cope with removal of get_bn()Richard Purdie 2015-12-18toaster: Update for buildstats changesRichard Purdie 2015-07-27toaster.bbclass: Fix ValueErrorEd Bartosh 2015-03-29toaster.bbclass: do not add symbolic links to artifactsAlexandru DAMIAN 2014-12-19toaster.bbclass: trigger event for other image filesAlexandru DAMIAN 2014-11-28toaster.bbclass: use the openembedded-core nameAlexandru DAMIAN 2014-11-06toaster.bbclass: read elapsed time from the stats fileAlexandru DAMIAN 2014-06-03toaster.bbclass: exclude variable dependency on toaster postfuncAlexandru DAMIAN 2014-04-19toaster.bbclass: do not fail on non-existent filesAlexandru DAMIAN 2014-04-11toaster.bbclass: read list of files in imageAlexandru DAMIAN 2014-04-08toaster.bbclass: image file is missing a "/"Cristiana Voicu 2014-03-31toaster.bbclass: the license.manifest is located in DEPLOY_DIRCristiana Voicu 2014-03-25toaster.bbclass: update buildstats event dataAlexandru DAMIAN 2014-03-21toaster.bbclass: read the data needed for license manifest pathCristiana Voicu 2014-01-29toaster.bbclass: save original package nameAlexandru DAMIAN 2013-12-21toaster.bbclass: fix crash on buildstats collectionAlexandru DAMIAN 2013-12-10toaster.bbclass: read package and image informationAlexandru DAMIAN 2013-12-10toaster.bbclass: read build statsAlexandru DAMIAN 2013-12-10toaster.bbclass: read layer informationAlexandru DAMIAN 2013-12-03classes/package: fix FILES_INFO serialisation in pkgdataPaul Eggleton 2013-11-04toaster: add class to dump toaster-tracked dataAlexandru DAMIAN