summaryrefslogtreecommitdiffstats
path: root/bitbake/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/bin')
-rwxr-xr-xbitbake/bin/bitbake-layers133
1 files changed, 133 insertions, 0 deletions
diff --git a/bitbake/bin/bitbake-layers b/bitbake/bin/bitbake-layers
index 956e7a978c..774ce2db22 100755
--- a/bitbake/bin/bitbake-layers
+++ b/bitbake/bin/bitbake-layers
@@ -542,6 +542,139 @@ Recipes are listed with the bbappends that apply to them as subitems.
542 notappended.append(basename) 542 notappended.append(basename)
543 return appended, notappended 543 return appended, notappended
544 544
545 def do_show_cross_depends(self, args):
546 """figure out the dependency between recipes that crosses a layer boundary.
547
548usage: show-cross-depends
549
550Figure out the dependency between recipes that crosses a layer boundary.
551
552NOTE:
553The .bbappend file can impact the dependency.
554"""
555 self.bbhandler.prepare()
556 pkg_fn = self.bbhandler.cooker_data.pkg_fn
557 bbpath = str(self.bbhandler.config_data.getVar('BBPATH', True))
558 self.require_re = re.compile(r"require\s+(.+)")
559 self.include_re = re.compile(r"include\s+(.+)")
560 self.inherit_re = re.compile(r"inherit\s+(.+)")
561
562 # The bb's DEPENDS and RDEPENDS
563 for f in pkg_fn:
564 f = bb.cache.Cache.virtualfn2realfn(f)[0]
565 # Get the layername that the file is in
566 layername = self.get_file_layer(f)
567
568 # The DEPENDS
569 deps = self.bbhandler.cooker_data.deps[f]
570 for pn in deps:
571 if pn in self.bbhandler.cooker_data.pkg_pn:
572 best = bb.providers.findBestProvider(pn,
573 self.bbhandler.cooker.configuration.data,
574 self.bbhandler.cooker_data,
575 self.bbhandler.cooker_data.pkg_pn)
576 self.check_cross_depends("DEPENDS", layername, f, best[3])
577
578 # The RDPENDS
579 all_rdeps = self.bbhandler.cooker_data.rundeps[f].values()
580 # Remove the duplicated or null one.
581 sorted_rdeps = {}
582 # The all_rdeps is the list in list, so we need two for loops
583 for k1 in all_rdeps:
584 for k2 in k1:
585 sorted_rdeps[k2] = 1
586 all_rdeps = sorted_rdeps.keys()
587 for rdep in all_rdeps:
588 all_p = bb.providers.getRuntimeProviders(self.bbhandler.cooker_data, rdep)
589 if all_p:
590 best = bb.providers.filterProvidersRunTime(all_p, rdep,
591 self.bbhandler.cooker.configuration.data,
592 self.bbhandler.cooker_data)[0][0]
593 self.check_cross_depends("RDEPENDS", layername, f, best)
594
595 # The inherit class
596 cls_re = re.compile('classes/')
597 if f in self.bbhandler.cooker_data.inherits:
598 inherits = self.bbhandler.cooker_data.inherits[f]
599 for cls in inherits:
600 # The inherits' format is [classes/cls, /path/to/classes/cls]
601 # ignore the classes/cls.
602 if not cls_re.match(cls):
603 inherit_layername = self.get_file_layer(cls)
604 if inherit_layername != layername:
605 logger.plain("%s inherits %s" % (f, cls))
606
607 # The 'require/include xxx' in the bb file
608 pv_re = re.compile(r"\${PV}")
609 fnfile = open(f, 'r')
610 line = fnfile.readline()
611 while line:
612 m, keyword = self.match_require_include(line)
613 # Found the 'require/include xxxx'
614 if m:
615 needed_file = m.group(1)
616 # Replace the ${PV} with the real PV
617 if pv_re.search(needed_file) and f in self.bbhandler.cooker_data.pkg_pepvpr:
618 pv = self.bbhandler.cooker_data.pkg_pepvpr[f][1]
619 needed_file = re.sub(r"\${PV}", pv, needed_file)
620 self.print_cross_files(bbpath, keyword, layername, f, needed_file)
621 line = fnfile.readline()
622 fnfile.close()
623
624 # The "require/include xxx" in conf/machine/*.conf, .inc and .bbclass
625 conf_re = re.compile(".*/conf/machine/[^\/]*\.conf$")
626 inc_re = re.compile(".*\.inc$")
627 # The "inherit xxx" in .bbclass
628 bbclass_re = re.compile(".*\.bbclass$")
629 for layerdir in self.bblayers:
630 layername = self.get_layer_name(layerdir)
631 for dirpath, dirnames, filenames in os.walk(layerdir):
632 for name in filenames:
633 f = os.path.join(dirpath, name)
634 s = conf_re.match(f) or inc_re.match(f) or bbclass_re.match(f)
635 if s:
636 ffile = open(f, 'r')
637 line = ffile.readline()
638 while line:
639 m, keyword = self.match_require_include(line)
640 # Only bbclass has the "inherit xxx" here.
641 bbclass=""
642 if not m and f.endswith(".bbclass"):
643 m, keyword = self.match_inherit(line)
644 bbclass=".bbclass"
645 # Find a 'require/include xxxx'
646 if m:
647 self.print_cross_files(bbpath, keyword, layername, f, m.group(1) + bbclass)
648 line = ffile.readline()
649 ffile.close()
650
651 def print_cross_files(self, bbpath, keyword, layername, f, needed_filename):
652 """Print the depends that crosses a layer boundary"""
653 needed_file = bb.utils.which(bbpath, needed_filename)
654 if needed_file:
655 # Which layer is this file from
656 needed_layername = self.get_file_layer(needed_file)
657 if needed_layername != layername:
658 logger.plain("%s %s %s" %(f, keyword, needed_file))
659 def match_inherit(self, line):
660 """Match the inherit xxx line"""
661 return (self.inherit_re.match(line), "inherits")
662
663 def match_require_include(self, line):
664 """Match the require/include xxx line"""
665 m = self.require_re.match(line)
666 keyword = "requires"
667 if not m:
668 m = self.include_re.match(line)
669 keyword = "includes"
670 return (m, keyword)
671
672 def check_cross_depends(self, keyword, layername, f, needed_file):
673 """Print the DEPENDS/RDEPENDS file that crosses a layer boundary"""
674 best_realfn = bb.cache.Cache.virtualfn2realfn(needed_file)[0]
675 needed_layername = self.get_file_layer(best_realfn)
676 if needed_layername != layername:
677 logger.plain("%s %s %s" % (f, keyword, best_realfn))
545 678
546if __name__ == '__main__': 679if __name__ == '__main__':
547 sys.exit(main(sys.argv[1:]) or 0) 680 sys.exit(main(sys.argv[1:]) or 0)