diff options
| author | Robert Yang <liezhi.yang@windriver.com> | 2013-01-25 16:35:10 +0800 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2013-01-31 14:00:03 +0000 |
| commit | 8d80483e2f0f755a61087be1dffaf595fbc467fd (patch) | |
| tree | be7bf0959b5173cf01c7bb6987a5119895c76d39 /bitbake/bin | |
| parent | d82eac804134028ece749928aa2d83096b7aec96 (diff) | |
| download | poky-8d80483e2f0f755a61087be1dffaf595fbc467fd.tar.gz | |
bitbake: bitbake-layers: print the recipe's depends that crosses a layer boundary
Figure out the dependency between recipes that crosses a layer boundary
* Introduction:
- For the .bb file, we need check the following depends:
> Check the DEPENDS, RDEPENDS and inherits according to the
cooker_data.
> The cooker_data doesn't have the info about "require/include xxx",
so we need check them manually.
- For the .bbclass, .inc and .conf file, we can't get their file
depends from the cooker_data, we need check them manually.
* Usage:
$ bitbake-layer show-cross-depends
I don't like the name "show-cross-depends", figure-out-cross-depends
might be better, but most of the commands are "show-xxx" for bitbake-layers.
* Output: (snipped)
/work/poky/meta/recipes-support/libusb/libusb-compat_0.1.4.bb inherits /work/poky/meta-yocto/classes/poky-sanity.bbclass
/work/poky/meta-intel/meta-cedartrail/recipes-cdv-media/images/core-image-cdv-media.bb requires /work/poky/meta/recipes-sato/images/core-image-sato.bb
/work/poky/meta-yocto/recipes-core/tiny-init/tiny-init.bb RDEPENDS /work/poky/meta/recipes-core/busybox/busybox_1.20.2.bb
/work/poky/meta-intel/common/recipes-bsp/amt/lms_7.1.20.bb DEPENDS /work/poky/meta/recipes-devtools/autoconf/autoconf_2.69.bb
/work/poky/meta/classes/distrodata.bbclass includes /work/poky/meta-yocto/conf/distro/include/package_regex.inc
/work/poky/meta-intel/meta-sys940x/conf/machine/sys940x.conf requires /work/poky/meta/conf/machine/include/tune-atom.inc
[YOCTO #3387]
(Bitbake rev: 100502ef722bf19b6c125a5e017f31686ad18421)
Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
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) |
