summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/cookerdata.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/cookerdata.py')
-rw-r--r--bitbake/lib/bb/cookerdata.py305
1 files changed, 305 insertions, 0 deletions
diff --git a/bitbake/lib/bb/cookerdata.py b/bitbake/lib/bb/cookerdata.py
new file mode 100644
index 0000000000..b9b9e16675
--- /dev/null
+++ b/bitbake/lib/bb/cookerdata.py
@@ -0,0 +1,305 @@
1#!/usr/bin/env python
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# Copyright (C) 2003, 2004 Chris Larson
6# Copyright (C) 2003, 2004 Phil Blundell
7# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
8# Copyright (C) 2005 Holger Hans Peter Freyther
9# Copyright (C) 2005 ROAD GmbH
10# Copyright (C) 2006 Richard Purdie
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License version 2 as
14# published by the Free Software Foundation.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License along
22# with this program; if not, write to the Free Software Foundation, Inc.,
23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25import os, sys
26from functools import wraps
27import logging
28import bb
29from bb import data
30import bb.parse
31
32logger = logging.getLogger("BitBake")
33parselog = logging.getLogger("BitBake.Parsing")
34
35class ConfigParameters(object):
36 def __init__(self):
37 self.options, targets = self.parseCommandLine()
38 self.environment = self.parseEnvironment()
39
40 self.options.pkgs_to_build = targets or []
41
42 self.options.tracking = False
43 if hasattr(self.options, "show_environment") and self.options.show_environment:
44 self.options.tracking = True
45
46 for key, val in self.options.__dict__.items():
47 setattr(self, key, val)
48
49 def parseCommandLine(self):
50 raise Exception("Caller must implement commandline option parsing")
51
52 def parseEnvironment(self):
53 return os.environ.copy()
54
55 def updateFromServer(self, server):
56 if not self.options.cmd:
57 defaulttask, error = server.runCommand(["getVariable", "BB_DEFAULT_TASK"])
58 if error:
59 raise Exception("Unable to get the value of BB_DEFAULT_TASK from the server: %s" % error)
60 self.options.cmd = defaulttask or "build"
61 _, error = server.runCommand(["setConfig", "cmd", self.options.cmd])
62 if error:
63 raise Exception("Unable to set configuration option 'cmd' on the server: %s" % error)
64
65 if not self.options.pkgs_to_build:
66 bbpkgs, error = server.runCommand(["getVariable", "BBPKGS"])
67 if error:
68 raise Exception("Unable to get the value of BBPKGS from the server: %s" % error)
69 if bbpkgs:
70 self.options.pkgs_to_build.extend(bbpkgs.split())
71
72 def parseActions(self):
73 # Parse any commandline into actions
74 action = {'action':None, 'msg':None}
75 if self.options.show_environment:
76 if 'world' in self.options.pkgs_to_build:
77 action['msg'] = "'world' is not a valid target for --environment."
78 elif 'universe' in self.options.pkgs_to_build:
79 action['msg'] = "'universe' is not a valid target for --environment."
80 elif len(self.options.pkgs_to_build) > 1:
81 action['msg'] = "Only one target can be used with the --environment option."
82 elif self.options.buildfile and len(self.options.pkgs_to_build) > 0:
83 action['msg'] = "No target should be used with the --environment and --buildfile options."
84 elif len(self.options.pkgs_to_build) > 0:
85 action['action'] = ["showEnvironmentTarget", self.options.pkgs_to_build]
86 else:
87 action['action'] = ["showEnvironment", self.options.buildfile]
88 elif self.options.buildfile is not None:
89 action['action'] = ["buildFile", self.options.buildfile, self.options.cmd]
90 elif self.options.revisions_changed:
91 action['action'] = ["compareRevisions"]
92 elif self.options.show_versions:
93 action['action'] = ["showVersions"]
94 elif self.options.parse_only:
95 action['action'] = ["parseFiles"]
96 elif self.options.dot_graph:
97 if self.options.pkgs_to_build:
98 action['action'] = ["generateDotGraph", self.options.pkgs_to_build, self.options.cmd]
99 else:
100 action['msg'] = "Please specify a package name for dependency graph generation."
101 else:
102 if self.options.pkgs_to_build:
103 action['action'] = ["buildTargets", self.options.pkgs_to_build, self.options.cmd]
104 else:
105 #action['msg'] = "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information."
106 action = None
107 self.options.initialaction = action
108 return action
109
110class CookerConfiguration(object):
111 """
112 Manages build options and configurations for one run
113 """
114
115 def __init__(self):
116 self.debug_domains = []
117 self.extra_assume_provided = []
118 self.prefile = []
119 self.postfile = []
120 self.debug = 0
121 self.cmd = None
122 self.abort = True
123 self.force = False
124 self.profile = False
125 self.nosetscene = False
126 self.invalidate_stamp = False
127 self.dump_signatures = []
128 self.dry_run = False
129 self.tracking = False
130 self.interface = []
131
132 self.env = {}
133
134 def setConfigParameters(self, parameters):
135 for key in self.__dict__.keys():
136 if key in parameters.options.__dict__:
137 setattr(self, key, parameters.options.__dict__[key])
138 self.env = parameters.environment.copy()
139 self.tracking = parameters.tracking
140
141 def setServerRegIdleCallback(self, srcb):
142 self.server_register_idlecallback = srcb
143
144 def __getstate__(self):
145 state = {}
146 for key in self.__dict__.keys():
147 if key == "server_register_idlecallback":
148 state[key] = None
149 else:
150 state[key] = getattr(self, key)
151 return state
152
153 def __setstate__(self,state):
154 for k in state:
155 setattr(self, k, state[k])
156
157
158def catch_parse_error(func):
159 """Exception handling bits for our parsing"""
160 @wraps(func)
161 def wrapped(fn, *args):
162 try:
163 return func(fn, *args)
164 except (IOError, bb.parse.ParseError, bb.data_smart.ExpansionError) as exc:
165 import traceback
166 parselog.critical( traceback.format_exc())
167 parselog.critical("Unable to parse %s: %s" % (fn, exc))
168 sys.exit(1)
169 return wrapped
170
171@catch_parse_error
172def parse_config_file(fn, data, include=True):
173 return bb.parse.handle(fn, data, include)
174
175@catch_parse_error
176def _inherit(bbclass, data):
177 bb.parse.BBHandler.inherit(bbclass, "configuration INHERITs", 0, data)
178 return data
179
180def findConfigFile(configfile, data):
181 search = []
182 bbpath = data.getVar("BBPATH", True)
183 if bbpath:
184 for i in bbpath.split(":"):
185 search.append(os.path.join(i, "conf", configfile))
186 path = os.getcwd()
187 while path != "/":
188 search.append(os.path.join(path, "conf", configfile))
189 path, _ = os.path.split(path)
190
191 for i in search:
192 if os.path.exists(i):
193 return i
194
195 return None
196
197class CookerDataBuilder(object):
198
199 def __init__(self, cookercfg, worker = False):
200
201 self.prefiles = cookercfg.prefile
202 self.postfiles = cookercfg.postfile
203 self.tracking = cookercfg.tracking
204
205 bb.utils.set_context(bb.utils.clean_context())
206 bb.event.set_class_handlers(bb.event.clean_class_handlers())
207 self.data = bb.data.init()
208 if self.tracking:
209 self.data.enableTracking()
210
211 # Keep a datastore of the initial environment variables and their
212 # values from when BitBake was launched to enable child processes
213 # to use environment variables which have been cleaned from the
214 # BitBake processes env
215 self.savedenv = bb.data.init()
216 for k in cookercfg.env:
217 self.savedenv.setVar(k, cookercfg.env[k])
218
219 filtered_keys = bb.utils.approved_variables()
220 bb.data.inheritFromOS(self.data, self.savedenv, filtered_keys)
221 self.data.setVar("BB_ORIGENV", self.savedenv)
222
223 if worker:
224 self.data.setVar("BB_WORKERCONTEXT", "1")
225
226 def parseBaseConfiguration(self):
227 try:
228 self.parseConfigurationFiles(self.prefiles, self.postfiles)
229 except SyntaxError:
230 sys.exit(1)
231 except Exception:
232 logger.exception("Error parsing configuration files")
233 sys.exit(1)
234
235 def _findLayerConf(self, data):
236 return findConfigFile("bblayers.conf", data)
237
238 def parseConfigurationFiles(self, prefiles, postfiles):
239 data = self.data
240 bb.parse.init_parser(data)
241
242 # Parse files for loading *before* bitbake.conf and any includes
243 for f in prefiles:
244 data = parse_config_file(f, data)
245
246 layerconf = self._findLayerConf(data)
247 if layerconf:
248 parselog.debug(2, "Found bblayers.conf (%s)", layerconf)
249 # By definition bblayers.conf is in conf/ of TOPDIR.
250 # We may have been called with cwd somewhere else so reset TOPDIR
251 data.setVar("TOPDIR", os.path.dirname(os.path.dirname(layerconf)))
252 data = parse_config_file(layerconf, data)
253
254 layers = (data.getVar('BBLAYERS', True) or "").split()
255
256 data = bb.data.createCopy(data)
257 for layer in layers:
258 parselog.debug(2, "Adding layer %s", layer)
259 data.setVar('LAYERDIR', layer)
260 data = parse_config_file(os.path.join(layer, "conf", "layer.conf"), data)
261 data.expandVarref('LAYERDIR')
262
263 data.delVar('LAYERDIR')
264
265 if not data.getVar("BBPATH", True):
266 msg = "The BBPATH variable is not set"
267 if not layerconf:
268 msg += (" and bitbake did not find a conf/bblayers.conf file in"
269 " the expected location.\nMaybe you accidentally"
270 " invoked bitbake from the wrong directory?")
271 raise SystemExit(msg)
272
273 data = parse_config_file(os.path.join("conf", "bitbake.conf"), data)
274
275 # Parse files for loading *after* bitbake.conf and any includes
276 for p in postfiles:
277 data = parse_config_file(p, data)
278
279 # Handle any INHERITs and inherit the base class
280 bbclasses = ["base"] + (data.getVar('INHERIT', True) or "").split()
281 for bbclass in bbclasses:
282 data = _inherit(bbclass, data)
283
284 # Nomally we only register event handlers at the end of parsing .bb files
285 # We register any handlers we've found so far here...
286 for var in data.getVar('__BBHANDLERS') or []:
287 bb.event.register(var, data.getVar(var), (data.getVarFlag(var, "eventmask", True) or "").split())
288
289 if data.getVar("BB_WORKERCONTEXT", False) is None:
290 bb.fetch.fetcher_init(data)
291 bb.codeparser.parser_cache_init(data)
292 bb.event.fire(bb.event.ConfigParsed(), data)
293
294 if data.getVar("BB_INVALIDCONF") is True:
295 data.setVar("BB_INVALIDCONF", False)
296 self.parseConfigurationFiles(self.prefiles, self.postfiles)
297 return
298
299 bb.parse.init_parser(data)
300 data.setVar('BBINCLUDED',bb.parse.get_file_depends(data))
301 self.data = data
302 self.data_hash = data.get_hash()
303
304
305