summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/doc/manual/usermanual.xml14
-rw-r--r--bitbake/lib/bb/cache.py10
-rw-r--r--bitbake/lib/bb/parse/ast.py114
-rw-r--r--bitbake/lib/bb/parse/parse_py/BBHandler.py26
4 files changed, 134 insertions, 30 deletions
diff --git a/bitbake/doc/manual/usermanual.xml b/bitbake/doc/manual/usermanual.xml
index 29cdf97a0a..6424a7ebd9 100644
--- a/bitbake/doc/manual/usermanual.xml
+++ b/bitbake/doc/manual/usermanual.xml
@@ -228,6 +228,18 @@ This event handler gets called every time an event is triggered. A global variab
228method one can get the name of the triggered event.</para><para>The above event handler prints the name 228method one can get the name of the triggered event.</para><para>The above event handler prints the name
229of the event and the content of the <varname>FILE</varname> variable.</para> 229of the event and the content of the <varname>FILE</varname> variable.</para>
230 </section> 230 </section>
231 <section>
232 <title>Variants</title>
233 <para>Two Bitbake features exist to facilitate the creation of multiple buildable incarnations from a single recipe file.</para>
234 <para>The first is <varname>BBCLASSEXTEND</varname>. This variable is a space separated list of classes to utilize to "extend" the recipe for each variant. As an example, setting <screen>BBCLASSEXTEND = "native"</screen> results in a second incarnation of the current recipe being available. This second incarantion will have the "native" class inherited.</para>
235 <para>The second feature is <varname>BBVERSIONS</varname>. This variable allows a single recipe to be able to build multiple versions of a project from a single recipe file, and allows you to specify conditional metadata (using the <varname>OVERRIDES</varname> mechanism) for a single version, or an optionally named range of versions:</para>
236 <para><screen>BBVERSIONS = "1.0 2.0 git"
237SRC_URI_git = "git://someurl/somepath.git"</screen></para>
238 <para><screen>BBVERSIONS = "1.0.[0-6]:1.0.0+ \
239 1.0.[7-9]:1.0.7+"
240SRC_URI_append_1.0.7+ = "file://some_patch_which_the_new_versions_need.patch;patch=1"</screen></para>
241 <para>Note that the name of the range will default to the original version of the recipe, so given OE, a recipe file of foo_1.0.0+.bb will default the name of its versions to 1.0.0+. This is useful, as the range name is not only placed into overrides, it's also made available for the metadata to use in the form of the <varname>BPV</varname> variable, for use in file:// search paths (<varname>FILESPATH</varname>).</para>
242 </section>
231 </section> 243 </section>
232 <section> 244 <section>
233 <title>Dependency Handling</title> 245 <title>Dependency Handling</title>
@@ -270,7 +282,7 @@ of the event and the content of the <varname>FILE</varname> variable.</para>
270 <section> 282 <section>
271 <title>Configuration Files</title> 283 <title>Configuration Files</title>
272 <para>The first of the classifications of metadata in BitBake is configuration metadata. This metadata is global, and therefore affects <emphasis>all</emphasis> packages and tasks which are executed.</para> 284 <para>The first of the classifications of metadata in BitBake is configuration metadata. This metadata is global, and therefore affects <emphasis>all</emphasis> packages and tasks which are executed.</para>
273 <papa>Bitbake will first search the current working directory for an optional "conf/bblayers.conf" configuration file. This file is expected to contain a BBLAYERS variable which is a space delimited list of 'layer' directories. For each directory in this list a "conf/layer.conf" file will be searched for and parsed with the LAYERDIR variable being set to the directory where the layer was found. The idea is these files will setup BBPATH and other variables correctly for a given build directory automatically for the user.</para> 285 <para>Bitbake will first search the current working directory for an optional "conf/bblayers.conf" configuration file. This file is expected to contain a BBLAYERS variable which is a space delimited list of 'layer' directories. For each directory in this list a "conf/layer.conf" file will be searched for and parsed with the LAYERDIR variable being set to the directory where the layer was found. The idea is these files will setup BBPATH and other variables correctly for a given build directory automatically for the user.</para>
274 <para>Bitbake will then expect to find 'conf/bitbake.conf' somewhere in the user specified <envar>BBPATH</envar>. That configuration file generally has include directives to pull in any other metadata (generally files specific to architecture, machine, <emphasis>local</emphasis> and so on.</para> 286 <para>Bitbake will then expect to find 'conf/bitbake.conf' somewhere in the user specified <envar>BBPATH</envar>. That configuration file generally has include directives to pull in any other metadata (generally files specific to architecture, machine, <emphasis>local</emphasis> and so on.</para>
275 <para>Only variable definitions and include directives are allowed in .conf files.</para> 287 <para>Only variable definitions and include directives are allowed in .conf files.</para>
276 </section> 288 </section>
diff --git a/bitbake/lib/bb/cache.py b/bitbake/lib/bb/cache.py
index 43091daa26..9a962ecc74 100644
--- a/bitbake/lib/bb/cache.py
+++ b/bitbake/lib/bb/cache.py
@@ -143,8 +143,8 @@ class Cache:
143 if dep not in self.depends_cache[fn]["__depends"]: 143 if dep not in self.depends_cache[fn]["__depends"]:
144 self.depends_cache[fn]["__depends"].append(dep) 144 self.depends_cache[fn]["__depends"].append(dep)
145 145
146 # Make sure BBCLASSEXTEND always makes the cache too 146 # Make sure the variants always make it into the cache too
147 self.getVar('BBCLASSEXTEND', virtualfn, True) 147 self.getVar('__VARIANTS', virtualfn, True)
148 148
149 self.depends_cache[virtualfn]["CACHETIMESTAMP"] = bb.parse.cached_mtime(fn) 149 self.depends_cache[virtualfn]["CACHETIMESTAMP"] = bb.parse.cached_mtime(fn)
150 150
@@ -199,7 +199,7 @@ class Cache:
199 self.cacheValidUpdate(fn) 199 self.cacheValidUpdate(fn)
200 200
201 if self.cacheValid(fn): 201 if self.cacheValid(fn):
202 multi = self.getVar('BBCLASSEXTEND', fn, True) 202 multi = self.getVar('__VARIANTS', fn, True)
203 for cls in (multi or "").split() + [""]: 203 for cls in (multi or "").split() + [""]:
204 virtualfn = self.realfn2virtual(fn, cls) 204 virtualfn = self.realfn2virtual(fn, cls)
205 if self.depends_cache[virtualfn]["__SKIPPED"]: 205 if self.depends_cache[virtualfn]["__SKIPPED"]:
@@ -292,7 +292,7 @@ class Cache:
292 self.clean[fn] = "" 292 self.clean[fn] = ""
293 293
294 # Mark extended class data as clean too 294 # Mark extended class data as clean too
295 multi = self.getVar('BBCLASSEXTEND', fn, True) 295 multi = self.getVar('__VARIANTS', fn, True)
296 for cls in (multi or "").split(): 296 for cls in (multi or "").split():
297 virtualfn = self.realfn2virtual(fn, cls) 297 virtualfn = self.realfn2virtual(fn, cls)
298 self.clean[virtualfn] = "" 298 self.clean[virtualfn] = ""
@@ -443,7 +443,7 @@ class Cache:
443 443
444 # Touch this to make sure its in the cache 444 # Touch this to make sure its in the cache
445 self.getVar('__BB_DONT_CACHE', file_name, True) 445 self.getVar('__BB_DONT_CACHE', file_name, True)
446 self.getVar('BBCLASSEXTEND', file_name, True) 446 self.getVar('__VARIANTS', file_name, True)
447 447
448 def load_bbfile( self, bbfile , config): 448 def load_bbfile( self, bbfile , config):
449 """ 449 """
diff --git a/bitbake/lib/bb/parse/ast.py b/bitbake/lib/bb/parse/ast.py
index 70a69b8d14..59aa44bee0 100644
--- a/bitbake/lib/bb/parse/ast.py
+++ b/bitbake/lib/bb/parse/ast.py
@@ -22,9 +22,11 @@
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 23
24import bb, re, string 24import bb, re, string
25from itertools import chain
25 26
26__word__ = re.compile(r"\S+") 27__word__ = re.compile(r"\S+")
27__parsed_methods__ = bb.methodpool.get_parsed_dict() 28__parsed_methods__ = bb.methodpool.get_parsed_dict()
29_bbversions_re = re.compile(r"\[(?P<from>[0-9]+)-(?P<to>[0-9]+)\]")
28 30
29class StatementGroup(list): 31class StatementGroup(list):
30 def eval(self, data): 32 def eval(self, data):
@@ -335,3 +337,115 @@ def finalise(fn, d):
335 337
336 bb.event.fire(bb.event.RecipeParsed(fn), d) 338 bb.event.fire(bb.event.RecipeParsed(fn), d)
337 339
340def _create_variants(datastores, names, function):
341 def create_variant(name, orig_d, arg = None):
342 new_d = bb.data.createCopy(orig_d)
343 function(arg or name, new_d)
344 datastores[name] = new_d
345
346 for variant, variant_d in datastores.items():
347 for name in names:
348 if not variant:
349 # Based on main recipe
350 create_variant(name, variant_d)
351 else:
352 create_variant("%s-%s" % (variant, name), variant_d, name)
353
354def _expand_versions(versions):
355 def expand_one(version, start, end):
356 for i in xrange(start, end + 1):
357 ver = _bbversions_re.sub(str(i), version, 1)
358 yield ver
359
360 versions = iter(versions)
361 while True:
362 try:
363 version = versions.next()
364 except StopIteration:
365 break
366
367 range_ver = _bbversions_re.search(version)
368 if not range_ver:
369 yield version
370 else:
371 newversions = expand_one(version, int(range_ver.group("from")),
372 int(range_ver.group("to")))
373 versions = chain(newversions, versions)
374
375def multi_finalize(fn, d):
376 safe_d = d
377
378 d = bb.data.createCopy(safe_d)
379 try:
380 finalise(fn, d)
381 except bb.parse.SkipPackage:
382 bb.data.setVar("__SKIPPED", True, d)
383 datastores = {"": safe_d}
384
385 versions = (d.getVar("BBVERSIONS", True) or "").split()
386 if versions:
387 pv = orig_pv = d.getVar("PV", True)
388 baseversions = {}
389
390 def verfunc(ver, d, pv_d = None):
391 if pv_d is None:
392 pv_d = d
393
394 overrides = d.getVar("OVERRIDES", True).split(":")
395 pv_d.setVar("PV", ver)
396 overrides.append(ver)
397 bpv = baseversions.get(ver) or orig_pv
398 pv_d.setVar("BPV", bpv)
399 overrides.append(bpv)
400 d.setVar("OVERRIDES", ":".join(overrides))
401
402 versions = list(_expand_versions(versions))
403 for pos, version in enumerate(list(versions)):
404 try:
405 pv, bpv = version.split(":", 2)
406 except ValueError:
407 pass
408 else:
409 versions[pos] = pv
410 baseversions[pv] = bpv
411
412 if pv in versions and not baseversions.get(pv):
413 versions.remove(pv)
414 else:
415 pv = versions.pop()
416
417 # This is necessary because our existing main datastore
418 # has already been finalized with the old PV, we need one
419 # that's been finalized with the new PV.
420 d = bb.data.createCopy(safe_d)
421 verfunc(pv, d, safe_d)
422 try:
423 finalise(fn, d)
424 except bb.parse.SkipPackage:
425 bb.data.setVar("__SKIPPED", True, d)
426
427 _create_variants(datastores, versions, verfunc)
428
429 extended = d.getVar("BBCLASSEXTEND", True) or ""
430 if extended:
431 pn = d.getVar("PN", True)
432 def extendfunc(name, d):
433 d.setVar("PN", "%s-%s" % (pn, name))
434 bb.parse.BBHandler.inherit([name], d)
435
436 safe_d.setVar("BBCLASSEXTEND", extended)
437 _create_variants(datastores, extended.split(), extendfunc)
438
439 for variant, variant_d in datastores.items():
440 if variant:
441 try:
442 finalise(fn, variant_d)
443 except bb.parse.SkipPackage:
444 bb.data.setVar("__SKIPPED", True, variant_d)
445
446 if len(datastores) > 1:
447 variants = filter(None, datastores.keys())
448 safe_d.setVar("__VARIANTS", " ".join(variants))
449
450 datastores[""] = d
451 return datastores
diff --git a/bitbake/lib/bb/parse/parse_py/BBHandler.py b/bitbake/lib/bb/parse/parse_py/BBHandler.py
index 4641c13d9c..262c883c95 100644
--- a/bitbake/lib/bb/parse/parse_py/BBHandler.py
+++ b/bitbake/lib/bb/parse/parse_py/BBHandler.py
@@ -152,30 +152,8 @@ def handle(fn, d, include):
152 classes.remove(__classname__) 152 classes.remove(__classname__)
153 else: 153 else:
154 if include == 0: 154 if include == 0:
155 safe_d = d 155 return ast.multi_finalize(fn, d)
156 d = bb.data.createCopy(safe_d) 156
157 try:
158 ast.finalise(fn, d)
159 except bb.parse.SkipPackage:
160 bb.data.setVar("__SKIPPED", True, d)
161 darray = {"": d}
162
163 extended = bb.data.getVar("BBCLASSEXTEND", d, True)
164 if extended:
165 bb.data.setVar("BBCLASSEXTEND", extended, safe_d)
166
167 for cls in (extended or "").split():
168 pn = data.getVar('PN', d, True)
169 variant_d = bb.data.createCopy(safe_d)
170 data.setVar('PN', pn + '-' + cls, variant_d)
171 inherit([cls], variant_d)
172 try:
173 ast.finalise(fn, variant_d)
174 except bb.parse.SkipPackage:
175 bb.data.setVar("__SKIPPED", True, variant_d)
176 darray[cls] = variant_d
177 return darray
178
179 if oldfile: 157 if oldfile:
180 bb.data.setVar("FILE", oldfile, d) 158 bb.data.setVar("FILE", oldfile, d)
181 159