Skip to contentSkip to conversation

skipped recipe handling

RFC PATCH In review Paul Eggleton 2 participants 7 messages Jun 1, 2011 – Jun 3, 2011

lore
Share & tools
lore
#0 lore raw

cover skipped recipe handling

I noticed bitbake-layers did not handle bbappends for skipped recipes properly (e.g. in Poky it complained that uclibc_git.bbappend did not match any recipe). Thus I added a mechanism to bitbake within cooker that lists skipped recipes and extended bitbake-layers to use it.

This (or something similar) will also be needed for improving the NoProvider error handling - ideally we should be reporting if the target being requested has been skipped and why. To this end the SkippedPackage class includes the reason and DEPENDS/RDEPENDS info (although at the moment RDEPENDS does not get populated). Some may prefer I remove the DEPENDS/RDEPENDS bits until the future patch where they are used, if so I wouldn't object to removing them.

I also considered adding to skiplist for BBMASKed-out recipes but on reflection I elected not to do so since I assumed we ought to be completely ignoring recipes that are masked out in this way.

Patch summary (these are against Poky but they apply cleanly with -p2 against bitbake master):

Paul Eggleton (2):
bitbake: track skipped packages
bitbake-layers: handle skipped recipes

 bitbake/bin/bitbake-layers  |   24 +++++++++++++++++++-----
 bitbake/lib/bb/cache.py     |   12 +++++++++---
 bitbake/lib/bb/cooker.py    |   16 ++++++++++++++++
 bitbake/lib/bb/parse/ast.py |   12 ++++++------
 4 files changed, 50 insertions(+), 14 deletions(-)
Signature · 1 line
1.7.4.1
#1 lore raw

RFC PATCH 1/2 bitbake: track skipped packages

Add skiplist to cooker that allows access to the list of packages skipped via SkipPackage (this includes COMPATIBLE_MACHINE, INCOMPATIBLE_LICENSE, etc.) This can be used to enhance error reporting.

---
 bitbake/lib/bb/cache.py     |   12 +++++++++---
 bitbake/lib/bb/cooker.py    |   16 ++++++++++++++++
 bitbake/lib/bb/parse/ast.py |   12 ++++++------
 3 files changed, 31 insertions(+), 9 deletions(-)
bitbake/lib/bb/cache.py +9 -3
index d083c51..076262b 100644
@@ -59,6 +59,7 @@ recipe_fields = (
     'broken',
     'not_world',
     'skipped',
+    'skipreason',
     'timestamp',
     'packages',
     'packages_dynamic',
@@ -128,11 +129,15 @@ class RecipeInfo(namedtuple('RecipeInfo', recipe_fields)):
 
     @classmethod
     def from_metadata(cls, filename, metadata):
-        if cls.getvar('__SKIPPED', metadata):
+        skipval = cls.getvar('__SKIPPED', metadata)
+        if skipval:
             return cls.make_optional(skipped=True,
+                                     skipreason=skipval,
                                      file_depends=metadata.getVar('__depends', False),
                                      timestamp=bb.parse.cached_mtime(filename),
-                                     variants=cls.listvar('__VARIANTS', metadata) + [''])
+                                     variants=cls.listvar('__VARIANTS', metadata) + [''],
+                                     provides=cls.depvar('PROVIDES', metadata),
+                                     rprovides=cls.depvar('RPROVIDES', metadata))
 
         tasks = metadata.getVar('__BBTASKS', False)
 
@@ -152,6 +157,7 @@ class RecipeInfo(namedtuple('RecipeInfo', recipe_fields)):
             variants         = cls.listvar('__VARIANTS', metadata) + [''],
 
             skipped          = False,
+            skipreason       = None,
             timestamp        = bb.parse.cached_mtime(filename),
             packages         = cls.listvar('PACKAGES', metadata),
             pn               = pn,
@@ -348,7 +354,7 @@ class Cache(object):
         cached, infos = self.load(fn, appends, cfgData)
         for virtualfn, info in infos:
             if info.skipped:
-                logger.debug(1, "Skipping %s", virtualfn)
+                logger.debug(1, "Skipping %s: %s", (virtualfn, info.skipreason) )
                 skipped += 1
             else:
                 self.add_info(virtualfn, info, cacheData, not cached)
