summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/command.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/command.py')
-rw-r--r--bitbake/lib/bb/command.py271
1 files changed, 271 insertions, 0 deletions
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py
new file mode 100644
index 0000000000..2bb5365c0c
--- /dev/null
+++ b/bitbake/lib/bb/command.py
@@ -0,0 +1,271 @@
1"""
2BitBake 'Command' module
3
4Provide an interface to interact with the bitbake server through 'commands'
5"""
6
7# Copyright (C) 2006-2007 Richard Purdie
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22"""
23The bitbake server takes 'commands' from its UI/commandline.
24Commands are either synchronous or asynchronous.
25Async commands return data to the client in the form of events.
26Sync commands must only return data through the function return value
27and must not trigger events, directly or indirectly.
28Commands are queued in a CommandQueue
29"""
30
31import bb
32
33async_cmds = {}
34sync_cmds = {}
35
36class Command:
37 """
38 A queue of asynchronous commands for bitbake
39 """
40 def __init__(self, cooker):
41
42 self.cooker = cooker
43 self.cmds_sync = CommandsSync()
44 self.cmds_async = CommandsAsync()
45
46 # FIXME Add lock for this
47 self.currentAsyncCommand = None
48
49 for attr in CommandsSync.__dict__:
50 command = attr[:].lower()
51 method = getattr(CommandsSync, attr)
52 sync_cmds[command] = (method)
53
54 for attr in CommandsAsync.__dict__:
55 command = attr[:].lower()
56 method = getattr(CommandsAsync, attr)
57 async_cmds[command] = (method)
58
59 def runCommand(self, commandline):
60 try:
61 command = commandline.pop(0)
62 if command in CommandsSync.__dict__:
63 # Can run synchronous commands straight away
64 return getattr(CommandsSync, command)(self.cmds_sync, self, commandline)
65 if self.currentAsyncCommand is not None:
66 return "Busy (%s in progress)" % self.currentAsyncCommand[0]
67 if command not in CommandsAsync.__dict__:
68 return "No such command"
69 self.currentAsyncCommand = (command, commandline)
70 self.cooker.server.register_idle_function(self.cooker.runCommands, self.cooker)
71 return True
72 except:
73 import traceback
74 return traceback.format_exc()
75
76 def runAsyncCommand(self):
77 try:
78 if self.currentAsyncCommand is not None:
79 (command, options) = self.currentAsyncCommand
80 commandmethod = getattr(CommandsAsync, command)
81 needcache = getattr( commandmethod, "needcache" )
82 if needcache and self.cooker.cookerState != bb.cooker.cookerParsed:
83 self.cooker.updateCache()
84 return True
85 else:
86 commandmethod(self.cmds_async, self, options)
87 return False
88 else:
89 return False
90 except:
91 import traceback
92 self.finishAsyncCommand(traceback.format_exc())
93 return False
94
95 def finishAsyncCommand(self, error = None):
96 if error:
97 bb.event.fire(bb.command.CookerCommandFailed(error), self.cooker.configuration.event_data)
98 else:
99 bb.event.fire(bb.command.CookerCommandCompleted(), self.cooker.configuration.event_data)
100 self.currentAsyncCommand = None
101
102
103class CommandsSync:
104 """
105 A class of synchronous commands
106 These should run quickly so as not to hurt interactive performance.
107 These must not influence any running synchronous command.
108 """
109
110 def stateShutdown(self, command, params):
111 """
112 Trigger cooker 'shutdown' mode
113 """
114 command.cooker.cookerAction = bb.cooker.cookerShutdown
115
116 def stateStop(self, command, params):
117 """
118 Stop the cooker
119 """
120 command.cooker.cookerAction = bb.cooker.cookerStop
121
122 def getCmdLineAction(self, command, params):
123 """
124 Get any command parsed from the commandline
125 """
126 return command.cooker.commandlineAction
127
128 def getVariable(self, command, params):
129 """
130 Read the value of a variable from configuration.data
131 """
132 varname = params[0]
133 expand = True
134 if len(params) > 1:
135 expand = params[1]
136
137 return bb.data.getVar(varname, command.cooker.configuration.data, expand)
138
139 def setVariable(self, command, params):
140 """
141 Set the value of variable in configuration.data
142 """
143 varname = params[0]
144 value = params[1]
145 bb.data.setVar(varname, value, command.cooker.configuration.data)
146
147
148class CommandsAsync:
149 """
150 A class of asynchronous commands
151 These functions communicate via generated events.
152 Any function that requires metadata parsing should be here.
153 """
154
155 def buildFile(self, command, params):
156 """
157 Build a single specified .bb file
158 """
159 bfile = params[0]
160 task = params[1]
161
162 command.cooker.buildFile(bfile, task)
163 buildFile.needcache = False
164
165 def buildTargets(self, command, params):
166 """
167 Build a set of targets
168 """
169 pkgs_to_build = params[0]
170 task = params[1]
171
172 command.cooker.buildTargets(pkgs_to_build, task)
173 buildTargets.needcache = True
174
175 def generateDepTreeEvent(self, command, params):
176 """
177 Generate an event containing the dependency information
178 """
179 pkgs_to_build = params[0]
180 task = params[1]
181
182 command.cooker.generateDepTreeEvent(pkgs_to_build, task)
183 command.finishAsyncCommand()
184 generateDepTreeEvent.needcache = True
185
186 def generateDotGraph(self, command, params):
187 """
188 Dump dependency information to disk as .dot files
189 """
190 pkgs_to_build = params[0]
191 task = params[1]
192
193 command.cooker.generateDotGraphFiles(pkgs_to_build, task)
194 command.finishAsyncCommand()
195 generateDotGraph.needcache = True
196
197 def showVersions(self, command, params):
198 """
199 Show the currently selected versions
200 """
201 command.cooker.showVersions()
202 command.finishAsyncCommand()
203 showVersions.needcache = True
204
205 def showEnvironmentTarget(self, command, params):
206 """
207 Print the environment of a target recipe
208 (needs the cache to work out which recipe to use)
209 """
210 pkg = params[0]
211
212 command.cooker.showEnvironment(None, pkg)
213 command.finishAsyncCommand()
214 showEnvironmentTarget.needcache = True
215
216 def showEnvironment(self, command, params):
217 """
218 Print the standard environment
219 or if specified the environment for a specified recipe
220 """
221 bfile = params[0]
222
223 command.cooker.showEnvironment(bfile)
224 command.finishAsyncCommand()
225 showEnvironment.needcache = False
226
227 def parseFiles(self, command, params):
228 """
229 Parse the .bb files
230 """
231 command.cooker.updateCache()
232 command.finishAsyncCommand()
233 parseFiles.needcache = True
234
235 def compareRevisions(self, command, params):
236 """
237 Parse the .bb files
238 """
239 command.cooker.compareRevisions()
240 command.finishAsyncCommand()
241 compareRevisions.needcache = True
242
243#
244# Events
245#
246class CookerCommandCompleted(bb.event.Event):
247 """
248 Cooker command completed
249 """
250 def __init__(self):
251 bb.event.Event.__init__(self)
252
253
254class CookerCommandFailed(bb.event.Event):
255 """
256 Cooker command completed
257 """
258 def __init__(self, error):
259 bb.event.Event.__init__(self)
260 self.error = error
261
262class CookerCommandSetExitCode(bb.event.Event):
263 """
264 Set the exit code for a cooker command
265 """
266 def __init__(self, exitcode):
267 bb.event.Event.__init__(self)
268 self.exitcode = int(exitcode)
269
270
271