* [PATCH v2 1/4] tinfoil: add context manager functions
2016-08-30 20:48 [PATCH v2 0/4] Tinfoil fixes Paul Eggleton
@ 2016-08-30 20:48 ` Paul Eggleton
2016-08-30 20:48 ` [PATCH v2 2/4] Ensure tinfoil is shut down correctly in utilities that use it Paul Eggleton
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Paul Eggleton @ 2016-08-30 20:48 UTC (permalink / raw)
To: bitbake-devel
Since calling the shutdown() function is highly recommended, make
tinfoil objects a little easier to deal with by adding context manager
support - so you can do the following:
with bb.tinfoil.Tinfoil() as tinfoil:
tinfoil.prepare(True)
...
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
---
lib/bb/tinfoil.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/lib/bb/tinfoil.py b/lib/bb/tinfoil.py
index 95608ae..441be2c 100644
--- a/lib/bb/tinfoil.py
+++ b/lib/bb/tinfoil.py
@@ -59,6 +59,12 @@ class Tinfoil:
def register_idle_function(self, function, data):
pass
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self.shutdown()
+
def parseRecipes(self):
sys.stderr.write("Parsing recipes..")
self.logger.setLevel(logging.WARNING)
--
2.5.5
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 2/4] Ensure tinfoil is shut down correctly in utilities that use it
2016-08-30 20:48 [PATCH v2 0/4] Tinfoil fixes Paul Eggleton
2016-08-30 20:48 ` [PATCH v2 1/4] tinfoil: add context manager functions Paul Eggleton
@ 2016-08-30 20:48 ` Paul Eggleton
2016-08-30 20:48 ` [PATCH v2 3/4] cache: allow parsing a recipe with a custom config datastore Paul Eggleton
2016-08-30 20:48 ` [PATCH v2 4/4] tinfoil: add a parse_recipe_file function Paul Eggleton
3 siblings, 0 replies; 6+ messages in thread
From: Paul Eggleton @ 2016-08-30 20:48 UTC (permalink / raw)
To: bitbake-devel
We should always shut down tinfoil when we're finished with it, either
by explicitly calling the shutdown() method or by using it as a
context manager ("with ...").
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
---
bin/bitbake-diffsigs | 6 +++---
bin/bitbake-layers | 53 +++++++++++++++++++++++++++-------------------------
2 files changed, 31 insertions(+), 28 deletions(-)
diff --git a/bin/bitbake-diffsigs b/bin/bitbake-diffsigs
index 3b6ef88..527d2c7 100755
--- a/bin/bitbake-diffsigs
+++ b/bin/bitbake-diffsigs
@@ -115,9 +115,9 @@ parser.add_option("-t", "--task",
options, args = parser.parse_args(sys.argv)
if options.taskargs:
- tinfoil = bb.tinfoil.Tinfoil()
- tinfoil.prepare(config_only = True)
- find_compare_task(tinfoil, options.taskargs[0], options.taskargs[1])
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=True)
+ find_compare_task(tinfoil, options.taskargs[0], options.taskargs[1])
else:
if len(args) == 1:
parser.print_help()
diff --git a/bin/bitbake-layers b/bin/bitbake-layers
index 0c973df..946def2 100755
--- a/bin/bitbake-layers
+++ b/bin/bitbake-layers
@@ -87,31 +87,34 @@ def main():
plugins = []
tinfoil = tinfoil_init(False)
- for path in ([topdir] +
- tinfoil.config_data.getVar('BBPATH', True).split(':')):
- pluginpath = os.path.join(path, 'lib', 'bblayers')
- bb.utils.load_plugins(logger, plugins, pluginpath)
-
- registered = False
- for plugin in plugins:
- if hasattr(plugin, 'register_commands'):
- registered = True
- plugin.register_commands(subparsers)
- if hasattr(plugin, 'tinfoil_init'):
- plugin.tinfoil_init(tinfoil)
-
- if not registered:
- logger.error("No commands registered - missing plugins?")
- sys.exit(1)
-
- args = parser.parse_args(unparsed_args, namespace=global_args)
-
- if getattr(args, 'parserecipes', False):
- tinfoil.config_data.disableTracking()
- tinfoil.parseRecipes()
- tinfoil.config_data.enableTracking()
-
- return args.func(args)
+ try:
+ for path in ([topdir] +
+ tinfoil.config_data.getVar('BBPATH', True).split(':')):
+ pluginpath = os.path.join(path, 'lib', 'bblayers')
+ bb.utils.load_plugins(logger, plugins, pluginpath)
+
+ registered = False
+ for plugin in plugins:
+ if hasattr(plugin, 'register_commands'):
+ registered = True
+ plugin.register_commands(subparsers)
+ if hasattr(plugin, 'tinfoil_init'):
+ plugin.tinfoil_init(tinfoil)
+
+ if not registered:
+ logger.error("No commands registered - missing plugins?")
+ sys.exit(1)
+
+ args = parser.parse_args(unparsed_args, namespace=global_args)
+
+ if getattr(args, 'parserecipes', False):
+ tinfoil.config_data.disableTracking()
+ tinfoil.parseRecipes()
+ tinfoil.config_data.enableTracking()
+
+ return args.func(args)
+ finally:
+ tinfoil.shutdown()
if __name__ == "__main__":
--
2.5.5
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 3/4] cache: allow parsing a recipe with a custom config datastore
2016-08-30 20:48 [PATCH v2 0/4] Tinfoil fixes Paul Eggleton
2016-08-30 20:48 ` [PATCH v2 1/4] tinfoil: add context manager functions Paul Eggleton
2016-08-30 20:48 ` [PATCH v2 2/4] Ensure tinfoil is shut down correctly in utilities that use it Paul Eggleton
@ 2016-08-30 20:48 ` Paul Eggleton
2016-08-30 21:11 ` Paul Eggleton
2016-08-30 20:48 ` [PATCH v2 4/4] tinfoil: add a parse_recipe_file function Paul Eggleton
3 siblings, 1 reply; 6+ messages in thread
From: Paul Eggleton @ 2016-08-30 20:48 UTC (permalink / raw)
To: bitbake-devel
To accommodate the OpenEmbedded layer index recipe parsing, we have to
have the ability to pass in a custom config datastore since it
constructs a synthetic one. To make this possible after the multi-config
changes, rename the internal _load_bbfile() function to parse_recipe(),
make it a function at the module level (since it doesn't actually need
to access any members of the class or instance) and move setting
__BBMULTICONFIG inside it since other code will expect that to be set.
Part of the fix for [YOCTO #10192].
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
---
lib/bb/cache.py | 73 ++++++++++++++++++++++++++++++---------------------------
1 file changed, 39 insertions(+), 34 deletions(-)
diff --git a/lib/bb/cache.py b/lib/bb/cache.py
index 0d5a034..ccad5c8 100644
--- a/lib/bb/cache.py
+++ b/lib/bb/cache.py
@@ -286,6 +286,42 @@ def variant2virtual(realfn, variant):
return "multiconfig:" + elems[1] + ":" + realfn
return "virtual:" + variant + ":" + realfn
+def parse_recipe(bb_data, bbfile, appends, mc=''):
+ """
+ Parse a recipe
+ """
+
+ chdir_back = False
+
+ bb_data.setVar("__BBMULTICONFIG", mc)
+
+ # expand tmpdir to include this topdir
+ bb_data.setVar('TMPDIR', bb_data.getVar('TMPDIR', True) or "")
+ bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
+ oldpath = os.path.abspath(os.getcwd())
+ bb.parse.cached_mtime_noerror(bbfile_loc)
+
+ # The ConfHandler first looks if there is a TOPDIR and if not
+ # then it would call getcwd().
+ # Previously, we chdir()ed to bbfile_loc, called the handler
+ # and finally chdir()ed back, a couple of thousand times. We now
+ # just fill in TOPDIR to point to bbfile_loc if there is no TOPDIR yet.
+ if not bb_data.getVar('TOPDIR', False):
+ chdir_back = True
+ bb_data.setVar('TOPDIR', bbfile_loc)
+ try:
+ if appends:
+ bb_data.setVar('__BBAPPEND', " ".join(appends))
+ bb_data = bb.parse.handle(bbfile, bb_data)
+ if chdir_back:
+ os.chdir(oldpath)
+ return bb_data
+ except:
+ if chdir_back:
+ os.chdir(oldpath)
+ raise
+
+
class NoCache(object):
@@ -312,54 +348,23 @@ class NoCache(object):
if virtonly:
(bbfile, virtual, mc) = virtualfn2realfn(bbfile)
bb_data = self.databuilder.mcdata[mc].createCopy()
- bb_data.setVar("__BBMULTICONFIG", mc)
bb_data.setVar("__ONLYFINALISE", virtual or "default")
- datastores = self._load_bbfile(bb_data, bbfile, appends)
+ datastores = parse_recipe(bb_data, bbfile, appends, mc)
return datastores
bb_data = self.data.createCopy()
- datastores = self._load_bbfile(bb_data, bbfile, appends)
+ datastores = parse_recipe(bb_data, bbfile, appends, mc)
for mc in self.databuilder.mcdata:
if not mc:
continue
bb_data = self.databuilder.mcdata[mc].createCopy()
- bb_data.setVar("__BBMULTICONFIG", mc)
- newstores = self._load_bbfile(bb_data, bbfile, appends)
+ newstores = parse_recipe(bb_data, bbfile, appends, mc)
for ns in newstores:
datastores["multiconfig:%s:%s" % (mc, ns)] = newstores[ns]
return datastores
- def _load_bbfile(self, bb_data, bbfile, appends):
- chdir_back = False
-
- # expand tmpdir to include this topdir
- bb_data.setVar('TMPDIR', bb_data.getVar('TMPDIR', True) or "")
- bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
- oldpath = os.path.abspath(os.getcwd())
- bb.parse.cached_mtime_noerror(bbfile_loc)
-
- # The ConfHandler first looks if there is a TOPDIR and if not
- # then it would call getcwd().
- # Previously, we chdir()ed to bbfile_loc, called the handler
- # and finally chdir()ed back, a couple of thousand times. We now
- # just fill in TOPDIR to point to bbfile_loc if there is no TOPDIR yet.
- if not bb_data.getVar('TOPDIR', False):
- chdir_back = True
- bb_data.setVar('TOPDIR', bbfile_loc)
- try:
- if appends:
- bb_data.setVar('__BBAPPEND', " ".join(appends))
- bb_data = bb.parse.handle(bbfile, bb_data)
- if chdir_back:
- os.chdir(oldpath)
- return bb_data
- except:
- if chdir_back:
- os.chdir(oldpath)
- raise
-
class Cache(NoCache):
"""
BitBake Cache implementation
--
2.5.5
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v2 3/4] cache: allow parsing a recipe with a custom config datastore
2016-08-30 20:48 ` [PATCH v2 3/4] cache: allow parsing a recipe with a custom config datastore Paul Eggleton
@ 2016-08-30 21:11 ` Paul Eggleton
0 siblings, 0 replies; 6+ messages in thread
From: Paul Eggleton @ 2016-08-30 21:11 UTC (permalink / raw)
To: bitbake-devel
On Wed, 31 Aug 2016 08:48:08 Paul Eggleton wrote:
> To accommodate the OpenEmbedded layer index recipe parsing, we have to
> have the ability to pass in a custom config datastore since it
> constructs a synthetic one. To make this possible after the multi-config
> changes, rename the internal _load_bbfile() function to parse_recipe(),
> make it a function at the module level (since it doesn't actually need
> to access any members of the class or instance) and move setting
> __BBMULTICONFIG inside it since other code will expect that to be set.
>
> Part of the fix for [YOCTO #10192].
>
> Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
> ---
> lib/bb/cache.py | 73
> ++++++++++++++++++++++++++++++--------------------------- 1 file changed,
> 39 insertions(+), 34 deletions(-)
>
> diff --git a/lib/bb/cache.py b/lib/bb/cache.py
> index 0d5a034..ccad5c8 100644
> --- a/lib/bb/cache.py
> +++ b/lib/bb/cache.py
> @@ -286,6 +286,42 @@ def variant2virtual(realfn, variant):
> return "multiconfig:" + elems[1] + ":" + realfn
> return "virtual:" + variant + ":" + realfn
>
> +def parse_recipe(bb_data, bbfile, appends, mc=''):
> + """
> + Parse a recipe
> + """
> +
> + chdir_back = False
> +
> + bb_data.setVar("__BBMULTICONFIG", mc)
> +
> + # expand tmpdir to include this topdir
> + bb_data.setVar('TMPDIR', bb_data.getVar('TMPDIR', True) or "")
> + bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
> + oldpath = os.path.abspath(os.getcwd())
> + bb.parse.cached_mtime_noerror(bbfile_loc)
> +
> + # The ConfHandler first looks if there is a TOPDIR and if not
> + # then it would call getcwd().
> + # Previously, we chdir()ed to bbfile_loc, called the handler
> + # and finally chdir()ed back, a couple of thousand times. We now
> + # just fill in TOPDIR to point to bbfile_loc if there is no TOPDIR yet.
> + if not bb_data.getVar('TOPDIR', False):
> + chdir_back = True
> + bb_data.setVar('TOPDIR', bbfile_loc)
> + try:
> + if appends:
> + bb_data.setVar('__BBAPPEND', " ".join(appends))
> + bb_data = bb.parse.handle(bbfile, bb_data)
> + if chdir_back:
> + os.chdir(oldpath)
> + return bb_data
> + except:
> + if chdir_back:
> + os.chdir(oldpath)
> + raise
> +
> +
>
> class NoCache(object):
>
> @@ -312,54 +348,23 @@ class NoCache(object):
> if virtonly:
> (bbfile, virtual, mc) = virtualfn2realfn(bbfile)
> bb_data = self.databuilder.mcdata[mc].createCopy()
> - bb_data.setVar("__BBMULTICONFIG", mc)
> bb_data.setVar("__ONLYFINALISE", virtual or "default")
> - datastores = self._load_bbfile(bb_data, bbfile, appends)
> + datastores = parse_recipe(bb_data, bbfile, appends, mc)
> return datastores
>
> bb_data = self.data.createCopy()
> - datastores = self._load_bbfile(bb_data, bbfile, appends)
> + datastores = parse_recipe(bb_data, bbfile, appends, mc)
So the last line above was definitely wrong - I've dropped the "mc" parameter
in this call and pushed a new paule/tinfoil-fixes-bb branch.
Cheers,
Paul
--
Paul Eggleton
Intel Open Source Technology Centre
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 4/4] tinfoil: add a parse_recipe_file function
2016-08-30 20:48 [PATCH v2 0/4] Tinfoil fixes Paul Eggleton
` (2 preceding siblings ...)
2016-08-30 20:48 ` [PATCH v2 3/4] cache: allow parsing a recipe with a custom config datastore Paul Eggleton
@ 2016-08-30 20:48 ` Paul Eggleton
3 siblings, 0 replies; 6+ messages in thread
From: Paul Eggleton @ 2016-08-30 20:48 UTC (permalink / raw)
To: bitbake-devel
Parsing a recipe is such a common task for tinfoil-using scripts, and is
a little awkward to do properly, so add an API function to do it. This
should also isolate scripts a little from future changes to the internal
code. The first user of this will be the OpenEmbedded layer index update
script.
Part of the fix for [YOCTO #10192].
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
---
lib/bb/tinfoil.py | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/lib/bb/tinfoil.py b/lib/bb/tinfoil.py
index 441be2c..8899e86 100644
--- a/lib/bb/tinfoil.py
+++ b/lib/bb/tinfoil.py
@@ -90,6 +90,42 @@ class Tinfoil:
else:
self.parseRecipes()
+ def parse_recipe_file(self, fn, appends=True, appendlist=None, config_data=None):
+ """
+ Parse the specified recipe file (with or without bbappends)
+ and return a datastore object representing the environment
+ for the recipe.
+ Parameters:
+ fn: recipe file to parse - can be a file path or virtual
+ specification
+ appends: True to apply bbappends, False otherwise
+ appendlist: optional list of bbappend files to apply, if you
+ want to filter them
+ config_data: custom config datastore to use. NOTE: if you
+ specify config_data then you cannot use a virtual
+ specification for fn.
+ """
+ if appends and appendlist == []:
+ appends = False
+ if appends:
+ if appendlist:
+ appendfiles = appendlist
+ else:
+ if not hasattr(self.cooker, 'collection'):
+ raise Exception('You must call tinfoil.prepare() with config_only=False in order to get bbappends')
+ appendfiles = self.cooker.collection.get_file_appends(fn)
+ else:
+ appendfiles = None
+ if config_data:
+ # We have to use a different function here if we're passing in a datastore
+ localdata = bb.data.createCopy(config_data)
+ envdata = bb.cache.parse_recipe(localdata, fn, appendfiles)['']
+ else:
+ # Use the standard path
+ parser = bb.cache.NoCache(self.cooker.databuilder)
+ envdata = parser.loadDataFull(fn, appendfiles)
+ return envdata
+
def shutdown(self):
self.cooker.shutdown(force=True)
self.cooker.post_serve()
--
2.5.5
^ permalink raw reply related [flat|nested] 6+ messages in thread