bitbake/lib/bb/cooker.py +16 -0
index 0b52f18..9b12e0d 100644
@@ -55,6 +55,20 @@ class NothingToBuild(Exception):
 class state:
     initial, parsing, running, shutdown, stop = range(5)
 
+
+class SkippedPackage:
+    def __init__(self, info = None, reason = None):
+        self.skipreason = None
+        self.provides = None
+        self.rprovides = None
+
+        if info:
+            self.skipreason = info.skipreason
+            self.provides = info.provides
+            self.rprovides = info.rprovides
+        elif reason:
+            self.skipreason = reason
+
 #============================================================================#
 # BBCooker
 #============================================================================#
@@ -66,6 +80,7 @@ class BBCooker:
     def __init__(self, configuration, server):
         self.status = None
         self.appendlist = {}
+        self.skiplist = {}
 
         if server:
             self.server = server.BitBakeServer(self)
@@ -1198,6 +1213,7 @@ class CookerParser(object):
         for virtualfn, info in result:
             if info.skipped:
                 self.skipped += 1
+                self.cooker.skiplist[virtualfn] = SkippedPackage(info)
             self.bb_cache.add_info(virtualfn, info, self.cooker.status,
                                         parsed=parsed)
         return True
bitbake/lib/bb/parse/ast.py +6 -6
index 375dc61..18e491c 100644
@@ -376,8 +376,8 @@ def multi_finalize(fn, d):
     try:
         if not onlyfinalise or "default" in onlyfinalise:
             finalize(fn, d)
-    except bb.parse.SkipPackage:
-        bb.data.setVar("__SKIPPED", True, d)
+    except bb.parse.SkipPackage as e:
+        bb.data.setVar("__SKIPPED", e.args[0], d)
     datastores = {"": safe_d}
 
     versions = (d.getVar("BBVERSIONS", True) or "").split()
@@ -419,8 +419,8 @@ def multi_finalize(fn, d):
             verfunc(pv, d, safe_d)
             try:
                 finalize(fn, d)
-            except bb.parse.SkipPackage:
-                bb.data.setVar("__SKIPPED", True, d)
+            except bb.parse.SkipPackage as e:
+                bb.data.setVar("__SKIPPED", e.args[0], d)
 
         _create_variants(datastores, versions, verfunc)
 
@@ -439,8 +439,8 @@ def multi_finalize(fn, d):
             try:
                 if not onlyfinalise or variant in onlyfinalise:
                     finalize(fn, variant_d, variant)
-            except bb.parse.SkipPackage:
-                bb.data.setVar("__SKIPPED", True, variant_d)
+            except bb.parse.SkipPackage as e:
+                bb.data.setVar("__SKIPPED", e.args[0], variant_d)
 
     if len(datastores) > 1:
         variants = filter(None, datastores.iterkeys())
Signature · 1 line
1.7.4.1
#5 lore raw

RFC PATCH 2/2 bitbake-layers: handle skipped recipes

In reply to Paul Eggleton

Report bbappends correctly for skipped recipes instead of reporting the bbappends as not having any matching recipe.

---
 bitbake/bin/bitbake-layers |   24 +++++++++++++++++++-----
 1 files changed, 19 insertions(+), 5 deletions(-)
bitbake/bin/bitbake-layers +19 -5
index b6106cd..c58aee3 100755
@@ -81,6 +81,8 @@ class Commands(cmd.Cmd):
         for pn in self.cooker_data.pkg_pn:
             self.show_appends_for_pn(pn)
 
+        self.show_appends_for_skipped()
+
         self.show_appends_with_no_recipes()
 
     def show_appends_for_pn(self, pn):
@@ -92,17 +94,27 @@ class Commands(cmd.Cmd):
                                              self.cooker_data.pkg_pn)
         best_filename = os.path.basename(best[3])
 
+        self.show_appends_output(filenames, best_filename)
+
+    def show_appends_for_skipped(self):
+        filenames = [os.path.basename(f)
+                    for f in self.cooker.skiplist.iterkeys()]
+        self.show_appends_output(filenames, None, " (skipped)")
+
+    def show_appends_output(self, filenames, best_filename, name_suffix = ''):
         appended, missing = self.get_appends_for_files(filenames)
         if appended:
             for basename, appends in appended:
