diff options
Diffstat (limited to 'bitbake/bin')
-rwxr-xr-x | bitbake/bin/bitbake-layers | 133 |
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 | |||
548 | usage: show-cross-depends | ||
549 | |||
550 | Figure out the dependency between recipes that crosses a layer boundary. | ||
551 | |||
552 | NOTE: | ||
553 | The .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 | ||
546 | if __name__ == '__main__': | 679 | if __name__ == '__main__': |
547 | sys.exit(main(sys.argv[1:]) or 0) | 680 | sys.exit(main(sys.argv[1:]) or 0) |