summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bblayers
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bblayers')
-rw-r--r--bitbake/lib/bblayers/__init__.py2
-rw-r--r--bitbake/lib/bblayers/action.py17
-rw-r--r--bitbake/lib/bblayers/common.py2
-rw-r--r--bitbake/lib/bblayers/layerindex.py43
-rw-r--r--bitbake/lib/bblayers/query.py60
5 files changed, 94 insertions, 30 deletions
diff --git a/bitbake/lib/bblayers/__init__.py b/bitbake/lib/bblayers/__init__.py
index 4e7c09da04..78efd29750 100644
--- a/bitbake/lib/bblayers/__init__.py
+++ b/bitbake/lib/bblayers/__init__.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright BitBake Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
diff --git a/bitbake/lib/bblayers/action.py b/bitbake/lib/bblayers/action.py
index f05f5d330f..a14f19948e 100644
--- a/bitbake/lib/bblayers/action.py
+++ b/bitbake/lib/bblayers/action.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright BitBake Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -9,6 +11,7 @@ import shutil
9import sys 11import sys
10import tempfile 12import tempfile
11 13
14from bb.cookerdata import findTopdir
12import bb.utils 15import bb.utils
13 16
14from bblayers.common import LayerPlugin 17from bblayers.common import LayerPlugin
@@ -35,7 +38,7 @@ class ActionPlugin(LayerPlugin):
35 sys.stderr.write("Specified layer directory %s doesn't contain a conf/layer.conf file\n" % layerdir) 38 sys.stderr.write("Specified layer directory %s doesn't contain a conf/layer.conf file\n" % layerdir)
36 return 1 39 return 1
37 40
38 bblayers_conf = os.path.join('conf', 'bblayers.conf') 41 bblayers_conf = os.path.join(findTopdir(),'conf', 'bblayers.conf')
39 if not os.path.exists(bblayers_conf): 42 if not os.path.exists(bblayers_conf):
40 sys.stderr.write("Unable to find bblayers.conf\n") 43 sys.stderr.write("Unable to find bblayers.conf\n")
41 return 1 44 return 1
@@ -48,12 +51,14 @@ class ActionPlugin(LayerPlugin):
48 try: 51 try:
49 notadded, _ = bb.utils.edit_bblayers_conf(bblayers_conf, layerdirs, None) 52 notadded, _ = bb.utils.edit_bblayers_conf(bblayers_conf, layerdirs, None)
50 if not (args.force or notadded): 53 if not (args.force or notadded):
54 self.tinfoil.modified_files()
51 try: 55 try:
52 self.tinfoil.run_command('parseConfiguration') 56 self.tinfoil.run_command('parseConfiguration')
53 except (bb.tinfoil.TinfoilUIException, bb.BBHandledException): 57 except (bb.tinfoil.TinfoilUIException, bb.BBHandledException):
54 # Restore the back up copy of bblayers.conf 58 # Restore the back up copy of bblayers.conf
55 shutil.copy2(backup, bblayers_conf) 59 shutil.copy2(backup, bblayers_conf)
56 bb.fatal("Parse failure with the specified layer added, aborting.") 60 self.tinfoil.modified_files()
61 bb.fatal("Parse failure with the specified layer added, exiting.")
57 else: 62 else:
58 for item in notadded: 63 for item in notadded:
59 sys.stderr.write("Specified layer %s is already in BBLAYERS\n" % item) 64 sys.stderr.write("Specified layer %s is already in BBLAYERS\n" % item)
@@ -63,7 +68,7 @@ class ActionPlugin(LayerPlugin):
63 68
64 def do_remove_layer(self, args): 69 def do_remove_layer(self, args):
65 """Remove one or more layers from bblayers.conf.""" 70 """Remove one or more layers from bblayers.conf."""
66 bblayers_conf = os.path.join('conf', 'bblayers.conf') 71 bblayers_conf = os.path.join(findTopdir() ,'conf', 'bblayers.conf')
67 if not os.path.exists(bblayers_conf): 72 if not os.path.exists(bblayers_conf):
68 sys.stderr.write("Unable to find bblayers.conf\n") 73 sys.stderr.write("Unable to find bblayers.conf\n")
69 return 1 74 return 1
@@ -78,6 +83,9 @@ class ActionPlugin(LayerPlugin):
78 layerdir = os.path.abspath(item) 83 layerdir = os.path.abspath(item)
79 layerdirs.append(layerdir) 84 layerdirs.append(layerdir)
80 (_, notremoved) = bb.utils.edit_bblayers_conf(bblayers_conf, None, layerdirs) 85 (_, notremoved) = bb.utils.edit_bblayers_conf(bblayers_conf, None, layerdirs)
86 if args.force > 1:
87 return 0
88 self.tinfoil.modified_files()
81 if notremoved: 89 if notremoved:
82 for item in notremoved: 90 for item in notremoved:
83 sys.stderr.write("No layers matching %s found in BBLAYERS\n" % item) 91 sys.stderr.write("No layers matching %s found in BBLAYERS\n" % item)
@@ -237,6 +245,9 @@ build results (as the layer priority order has effectively changed).
237 if not entry_found: 245 if not entry_found:
238 logger.warning("File %s does not match the flattened layer's BBFILES setting, you may need to edit conf/layer.conf or move the file elsewhere" % f1full) 246 logger.warning("File %s does not match the flattened layer's BBFILES setting, you may need to edit conf/layer.conf or move the file elsewhere" % f1full)
239 247
248 self.tinfoil.modified_files()
249
250
240 def get_file_layer(self, filename): 251 def get_file_layer(self, filename):
241 layerdir = self.get_file_layerdir(filename) 252 layerdir = self.get_file_layerdir(filename)
242 if layerdir: 253 if layerdir:
diff --git a/bitbake/lib/bblayers/common.py b/bitbake/lib/bblayers/common.py
index 6c76ef3505..f7b9cee371 100644
--- a/bitbake/lib/bblayers/common.py
+++ b/bitbake/lib/bblayers/common.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright BitBake Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
diff --git a/bitbake/lib/bblayers/layerindex.py b/bitbake/lib/bblayers/layerindex.py
index b2f27b21ee..ba91fac669 100644
--- a/bitbake/lib/bblayers/layerindex.py
+++ b/bitbake/lib/bblayers/layerindex.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright BitBake Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -47,6 +49,31 @@ class LayerIndexPlugin(ActionPlugin):
47 else: 49 else:
48 logger.plain("Repository %s needs to be fetched" % url) 50 logger.plain("Repository %s needs to be fetched" % url)
49 return subdir, layername, layerdir 51 return subdir, layername, layerdir
52 elif os.path.exists(repodir) and branch:
53 """
54 If the repo is already cloned, ensure it is on the correct branch,
55 switching branches if necessary and possible.
56 """
57 base_cmd = ['git', '--git-dir=%s/.git' % repodir, '--work-tree=%s' % repodir]
58 cmd = base_cmd + ['branch']
59 completed_proc = subprocess.run(cmd, text=True, capture_output=True)
60 if completed_proc.returncode:
61 logger.error("Unable to validate repo %s (%s)" % (repodir, stderr))
62 return None, None, None
63 else:
64 if branch != completed_proc.stdout[2:-1]:
65 cmd = base_cmd + ['status', '--short']
66 completed_proc = subprocess.run(cmd, text=True, capture_output=True)
67 if completed_proc.stdout.count('\n') != 0:
68 logger.warning("There are uncommitted changes in repo %s" % repodir)
69 cmd = base_cmd + ['checkout', branch]
70 completed_proc = subprocess.run(cmd, text=True, capture_output=True)
71 if completed_proc.returncode:
72 # Could be due to original shallow clone on a different branch for example
73 logger.error("Unable to automatically switch %s to desired branch '%s' (%s)"
74 % (repodir, branch, completed_proc.stderr))
75 return None, None, None
76 return subdir, layername, layerdir
50 elif os.path.exists(layerdir): 77 elif os.path.exists(layerdir):
51 return subdir, layername, layerdir 78 return subdir, layername, layerdir
52 else: 79 else:
@@ -159,12 +186,17 @@ class LayerIndexPlugin(ActionPlugin):
159 logger.plain(' recommended by: %s' % ' '.join(recommendedby)) 186 logger.plain(' recommended by: %s' % ' '.join(recommendedby))
160 187
161 if dependencies: 188 if dependencies:
162 fetchdir = self.tinfoil.config_data.getVar('BBLAYERS_FETCH_DIR') 189 if args.fetchdir:
163 if not fetchdir: 190 fetchdir = args.fetchdir
164 logger.error("Cannot get BBLAYERS_FETCH_DIR") 191 else:
165 return 1 192 fetchdir = self.tinfoil.config_data.getVar('BBLAYERS_FETCH_DIR')
193 if not fetchdir:
194 logger.error("Cannot get BBLAYERS_FETCH_DIR")
195 return 1
196
166 if not os.path.exists(fetchdir): 197 if not os.path.exists(fetchdir):
167 os.makedirs(fetchdir) 198 os.makedirs(fetchdir)
199
168 addlayers = [] 200 addlayers = []
169 201
170 for deplayerbranch in dependencies: 202 for deplayerbranch in dependencies:
@@ -206,6 +238,8 @@ class LayerIndexPlugin(ActionPlugin):
206""" 238"""
207 args.show_only = True 239 args.show_only = True
208 args.ignore = [] 240 args.ignore = []
241 args.fetchdir = ""
242 args.shallow = True
209 self.do_layerindex_fetch(args) 243 self.do_layerindex_fetch(args)
210 244
211 def register_commands(self, sp): 245 def register_commands(self, sp):
@@ -214,6 +248,7 @@ class LayerIndexPlugin(ActionPlugin):
214 parser_layerindex_fetch.add_argument('-b', '--branch', help='branch name to fetch') 248 parser_layerindex_fetch.add_argument('-b', '--branch', help='branch name to fetch')
215 parser_layerindex_fetch.add_argument('-s', '--shallow', help='do only shallow clones (--depth=1)', action='store_true') 249 parser_layerindex_fetch.add_argument('-s', '--shallow', help='do only shallow clones (--depth=1)', action='store_true')
216 parser_layerindex_fetch.add_argument('-i', '--ignore', help='assume the specified layers do not need to be fetched/added (separate multiple layers with commas, no spaces)', metavar='LAYER') 250 parser_layerindex_fetch.add_argument('-i', '--ignore', help='assume the specified layers do not need to be fetched/added (separate multiple layers with commas, no spaces)', metavar='LAYER')
251 parser_layerindex_fetch.add_argument('-f', '--fetchdir', help='directory to fetch the layer(s) into (will be created if it does not exist)')
217 parser_layerindex_fetch.add_argument('layername', nargs='+', help='layer to fetch') 252 parser_layerindex_fetch.add_argument('layername', nargs='+', help='layer to fetch')
218 253
219 parser_layerindex_show_depends = self.add_command(sp, 'layerindex-show-depends', self.do_layerindex_show_depends, parserecipes=False) 254 parser_layerindex_show_depends = self.add_command(sp, 'layerindex-show-depends', self.do_layerindex_show_depends, parserecipes=False)
diff --git a/bitbake/lib/bblayers/query.py b/bitbake/lib/bblayers/query.py
index f5e3c84747..bfc18a7593 100644
--- a/bitbake/lib/bblayers/query.py
+++ b/bitbake/lib/bblayers/query.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright BitBake Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -27,12 +29,12 @@ class QueryPlugin(LayerPlugin):
27 29
28 def do_show_layers(self, args): 30 def do_show_layers(self, args):
29 """show current configured layers.""" 31 """show current configured layers."""
30 logger.plain("%s %s %s" % ("layer".ljust(20), "path".ljust(40), "priority")) 32 logger.plain("%s %s %s" % ("layer".ljust(20), "path".ljust(70), "priority"))
31 logger.plain('=' * 74) 33 logger.plain('=' * 104)
32 for layer, _, regex, pri in self.tinfoil.cooker.bbfile_config_priorities: 34 for layer, _, regex, pri in self.tinfoil.cooker.bbfile_config_priorities:
33 layerdir = self.bbfile_collections.get(layer, None) 35 layerdir = self.bbfile_collections.get(layer, None)
34 layername = self.get_layer_name(layerdir) 36 layername = layer
35 logger.plain("%s %s %d" % (layername.ljust(20), layerdir.ljust(40), pri)) 37 logger.plain("%s %s %s" % (layername.ljust(20), layerdir.ljust(70), pri))
36 38
37 def version_str(self, pe, pv, pr = None): 39 def version_str(self, pe, pv, pr = None):
38 verstr = "%s" % pv 40 verstr = "%s" % pv
@@ -55,11 +57,12 @@ are overlayed will also be listed, with a " (skipped)" suffix.
55 # Check for overlayed .bbclass files 57 # Check for overlayed .bbclass files
56 classes = collections.defaultdict(list) 58 classes = collections.defaultdict(list)
57 for layerdir in self.bblayers: 59 for layerdir in self.bblayers:
58 classdir = os.path.join(layerdir, 'classes') 60 for c in ["classes-global", "classes-recipe", "classes"]:
59 if os.path.exists(classdir): 61 classdir = os.path.join(layerdir, c)
60 for classfile in os.listdir(classdir): 62 if os.path.exists(classdir):
61 if os.path.splitext(classfile)[1] == '.bbclass': 63 for classfile in os.listdir(classdir):
62 classes[classfile].append(classdir) 64 if os.path.splitext(classfile)[1] == '.bbclass':
65 classes[classfile].append(classdir)
63 66
64 # Locating classes and other files is a bit more complicated than recipes - 67 # Locating classes and other files is a bit more complicated than recipes -
65 # layer priority is not a factor; instead BitBake uses the first matching 68 # layer priority is not a factor; instead BitBake uses the first matching
@@ -122,13 +125,18 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
122 if inherits: 125 if inherits:
123 bbpath = str(self.tinfoil.config_data.getVar('BBPATH')) 126 bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
124 for classname in inherits: 127 for classname in inherits:
125 classfile = 'classes/%s.bbclass' % classname 128 found = False
126 if not bb.utils.which(bbpath, classfile, history=False): 129 for c in ["classes-global", "classes-recipe", "classes"]:
127 logger.error('No class named %s found in BBPATH', classfile) 130 cfile = c + '/%s.bbclass' % classname
131 if bb.utils.which(bbpath, cfile, history=False):
132 found = True
133 break
134 if not found:
135 logger.error('No class named %s found in BBPATH', classname)
128 sys.exit(1) 136 sys.exit(1)
129 137
130 pkg_pn = self.tinfoil.cooker.recipecaches[mc].pkg_pn 138 pkg_pn = self.tinfoil.cooker.recipecaches[mc].pkg_pn
131 (latest_versions, preferred_versions) = self.tinfoil.find_providers(mc) 139 (latest_versions, preferred_versions, required_versions) = self.tinfoil.find_providers(mc)
132 allproviders = self.tinfoil.get_all_providers(mc) 140 allproviders = self.tinfoil.get_all_providers(mc)
133 141
134 # Ensure we list skipped recipes 142 # Ensure we list skipped recipes
@@ -154,7 +162,7 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
154 def print_item(f, pn, ver, layer, ispref): 162 def print_item(f, pn, ver, layer, ispref):
155 if not selected_layer or layer == selected_layer: 163 if not selected_layer or layer == selected_layer:
156 if not bare and f in skiplist: 164 if not bare and f in skiplist:
157 skipped = ' (skipped)' 165 skipped = ' (skipped: %s)' % self.tinfoil.cooker.skiplist[f].skipreason
158 else: 166 else:
159 skipped = '' 167 skipped = ''
160 if show_filenames: 168 if show_filenames:
@@ -172,7 +180,7 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
172 logger.plain(" %s %s%s", layer.ljust(20), ver, skipped) 180 logger.plain(" %s %s%s", layer.ljust(20), ver, skipped)
173 181
174 global_inherit = (self.tinfoil.config_data.getVar('INHERIT') or "").split() 182 global_inherit = (self.tinfoil.config_data.getVar('INHERIT') or "").split()
175 cls_re = re.compile('classes/') 183 cls_re = re.compile('classes.*/')
176 184
177 preffiles = [] 185 preffiles = []
178 show_unique_pn = [] 186 show_unique_pn = []
@@ -274,7 +282,10 @@ Lists recipes with the bbappends that apply to them as subitems.
274 else: 282 else:
275 logger.plain('=== Appended recipes ===') 283 logger.plain('=== Appended recipes ===')
276 284
277 pnlist = list(self.tinfoil.cooker_data.pkg_pn.keys()) 285
286 cooker_data = self.tinfoil.cooker.recipecaches[args.mc]
287
288 pnlist = list(cooker_data.pkg_pn.keys())
278 pnlist.sort() 289 pnlist.sort()
279 appends = False 290 appends = False
280 for pn in pnlist: 291 for pn in pnlist:
@@ -287,7 +298,7 @@ Lists recipes with the bbappends that apply to them as subitems.
287 if not found: 298 if not found:
288 continue 299 continue
289 300
290 if self.show_appends_for_pn(pn): 301 if self.show_appends_for_pn(pn, cooker_data, args.mc):
291 appends = True 302 appends = True
292 303
293 if not args.pnspec and self.show_appends_for_skipped(): 304 if not args.pnspec and self.show_appends_for_skipped():
@@ -296,8 +307,10 @@ Lists recipes with the bbappends that apply to them as subitems.
296 if not appends: 307 if not appends:
297 logger.plain('No append files found') 308 logger.plain('No append files found')
298 309
299 def show_appends_for_pn(self, pn): 310 def show_appends_for_pn(self, pn, cooker_data, mc):
300 filenames = self.tinfoil.cooker_data.pkg_pn[pn] 311 filenames = cooker_data.pkg_pn[pn]
312 if mc:
313 pn = "mc:%s:%s" % (mc, pn)
301 314
302 best = self.tinfoil.find_best_provider(pn) 315 best = self.tinfoil.find_best_provider(pn)
303 best_filename = os.path.basename(best[3]) 316 best_filename = os.path.basename(best[3])
@@ -405,7 +418,7 @@ NOTE: .bbappend files can impact the dependencies.
405 self.check_cross_depends("RRECOMMENDS", layername, f, best, args.filenames, ignore_layers) 418 self.check_cross_depends("RRECOMMENDS", layername, f, best, args.filenames, ignore_layers)
406 419
407 # The inherit class 420 # The inherit class
408 cls_re = re.compile('classes/') 421 cls_re = re.compile('classes.*/')
409 if f in self.tinfoil.cooker_data.inherits: 422 if f in self.tinfoil.cooker_data.inherits:
410 inherits = self.tinfoil.cooker_data.inherits[f] 423 inherits = self.tinfoil.cooker_data.inherits[f]
411 for cls in inherits: 424 for cls in inherits:
@@ -441,10 +454,10 @@ NOTE: .bbappend files can impact the dependencies.
441 line = fnfile.readline() 454 line = fnfile.readline()
442 455
443 # The "require/include xxx" in conf/machine/*.conf, .inc and .bbclass 456 # The "require/include xxx" in conf/machine/*.conf, .inc and .bbclass
444 conf_re = re.compile(".*/conf/machine/[^\/]*\.conf$") 457 conf_re = re.compile(r".*/conf/machine/[^\/]*\.conf$")
445 inc_re = re.compile(".*\.inc$") 458 inc_re = re.compile(r".*\.inc$")
446 # The "inherit xxx" in .bbclass 459 # The "inherit xxx" in .bbclass
447 bbclass_re = re.compile(".*\.bbclass$") 460 bbclass_re = re.compile(r".*\.bbclass$")
448 for layerdir in self.bblayers: 461 for layerdir in self.bblayers:
449 layername = self.get_layer_name(layerdir) 462 layername = self.get_layer_name(layerdir)
450 for dirpath, dirnames, filenames in os.walk(layerdir): 463 for dirpath, dirnames, filenames in os.walk(layerdir):
@@ -522,6 +535,7 @@ NOTE: .bbappend files can impact the dependencies.
522 535
523 parser_show_appends = self.add_command(sp, 'show-appends', self.do_show_appends) 536 parser_show_appends = self.add_command(sp, 'show-appends', self.do_show_appends)
524 parser_show_appends.add_argument('pnspec', nargs='*', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)') 537 parser_show_appends.add_argument('pnspec', nargs='*', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)')
538 parser_show_appends.add_argument('--mc', help='use specified multiconfig', default='')
525 539
526 parser_show_cross_depends = self.add_command(sp, 'show-cross-depends', self.do_show_cross_depends) 540 parser_show_cross_depends = self.add_command(sp, 'show-cross-depends', self.do_show_cross_depends)
527 parser_show_cross_depends.add_argument('-f', '--filenames', help='show full file path', action='store_true') 541 parser_show_cross_depends.add_argument('-f', '--filenames', help='show full file path', action='store_true')