-                logger.info('%s:', basename)
+                logger.info('%s%s:', basename, name_suffix)
                 for append in appends:
                     logger.info('  %s', append)
 
-            if best_filename in missing:
-                logger.warn('%s: missing append for preferred version',
-                            best_filename)
-                self.returncode |= 1
+            if best_filename:
+                if best_filename in missing:
+                    logger.warn('%s: missing append for preferred version',
+                                best_filename)
+                    self.returncode |= 1
+
 
     def get_appends_for_files(self, filenames):
         appended, notappended = set(), set()
@@ -122,6 +134,8 @@ class Commands(cmd.Cmd):
     def show_appends_with_no_recipes(self):
         recipes = set(os.path.basename(f)
                       for f in self.cooker_data.pkg_fn.iterkeys())
+        recipes |= set(os.path.basename(f)
+                      for f in self.cooker.skiplist.iterkeys())
         appended_recipes = self.cooker_data.appends.iterkeys()
         appends_without_recipes = [self.cooker_data.appends[recipe]
                                    for recipe in appended_recipes
Signature · 1 line
1.7.4.1
#2 lore raw

Re: [RFC PATCH 1/2] bitbake: track skipped packages

In reply to Paul Eggleton
Quoted 3 lines · Paul Eggleton

Add skiplist to cooker that allows access to the list of packages skipped via SkipPackage (this includes COMPATIBLE_MACHINE, INCOMPATIBLE_LICENSE, etc.) This can be used to enhance error reporting.

Neat. Minor coding style nit below.

Quoted 112 lines
---
 bitbake/lib/bb/cache.py     |   12 +++++++++---
 bitbake/lib/bb/cooker.py    |   16 ++++++++++++++++
 bitbake/lib/bb/parse/ast.py |   12 ++++++------
 3 files changed, 31 insertions(+), 9 deletions(-)
bitbake/lib/bb/cache.py +9 -3
index d083c51..076262b 100644
@@ -59,6 +59,7 @@ recipe_fields = (
     'broken',
     'not_world',
     'skipped',
+    'skipreason',
     'timestamp',
     'packages',
     'packages_dynamic',
@@ -128,11 +129,15 @@ class RecipeInfo(namedtuple('RecipeInfo', recipe_fields)):
 
     @classmethod
     def from_metadata(cls, filename, metadata):
-        if cls.getvar('__SKIPPED', metadata):
+        skipval = cls.getvar('__SKIPPED', metadata)
+        if skipval:
             return cls.make_optional(skipped=True,
+                                     skipreason=skipval,
                                      file_depends=metadata.getVar('__depends', False),
                                      timestamp=bb.parse.cached_mtime(filename),
-                                     variants=cls.listvar('__VARIANTS', metadata) + [''])
+                                     variants=cls.listvar('__VARIANTS', metadata) + [''],
+                                     provides=cls.depvar('PROVIDES', metadata),
+                                     rprovides=cls.depvar('RPROVIDES', metadata))
 
         tasks = metadata.getVar('__BBTASKS', False)
 
@@ -152,6 +157,7 @@ class RecipeInfo(namedtuple('RecipeInfo', recipe_fields)):
             variants         = cls.listvar('__VARIANTS', metadata) + [''],
 
             skipped          = False,
+            skipreason       = None,
             timestamp        = bb.parse.cached_mtime(filename),
             packages         = cls.listvar('PACKAGES', metadata),
             pn               = pn,
@@ -348,7 +354,7 @@ class Cache(object):
         cached, infos = self.load(fn, appends, cfgData)
         for virtualfn, info in infos:
             if info.skipped:
-                logger.debug(1, "Skipping %s", virtualfn)
+                logger.debug(1, "Skipping %s: %s", (virtualfn, info.skipreason) )
                 skipped += 1
             else:
                 self.add_info(virtualfn, info, cacheData, not cached)
bitbake/lib/bb/cooker.py +16 -0
index 0b52f18..9b12e0d 100644
@@ -55,6 +55,20 @@ class NothingToBuild(Exception):
 class state:
     initial, parsing, running, shutdown, stop = range(5)
 
+
+class SkippedPackage:
+    def __init__(self, info = None, reason = None):
+        self.skipreason = None
+        self.provides = None
+        self.rprovides = None
+
+        if info:
+            self.skipreason = info.skipreason
+            self.provides = info.provides
+            self.rprovides = info.rprovides
+        elif reason:
+            self.skipreason = reason
+
 #============================================================================#
 # BBCooker
 #============================================================================#
@@ -66,6 +80,7 @@ class BBCooker:
     def __init__(self, configuration, server):
         self.status = None
         self.appendlist = {}
+        self.skiplist = {}
 
         if server:
             self.server = server.BitBakeServer(self)
@@ -1198,6 +1213,7 @@ class CookerParser(object):
         for virtualfn, info in result:
             if info.skipped:
                 self.skipped += 1
+                self.cooker.skiplist[virtualfn] = SkippedPackage(info)
             self.bb_cache.add_info(virtualfn, info, self.cooker.status,
                                         parsed=parsed)
         return True
bitbake/lib/bb/parse/ast.py +2 -2
index 375dc61..18e491c 100644
@@ -376,8 +376,8 @@ def multi_finalize(fn, d):
     try:
         if not onlyfinalise or "default" in onlyfinalise:
             finalize(fn, d)
-    except bb.parse.SkipPackage:
-        bb.data.setVar("__SKIPPED", True, d)
+    except bb.parse.SkipPackage as e:
+        bb.data.setVar("__SKIPPED", e.args[0], d)
     datastores = {"": safe_d}
 
     versions = (d.getVar("BBVERSIONS", True) or "").split()

bitbake/lib/bb/parse/ast.py def multi_finalize(fn, d): · line 423

Quoted 7 lines
bitbake/lib/bb/parse/ast.py +2 -2
@@ -419,8 +419,8 @@ def multi_finalize(fn, d):
             verfunc(pv, d, safe_d)
             try:
                 finalize(fn, d)
-            except bb.parse.SkipPackage:
-                bb.data.setVar("__SKIPPED", True, d)
+            except bb.parse.SkipPackage as e:
+                bb.data.setVar("__SKIPPED", e.args[0], d)

This doesn't seem very Pythonic. I think you should just be able to do:
bb.data.setVar("__SKIPPED", e, d)
or possibly:
bb.data.setVar("__SKIPPED", str(e), d)

I know I'm being picky but that e.args[0] stuck out like a sore thumb.

bitbake/lib/bb/parse/ast.py def multi_finalize(fn, d): · line 443

Quoted 11 lines
bitbake/lib/bb/parse/ast.py +2 -2
         _create_variants(datastores, versions, verfunc)
 
@@ -439,8 +439,8 @@ def multi_finalize(fn, d):
             try:
                 if not onlyfinalise or variant in onlyfinalise:
                     finalize(fn, variant_d, variant)
-            except bb.parse.SkipPackage:
-                bb.data.setVar("__SKIPPED", True, variant_d)
+            except bb.parse.SkipPackage as e:
+                bb.data.setVar("__SKIPPED", e.args[0], variant_d)

Same as above.

Quoted 3 lines
bitbake/lib/bb/parse/ast.py +0 -0
     if len(datastores) > 1:
         variants = filter(None, datastores.iterkeys())
Signature · 3 lines
Joshua Lock
        Yocto Build System Monkey
        Intel Open Source Technology Centre
#6 lore raw

Re: [RFC PATCH 2/2] bitbake-layers: handle skipped recipes

In reply to Paul Eggleton
Quoted 4 lines · Paul Eggleton

Report bbappends correctly for skipped recipes instead of reporting the bbappends as not having any matching recipe.

Cool! I know this depends on the 1st patch but

Quoted 59 lines
---
 bitbake/bin/bitbake-layers |   24 +++++++++++++++++++-----
 1 files changed, 19 insertions(+), 5 deletions(-)
bitbake/bin/bitbake-layers +19 -5
index b6106cd..c58aee3 100755
@@ -81,6 +81,8 @@ class Commands(cmd.Cmd):
         for pn in self.cooker_data.pkg_pn:
             self.show_appends_for_pn(pn)
 
+        self.show_appends_for_skipped()
+
         self.show_appends_with_no_recipes()
 
     def show_appends_for_pn(self, pn):
@@ -92,17 +94,27 @@ class Commands(cmd.Cmd):
                                              self.cooker_data.pkg_pn)
         best_filename = os.path.basename(best[3])
 
