diff options
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/configurator.py')
-rw-r--r-- | bitbake/lib/bb/ui/crumbs/configurator.py | 346 |
1 files changed, 0 insertions, 346 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/configurator.py b/bitbake/lib/bb/ui/crumbs/configurator.py deleted file mode 100644 index 837ee1ca91..0000000000 --- a/bitbake/lib/bb/ui/crumbs/configurator.py +++ /dev/null | |||
@@ -1,346 +0,0 @@ | |||
1 | # | ||
2 | # BitBake Graphical GTK User Interface | ||
3 | # | ||
4 | # Copyright (C) 2011 Intel Corporation | ||
5 | # | ||
6 | # Authored by Joshua Lock <josh@linux.intel.com> | ||
7 | # | ||
8 | # This program is free software; you can redistribute it and/or modify | ||
9 | # it under the terms of the GNU General Public License version 2 as | ||
10 | # published by the Free Software Foundation. | ||
11 | # | ||
12 | # This program is distributed in the hope that it will be useful, | ||
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | # GNU General Public License for more details. | ||
16 | # | ||
17 | # You should have received a copy of the GNU General Public License along | ||
18 | # with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | |||
21 | import gobject | ||
22 | import copy | ||
23 | import re, os | ||
24 | from bb import data | ||
25 | |||
26 | class Configurator(gobject.GObject): | ||
27 | |||
28 | """ | ||
29 | A GObject to handle writing modified configuration values back | ||
30 | to conf files. | ||
31 | """ | ||
32 | __gsignals__ = { | ||
33 | "layers-loaded" : (gobject.SIGNAL_RUN_LAST, | ||
34 | gobject.TYPE_NONE, | ||
35 | ()), | ||
36 | "layers-changed" : (gobject.SIGNAL_RUN_LAST, | ||
37 | gobject.TYPE_NONE, | ||
38 | ()) | ||
39 | } | ||
40 | |||
41 | def __init__(self): | ||
42 | gobject.GObject.__init__(self) | ||
43 | self.bblayers = None | ||
44 | self.enabled_layers = {} | ||
45 | self.loaded_layers = {} | ||
46 | self.config = {} | ||
47 | self.orig_config = {} | ||
48 | self.preconf = None | ||
49 | self.postconf = None | ||
50 | |||
51 | # NOTE: cribbed from the cooker... | ||
52 | def _parse(self, f, data, include=False): | ||
53 | try: | ||
54 | return bb.parse.handle(f, data, include) | ||
55 | except (IOError, bb.parse.ParseError) as exc: | ||
56 | parselog.critical("Unable to parse %s: %s" % (f, exc)) | ||
57 | sys.exit(1) | ||
58 | |||
59 | def _loadConf(self, path): | ||
60 | def getString(var): | ||
61 | return data.getVar(var, True) or "" | ||
62 | |||
63 | if self.orig_config: | ||
64 | del self.orig_config | ||
65 | self.orig_config = {} | ||
66 | |||
67 | data = bb.data.init() | ||
68 | data = self._parse(path, data) | ||
69 | |||
70 | # We only need to care about certain variables | ||
71 | mach = getString('MACHINE') | ||
72 | if mach and mach != self.config.get('MACHINE', ''): | ||
73 | self.config['MACHINE'] = mach | ||
74 | sdkmach = getString('SDKMACHINE') | ||
75 | if sdkmach and sdkmach != self.config.get('SDKMACHINE', ''): | ||
76 | self.config['SDKMACHINE'] = sdkmach | ||
77 | distro = getString('DISTRO') | ||
78 | if not distro: | ||
79 | distro = "defaultsetup" | ||
80 | if distro and distro != self.config.get('DISTRO', ''): | ||
81 | self.config['DISTRO'] = distro | ||
82 | bbnum = getString('BB_NUMBER_THREADS') | ||
83 | if bbnum and bbnum != self.config.get('BB_NUMBER_THREADS', ''): | ||
84 | self.config['BB_NUMBER_THREADS'] = bbnum | ||
85 | pmake = getString('PARALLEL_MAKE') | ||
86 | if pmake and pmake != self.config.get('PARALLEL_MAKE', ''): | ||
87 | self.config['PARALLEL_MAKE'] = pmake | ||
88 | pclass = getString('PACKAGE_CLASSES') | ||
89 | if pclass and pclass != self.config.get('PACKAGE_CLASSES', ''): | ||
90 | self.config['PACKAGE_CLASSES'] = pclass | ||
91 | fstypes = getString('IMAGE_FSTYPES') | ||
92 | if fstypes and fstypes != self.config.get('IMAGE_FSTYPES', ''): | ||
93 | self.config['IMAGE_FSTYPES'] = fstypes | ||
94 | |||
95 | # Values which aren't always set in the conf must be explicitly | ||
96 | # loaded as empty values for save to work | ||
97 | incompat = getString('INCOMPATIBLE_LICENSE') | ||
98 | if incompat and incompat != self.config.get('INCOMPATIBLE_LICENSE', ''): | ||
99 | self.config['INCOMPATIBLE_LICENSE'] = incompat | ||
100 | else: | ||
101 | self.config['INCOMPATIBLE_LICENSE'] = "" | ||
102 | |||
103 | # Non-standard, namespaces, variables for GUI preferences | ||
104 | toolchain = getString('HOB_BUILD_TOOLCHAIN') | ||
105 | if toolchain and toolchain != self.config.get('HOB_BUILD_TOOLCHAIN', ''): | ||
106 | self.config['HOB_BUILD_TOOLCHAIN'] = toolchain | ||
107 | header = getString('HOB_BUILD_TOOLCHAIN_HEADERS') | ||
108 | if header and header != self.config.get('HOB_BUILD_TOOLCHAIN_HEADERS', ''): | ||
109 | self.config['HOB_BUILD_TOOLCHAIN_HEADERS'] = header | ||
110 | |||
111 | self.orig_config = copy.deepcopy(self.config) | ||
112 | |||
113 | def setConfVar(self, var, val): | ||
114 | self.config[var] = val | ||
115 | |||
116 | def getConfVar(self, var): | ||
117 | if var in self.config: | ||
118 | return self.config[var] | ||
119 | else: | ||
120 | return "" | ||
121 | |||
122 | def _loadLayerConf(self, path): | ||
123 | self.bblayers = path | ||
124 | self.enabled_layers = {} | ||
125 | self.loaded_layers = {} | ||
126 | data = bb.data.init() | ||
127 | data = self._parse(self.bblayers, data) | ||
128 | layers = (data.getVar('BBLAYERS', True) or "").split() | ||
129 | for layer in layers: | ||
130 | # TODO: we may be better off calling the layer by its | ||
131 | # BBFILE_COLLECTIONS value? | ||
132 | name = self._getLayerName(layer) | ||
133 | self.loaded_layers[name] = layer | ||
134 | |||
135 | self.enabled_layers = copy.deepcopy(self.loaded_layers) | ||
136 | self.emit("layers-loaded") | ||
137 | |||
138 | def _addConfigFile(self, path): | ||
139 | conffiles = ["local.conf", "hob-pre.conf", "hob-post.conf"] | ||
140 | pref, sep, filename = path.rpartition("/") | ||
141 | |||
142 | if filename == "hob-pre.conf": | ||
143 | self.preconf = path | ||
144 | |||
145 | if filename == "hob-post.conf": | ||
146 | self.postconf = path | ||
147 | |||
148 | if filename in conffiles: | ||
149 | self._loadConf(path) | ||
150 | elif filename == "bblayers.conf": | ||
151 | self._loadLayerConf(path) | ||
152 | |||
153 | def _splitLayer(self, path): | ||
154 | # we only care about the path up to /conf/layer.conf | ||
155 | layerpath, conf, end = path.rpartition("/conf/") | ||
156 | return layerpath | ||
157 | |||
158 | def _getLayerName(self, path): | ||
159 | # Should this be the collection name? | ||
160 | layerpath, sep, name = path.rpartition("/") | ||
161 | return name | ||
162 | |||
163 | def disableLayer(self, layer): | ||
164 | if layer in self.enabled_layers: | ||
165 | del self.enabled_layers[layer] | ||
166 | |||
167 | def addLayerConf(self, confpath): | ||
168 | layerpath = self._splitLayer(confpath) | ||
169 | name = self._getLayerName(layerpath) | ||
170 | |||
171 | if not layerpath or not name: | ||
172 | return None, None | ||
173 | elif name not in self.enabled_layers: | ||
174 | self.addLayer(name, layerpath) | ||
175 | return name, layerpath | ||
176 | else: | ||
177 | return name, None | ||
178 | |||
179 | def addLayer(self, name, path): | ||
180 | self.enabled_layers[name] = path | ||
181 | |||
182 | def _isLayerConfDirty(self): | ||
183 | # if a different number of layers enabled to what was | ||
184 | # loaded, definitely different | ||
185 | if len(self.enabled_layers) != len(self.loaded_layers): | ||
186 | return True | ||
187 | |||
188 | for layer in self.loaded_layers: | ||
189 | # if layer loaded but no longer present, definitely dirty | ||
190 | if layer not in self.enabled_layers: | ||
191 | return True | ||
192 | |||
193 | for layer in self.enabled_layers: | ||
194 | # if this layer wasn't present at load, definitely dirty | ||
195 | if layer not in self.loaded_layers: | ||
196 | return True | ||
197 | # if this layers path has changed, definitely dirty | ||
198 | if self.enabled_layers[layer] != self.loaded_layers[layer]: | ||
199 | return True | ||
200 | |||
201 | return False | ||
202 | |||
203 | def _constructLayerEntry(self): | ||
204 | """ | ||
205 | Returns a string representing the new layer selection | ||
206 | """ | ||
207 | layers = self.enabled_layers.copy() | ||
208 | # Construct BBLAYERS entry | ||
209 | layer_entry = "BBLAYERS = \" \\\n" | ||
210 | if 'meta' in layers: | ||
211 | layer_entry = layer_entry + " %s \\\n" % layers['meta'] | ||
212 | del layers['meta'] | ||
213 | for layer in layers: | ||
214 | layer_entry = layer_entry + " %s \\\n" % layers[layer] | ||
215 | layer_entry = layer_entry + " \"" | ||
216 | |||
217 | return "".join(layer_entry) | ||
218 | |||
219 | def writeConfFile(self, conffile, contents): | ||
220 | """ | ||
221 | Make a backup copy of conffile and write a new file in its stead with | ||
222 | the lines in the contents list. | ||
223 | """ | ||
224 | # Create a backup of the conf file | ||
225 | bkup = "%s~" % conffile | ||
226 | os.rename(conffile, bkup) | ||
227 | |||
228 | # Write the contents list object to the conf file | ||
229 | with open(conffile, "w") as new: | ||
230 | new.write("".join(contents)) | ||
231 | |||
232 | def updateConf(self, orig_lines, changed_values): | ||
233 | new_config_lines = [] | ||
234 | for var in changed_values: | ||
235 | # Convenience function for re.subn(). If the pattern matches | ||
236 | # return a string which contains an assignment using the same | ||
237 | # assignment operator as the old assignment. | ||
238 | def replace_val(matchobj): | ||
239 | var = matchobj.group(1) # config variable | ||
240 | op = matchobj.group(2) # assignment operator | ||
241 | val = changed_values[var] # new config value | ||
242 | return "%s %s \"%s\"" % (var, op, val) | ||
243 | |||
244 | pattern = '^\s*(%s)\s*([+=?.]+)(.*)' % re.escape(var) | ||
245 | p = re.compile(pattern) | ||
246 | cnt = 0 | ||
247 | replaced = False | ||
248 | |||
249 | # Iterate over the local.conf lines and if they are a match | ||
250 | # for the pattern comment out the line and append a new line | ||
251 | # with the new VAR op "value" entry | ||
252 | for line in orig_lines: | ||
253 | new_line, replacements = p.subn(replace_val, line) | ||
254 | if replacements: | ||
255 | orig_lines[cnt] = "#%s" % line | ||
256 | new_config_lines.append(new_line) | ||
257 | replaced = True | ||
258 | cnt = cnt + 1 | ||
259 | |||
260 | if not replaced: | ||
261 | new_config_lines.append("%s = \"%s\"\n" % (var, changed_values[var])) | ||
262 | |||
263 | # Add the modified variables | ||
264 | orig_lines.extend(new_config_lines) | ||
265 | return orig_lines | ||
266 | |||
267 | def writeConf(self): | ||
268 | pre_vars = ["MACHINE", "SDKMACHINE", "DISTRO", | ||
269 | "INCOMPATIBLE_LICENSE"] | ||
270 | post_vars = ["BB_NUMBER_THREADS", "PARALLEL_MAKE", "PACKAGE_CLASSES", | ||
271 | "IMAGE_FSTYPES", "HOB_BUILD_TOOLCHAIN", | ||
272 | "HOB_BUILD_TOOLCHAIN_HEADERS"] | ||
273 | pre_values = {} | ||
274 | post_values = {} | ||
275 | changed_values = {} | ||
276 | pre_lines = None | ||
277 | post_lines = None | ||
278 | |||
279 | for var in self.config: | ||
280 | val = self.config[var] | ||
281 | if self.orig_config.get(var, None) != val: | ||
282 | changed_values[var] = val | ||
283 | |||
284 | if not len(changed_values): | ||
285 | return | ||
286 | |||
287 | for var in changed_values: | ||
288 | if var in pre_vars: | ||
289 | pre_values[var] = changed_values[var] | ||
290 | elif var in post_vars: | ||
291 | post_values[var] = changed_values[var] | ||
292 | |||
293 | with open(self.preconf, 'r') as pre: | ||
294 | pre_lines = pre.readlines() | ||
295 | pre_lines = self.updateConf(pre_lines, pre_values) | ||
296 | if len(pre_lines): | ||
297 | self.writeConfFile(self.preconf, pre_lines) | ||
298 | |||
299 | with open(self.postconf, 'r') as post: | ||
300 | post_lines = post.readlines() | ||
301 | post_lines = self.updateConf(post_lines, post_values) | ||
302 | if len(post_lines): | ||
303 | self.writeConfFile(self.postconf, post_lines) | ||
304 | |||
305 | del self.orig_config | ||
306 | self.orig_config = copy.deepcopy(self.config) | ||
307 | |||
308 | def insertTempBBPath(self, bbpath, bbfiles): | ||
309 | # read the original conf into a list | ||
310 | with open(self.postconf, 'r') as config: | ||
311 | config_lines = config.readlines() | ||
312 | |||
313 | if bbpath: | ||
314 | config_lines.append("BBPATH := \"${BBPATH}:%s\"\n" % bbpath) | ||
315 | if bbfiles: | ||
316 | config_lines.append("BBFILES := \"${BBFILES} %s\"\n" % bbfiles) | ||
317 | |||
318 | self.writeConfFile(self.postconf, config_lines) | ||
319 | |||
320 | def writeLayerConf(self): | ||
321 | # If we've not added/removed new layers don't write | ||
322 | if not self._isLayerConfDirty(): | ||
323 | return | ||
324 | |||
325 | # This pattern should find the existing BBLAYERS | ||
326 | pattern = 'BBLAYERS\s=\s\".*\"' | ||
327 | |||
328 | replacement = self._constructLayerEntry() | ||
329 | |||
330 | with open(self.bblayers, "r") as f: | ||
331 | contents = f.read() | ||
332 | p = re.compile(pattern, re.DOTALL) | ||
333 | new = p.sub(replacement, contents) | ||
334 | |||
335 | self.writeConfFile(self.bblayers, new) | ||
336 | |||
337 | # set loaded_layers for dirtiness tracking | ||
338 | self.loaded_layers = copy.deepcopy(self.enabled_layers) | ||
339 | |||
340 | self.emit("layers-changed") | ||
341 | |||
342 | def configFound(self, handler, path): | ||
343 | self._addConfigFile(path) | ||
344 | |||
345 | def loadConfig(self, path): | ||
346 | self._addConfigFile(path) | ||