summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Laplante <chris.laplante@agilent.com>2025-01-07 16:54:03 -0500
committerSteve Sakoman <steve@sakoman.com>2025-01-24 07:59:38 -0800
commit7aa8128bf1744dc0dd4c68065d19e12c86443c46 (patch)
tree13a67d6420ee51cfbb759accbc5f6d745fcfa66a
parentc1ed07ecde3eea6dee3f7f0c7862ca85858e840d (diff)
downloadpoky-7aa8128bf1744dc0dd4c68065d19e12c86443c46.tar.gz
bitbake: cooker: Make cooker 'skiplist' per-multiconfig/mc
Previously, the cooker skiplist was shared across multiconfigs (including default ''). If you had a recipe that was incompatible with several multiconfigs for different reasons, then the displayed reason (i.e. the "ERROR: Nothing PROVIDES" and "* was skipped" messages) might vary across invocations of bitbake. This was caused by the random order in which recipes are parsed under different multiconfig contexts, with each skip reason overwriting the previously assigned reason. I hit this specificially when using COMPATIBLE_MACHINE, but COMPATIBLE_HOST (or anything using bb.parse.SkipRecipe) would have done it too. (Bitbake rev: 7dde14582bfd104c6da26e3f5ecf2ef37a1494ce) Signed-off-by: Chris Laplante <chris.laplante@agilent.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--bitbake/lib/bb/command.py21
-rw-r--r--bitbake/lib/bb/cooker.py11
-rw-r--r--bitbake/lib/bb/tinfoil.py16
-rw-r--r--bitbake/lib/bblayers/query.py14
4 files changed, 43 insertions, 19 deletions
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py
index 1fcb9bf14c..5e166fe45c 100644
--- a/bitbake/lib/bb/command.py
+++ b/bitbake/lib/bb/command.py
@@ -420,15 +420,30 @@ class CommandsSync:
420 return command.cooker.recipecaches[mc].pkg_dp 420 return command.cooker.recipecaches[mc].pkg_dp
421 getDefaultPreference.readonly = True 421 getDefaultPreference.readonly = True
422 422
423
423 def getSkippedRecipes(self, command, params): 424 def getSkippedRecipes(self, command, params):
425 """
426 Get the map of skipped recipes for the specified multiconfig/mc name (`params[0]`).
427
428 Invoked by `bb.tinfoil.Tinfoil.get_skipped_recipes`
429
430 :param command: Internally used parameter.
431 :param params: Parameter array. params[0] is multiconfig/mc name. If not given, then default mc '' is assumed.
432 :return: Dict whose keys are virtualfns and values are `bb.cooker.SkippedPackage`
433 """
434 try:
435 mc = params[0]
436 except IndexError:
437 mc = ''
438
424 # Return list sorted by reverse priority order 439 # Return list sorted by reverse priority order
425 import bb.cache 440 import bb.cache
426 def sortkey(x): 441 def sortkey(x):
427 vfn, _ = x 442 vfn, _ = x
428 realfn, _, mc = bb.cache.virtualfn2realfn(vfn) 443 realfn, _, item_mc = bb.cache.virtualfn2realfn(vfn)
429 return (-command.cooker.collections[mc].calc_bbfile_priority(realfn)[0], vfn) 444 return -command.cooker.collections[item_mc].calc_bbfile_priority(realfn)[0], vfn
430 445
431 skipdict = OrderedDict(sorted(command.cooker.skiplist.items(), key=sortkey)) 446 skipdict = OrderedDict(sorted(command.cooker.skiplist_by_mc[mc].items(), key=sortkey))
432 return list(skipdict.items()) 447 return list(skipdict.items())
433 getSkippedRecipes.readonly = True 448 getSkippedRecipes.readonly = True
434 449
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py
index 1cb3e189f4..6fce19b464 100644
--- a/bitbake/lib/bb/cooker.py
+++ b/bitbake/lib/bb/cooker.py
@@ -134,7 +134,8 @@ class BBCooker:
134 self.baseconfig_valid = False 134 self.baseconfig_valid = False
135 self.parsecache_valid = False 135 self.parsecache_valid = False
136 self.eventlog = None 136 self.eventlog = None
137 self.skiplist = {} 137 # The skiplists, one per multiconfig
138 self.skiplist_by_mc = defaultdict(dict)
138 self.featureset = CookerFeatures() 139 self.featureset = CookerFeatures()
139 if featureSet: 140 if featureSet:
140 for f in featureSet: 141 for f in featureSet:
@@ -612,8 +613,8 @@ class BBCooker:
612 localdata = {} 613 localdata = {}
613 614
614 for mc in self.multiconfigs: 615 for mc in self.multiconfigs:
615 taskdata[mc] = bb.taskdata.TaskData(halt, skiplist=self.skiplist, allowincomplete=allowincomplete) 616 taskdata[mc] = bb.taskdata.TaskData(halt, skiplist=self.skiplist_by_mc[mc], allowincomplete=allowincomplete)
616 localdata[mc] = data.createCopy(self.databuilder.mcdata[mc]) 617 localdata[mc] = bb.data.createCopy(self.databuilder.mcdata[mc])
617 bb.data.expandKeys(localdata[mc]) 618 bb.data.expandKeys(localdata[mc])
618 619
619 current = 0 620 current = 0
@@ -933,7 +934,7 @@ class BBCooker:
933 for mc in self.multiconfigs: 934 for mc in self.multiconfigs:
934 # First get list of recipes, including skipped 935 # First get list of recipes, including skipped
935 recipefns = list(self.recipecaches[mc].pkg_fn.keys()) 936 recipefns = list(self.recipecaches[mc].pkg_fn.keys())
936 recipefns.extend(self.skiplist.keys()) 937 recipefns.extend(self.skiplist_by_mc[mc].keys())
937 938
938 # Work out list of bbappends that have been applied 939 # Work out list of bbappends that have been applied
939 applied_appends = [] 940 applied_appends = []
@@ -2358,7 +2359,7 @@ class CookerParser(object):
2358 for virtualfn, info_array in result: 2359 for virtualfn, info_array in result:
2359 if info_array[0].skipped: 2360 if info_array[0].skipped:
2360 self.skipped += 1 2361 self.skipped += 1
2361 self.cooker.skiplist[virtualfn] = SkippedPackage(info_array[0]) 2362 self.cooker.skiplist_by_mc[mc][virtualfn] = SkippedPackage(info_array[0])
2362 self.bb_caches[mc].add_info(virtualfn, info_array, self.cooker.recipecaches[mc], 2363 self.bb_caches[mc].add_info(virtualfn, info_array, self.cooker.recipecaches[mc],
2363 parsed=parsed, watcher = self.cooker.add_filewatch) 2364 parsed=parsed, watcher = self.cooker.add_filewatch)
2364 return True 2365 return True
diff --git a/bitbake/lib/bb/tinfoil.py b/bitbake/lib/bb/tinfoil.py
index dcd3910cc4..4dc4590c31 100644
--- a/bitbake/lib/bb/tinfoil.py
+++ b/bitbake/lib/bb/tinfoil.py
@@ -188,11 +188,19 @@ class TinfoilCookerAdapter:
188 self._cache[name] = attrvalue 188 self._cache[name] = attrvalue
189 return attrvalue 189 return attrvalue
190 190
191 class TinfoilSkiplistByMcAdapter:
192 def __init__(self, tinfoil):
193 self.tinfoil = tinfoil
194
195 def __getitem__(self, mc):
196 return self.tinfoil.get_skipped_recipes(mc)
197
191 def __init__(self, tinfoil): 198 def __init__(self, tinfoil):
192 self.tinfoil = tinfoil 199 self.tinfoil = tinfoil
193 self.multiconfigs = [''] + (tinfoil.config_data.getVar('BBMULTICONFIG') or '').split() 200 self.multiconfigs = [''] + (tinfoil.config_data.getVar('BBMULTICONFIG') or '').split()
194 self.collections = {} 201 self.collections = {}
195 self.recipecaches = {} 202 self.recipecaches = {}
203 self.skiplist_by_mc = self.TinfoilSkiplistByMcAdapter(tinfoil)
196 for mc in self.multiconfigs: 204 for mc in self.multiconfigs:
197 self.collections[mc] = self.TinfoilCookerCollectionAdapter(tinfoil, mc) 205 self.collections[mc] = self.TinfoilCookerCollectionAdapter(tinfoil, mc)
198 self.recipecaches[mc] = self.TinfoilRecipeCacheAdapter(tinfoil, mc) 206 self.recipecaches[mc] = self.TinfoilRecipeCacheAdapter(tinfoil, mc)
@@ -201,8 +209,6 @@ class TinfoilCookerAdapter:
201 # Grab these only when they are requested since they aren't always used 209 # Grab these only when they are requested since they aren't always used
202 if name in self._cache: 210 if name in self._cache:
203 return self._cache[name] 211 return self._cache[name]
204 elif name == 'skiplist':
205 attrvalue = self.tinfoil.get_skipped_recipes()
206 elif name == 'bbfile_config_priorities': 212 elif name == 'bbfile_config_priorities':
207 ret = self.tinfoil.run_command('getLayerPriorities') 213 ret = self.tinfoil.run_command('getLayerPriorities')
208 bbfile_config_priorities = [] 214 bbfile_config_priorities = []
@@ -514,12 +520,12 @@ class Tinfoil:
514 """ 520 """
515 return defaultdict(list, self.run_command('getOverlayedRecipes', mc)) 521 return defaultdict(list, self.run_command('getOverlayedRecipes', mc))
516 522
517 def get_skipped_recipes(self): 523 def get_skipped_recipes(self, mc=''):
518 """ 524 """
519 Find recipes which were skipped (i.e. SkipRecipe was raised 525 Find recipes which were skipped (i.e. SkipRecipe was raised
520 during parsing). 526 during parsing).
521 """ 527 """
522 return OrderedDict(self.run_command('getSkippedRecipes')) 528 return OrderedDict(self.run_command('getSkippedRecipes', mc))
523 529
524 def get_all_providers(self, mc=''): 530 def get_all_providers(self, mc=''):
525 return defaultdict(list, self.run_command('allProviders', mc)) 531 return defaultdict(list, self.run_command('allProviders', mc))
@@ -533,6 +539,7 @@ class Tinfoil:
533 def get_runtime_providers(self, rdep): 539 def get_runtime_providers(self, rdep):
534 return self.run_command('getRuntimeProviders', rdep) 540 return self.run_command('getRuntimeProviders', rdep)
535 541
542 # TODO: teach this method about mc
536 def get_recipe_file(self, pn): 543 def get_recipe_file(self, pn):
537 """ 544 """
538 Get the file name for the specified recipe/target. Raises 545 Get the file name for the specified recipe/target. Raises
@@ -541,6 +548,7 @@ class Tinfoil:
541 """ 548 """
542 best = self.find_best_provider(pn) 549 best = self.find_best_provider(pn)
543 if not best or (len(best) > 3 and not best[3]): 550 if not best or (len(best) > 3 and not best[3]):
551 # TODO: pass down mc
544 skiplist = self.get_skipped_recipes() 552 skiplist = self.get_skipped_recipes()
545 taskdata = bb.taskdata.TaskData(None, skiplist=skiplist) 553 taskdata = bb.taskdata.TaskData(None, skiplist=skiplist)
546 skipreasons = taskdata.get_reasons(pn) 554 skipreasons = taskdata.get_reasons(pn)
diff --git a/bitbake/lib/bblayers/query.py b/bitbake/lib/bblayers/query.py
index bfc18a7593..eb7cb465b4 100644
--- a/bitbake/lib/bblayers/query.py
+++ b/bitbake/lib/bblayers/query.py
@@ -142,10 +142,10 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
142 # Ensure we list skipped recipes 142 # Ensure we list skipped recipes
143 # We are largely guessing about PN, PV and the preferred version here, 143 # We are largely guessing about PN, PV and the preferred version here,
144 # but we have no choice since skipped recipes are not fully parsed 144 # but we have no choice since skipped recipes are not fully parsed
145 skiplist = list(self.tinfoil.cooker.skiplist.keys()) 145 skiplist = list(self.tinfoil.cooker.skiplist_by_mc[mc].keys())
146 mcspec = 'mc:%s:' % mc 146
147 if mc: 147 if mc:
148 skiplist = [s[len(mcspec):] for s in skiplist if s.startswith(mcspec)] 148 skiplist = [s.removeprefix(f'mc:{mc}:') for s in skiplist]
149 149
150 for fn in skiplist: 150 for fn in skiplist:
151 recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_') 151 recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_')
@@ -162,7 +162,7 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
162 def print_item(f, pn, ver, layer, ispref): 162 def print_item(f, pn, ver, layer, ispref):
163 if not selected_layer or layer == selected_layer: 163 if not selected_layer or layer == selected_layer:
164 if not bare and f in skiplist: 164 if not bare and f in skiplist:
165 skipped = ' (skipped: %s)' % self.tinfoil.cooker.skiplist[f].skipreason 165 skipped = ' (skipped: %s)' % self.tinfoil.cooker.skiplist_by_mc[mc][f].skipreason
166 else: 166 else:
167 skipped = '' 167 skipped = ''
168 if show_filenames: 168 if show_filenames:
@@ -301,7 +301,7 @@ Lists recipes with the bbappends that apply to them as subitems.
301 if self.show_appends_for_pn(pn, cooker_data, args.mc): 301 if self.show_appends_for_pn(pn, cooker_data, args.mc):
302 appends = True 302 appends = True
303 303
304 if not args.pnspec and self.show_appends_for_skipped(): 304 if not args.pnspec and self.show_appends_for_skipped(args.mc):
305 appends = True 305 appends = True
306 306
307 if not appends: 307 if not appends:
@@ -317,9 +317,9 @@ Lists recipes with the bbappends that apply to them as subitems.
317 317
318 return self.show_appends_output(filenames, best_filename) 318 return self.show_appends_output(filenames, best_filename)
319 319
320 def show_appends_for_skipped(self): 320 def show_appends_for_skipped(self, mc):
321 filenames = [os.path.basename(f) 321 filenames = [os.path.basename(f)
322 for f in self.tinfoil.cooker.skiplist.keys()] 322 for f in self.tinfoil.cooker.skiplist_by_mc[mc].keys()]
323 return self.show_appends_output(filenames, None, " (skipped)") 323 return self.show_appends_output(filenames, None, " (skipped)")
324 324
325 def show_appends_output(self, filenames, best_filename, name_suffix = ''): 325 def show_appends_output(self, filenames, best_filename, name_suffix = ''):