+        self.show_appends_output(filenames, best_filename)
+
+    def show_appends_for_skipped(self):
+        filenames = [os.path.basename(f)
+                    for f in self.cooker.skiplist.iterkeys()]
+        self.show_appends_output(filenames, None, " (skipped)")
+
+    def show_appends_output(self, filenames, best_filename, name_suffix = ''):
         appended, missing = self.get_appends_for_files(filenames)
         if appended:
             for basename, appends in appended:
-                logger.info('%s:', basename)
+                logger.info('%s%s:', basename, name_suffix)
                 for append in appends:
                     logger.info('  %s', append)
 
-            if best_filename in missing:
-                logger.warn('%s: missing append for preferred version',
-                            best_filename)
-                self.returncode |= 1
+            if best_filename:
+                if best_filename in missing:
+                    logger.warn('%s: missing append for preferred version',
+                                best_filename)
+                    self.returncode |= 1
+
 
     def get_appends_for_files(self, filenames):
         appended, notappended = set(), set()
@@ -122,6 +134,8 @@ class Commands(cmd.Cmd):
     def show_appends_with_no_recipes(self):
         recipes = set(os.path.basename(f)
                       for f in self.cooker_data.pkg_fn.iterkeys())
+        recipes |= set(os.path.basename(f)
+                      for f in self.cooker.skiplist.iterkeys())
         appended_recipes = self.cooker_data.appends.iterkeys()
         appends_without_recipes = [self.cooker_data.appends[recipe]
                                    for recipe in appended_recipes
Signature · 3 lines
Joshua Lock
        Yocto Build System Monkey
        Intel Open Source Technology Centre
#3 lore raw

Re: [RFC PATCH 1/2] bitbake: track skipped packages

In reply to Joshua Lock
Quoted 4 lines · On Thursday 02 June 2011 21:01:52 Joshua Lock wrote:

This doesn't seem very Pythonic. I think you should just be able to do:
bb.data.setVar("__SKIPPED", e, d)
or possibly:
bb.data.setVar("__SKIPPED", str(e), d)

Why is accessing args[0] un-Pythonic? As I understand it, args is provided (and documented) as the way to get access to the arguments to the exception, and the first argument is being used by us for the reason in the case of SkipPackage. At the moment e or str(e) will accomplish the same thing, but were we to add another argument then it seems to me that the results would be different.

Now I'm not a Python expert by any stretch of the imagination but I'd like to understand the reason why this usage might be considered undesirable.

Cheers,
Paul

Signature · 2 lines
Paul Eggleton
Intel Open Source Technology Centre
#4 lore raw

Re: [RFC PATCH 1/2] bitbake: track skipped packages

Quoted 13 lines · Paul Eggleton
Quoted 4 lines · On Thursday 02 June 2011 21:01:52 Joshua Lock wrote:

This doesn't seem very Pythonic. I think you should just be able to do:
bb.data.setVar("__SKIPPED", e, d)
or possibly:
bb.data.setVar("__SKIPPED", str(e), d)

Why is accessing args[0] un-Pythonic? As I understand it, args is provided (and documented) as the way to get access to the arguments to the exception, and the first argument is being used by us for the reason in the case of SkipPackage. At the moment e or str(e) will accomplish the same thing, but were we to add another argument then it seems to me that the results would be different.

Quoted 3 lines

Now I'm not a Python expert by any stretch of the imagination but I'd like to understand the reason why this usage might be considered undesirable.

Caveat: also not a Python expert!

I raised the comment as it's a pattern I've not seen often in Python code I've interacted with. Therefore it stood out/didn't look quite right.

You are correct that if another argument were added the results would be
different: "If str() or unicode() is called on an instance of this class, the representation of the argument(s) to the instance are returned, or the empty string when there were no arguments."
http://docs.python.org/library/exceptions.htm

Happy to retract my nit picking,
Joshua

Signature · 3 lines
Joshua Lock
        Yocto Build System Monkey
        Intel Open Source Technology Centre