list-packageconfig-flags.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #!/usr/bin/env python3
  2. # This program is free software; you can redistribute it and/or modify
  3. # it under the terms of the GNU General Public License as published by
  4. # the Free Software Foundation; either version 2 of the License, or
  5. # (at your option) any later version.
  6. #
  7. # This program is distributed in the hope that it will be useful,
  8. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. # GNU General Public License for more details.
  11. #
  12. # You should have received a copy of the GNU General Public License
  13. # along with this program; if not, write to the Free Software Foundation.
  14. #
  15. # Copyright (C) 2013 Wind River Systems, Inc.
  16. # Copyright (C) 2014 Intel Corporation
  17. #
  18. # - list available recipes which have PACKAGECONFIG flags
  19. # - list available PACKAGECONFIG flags and all affected recipes
  20. # - list all recipes and PACKAGECONFIG information
  21. import sys
  22. import optparse
  23. import os
  24. scripts_path = os.path.abspath(os.path.dirname(os.path.abspath(sys.argv[0])))
  25. lib_path = os.path.abspath(scripts_path + '/../lib')
  26. sys.path = sys.path + [lib_path]
  27. import scriptpath
  28. # For importing the following modules
  29. bitbakepath = scriptpath.add_bitbake_lib_path()
  30. if not bitbakepath:
  31. sys.stderr.write("Unable to find bitbake by searching parent directory of this script or PATH\n")
  32. sys.exit(1)
  33. import bb.cache
  34. import bb.cooker
  35. import bb.providers
  36. import bb.tinfoil
  37. def get_fnlist(bbhandler, pkg_pn, preferred):
  38. ''' Get all recipe file names '''
  39. if preferred:
  40. (latest_versions, preferred_versions) = bb.providers.findProviders(bbhandler.config_data, bbhandler.cooker.recipecache, pkg_pn)
  41. fn_list = []
  42. for pn in sorted(pkg_pn):
  43. if preferred:
  44. fn_list.append(preferred_versions[pn][1])
  45. else:
  46. fn_list.extend(pkg_pn[pn])
  47. return fn_list
  48. def get_recipesdata(bbhandler, preferred):
  49. ''' Get data of all available recipes which have PACKAGECONFIG flags '''
  50. pkg_pn = bbhandler.cooker.recipecache.pkg_pn
  51. data_dict = {}
  52. for fn in get_fnlist(bbhandler, pkg_pn, preferred):
  53. data = bb.cache.Cache.loadDataFull(fn, bbhandler.cooker.collection.get_file_appends(fn), bbhandler.config_data)
  54. flags = data.getVarFlags("PACKAGECONFIG")
  55. flags.pop('doc', None)
  56. if flags:
  57. data_dict[fn] = data
  58. return data_dict
  59. def collect_pkgs(data_dict):
  60. ''' Collect available pkgs in which have PACKAGECONFIG flags '''
  61. # pkg_dict = {'pkg1': ['flag1', 'flag2',...]}
  62. pkg_dict = {}
  63. for fn in data_dict:
  64. pkgconfigflags = data_dict[fn].getVarFlags("PACKAGECONFIG")
  65. pkgconfigflags.pop('doc', None)
  66. pkgname = data_dict[fn].getVar("P", True)
  67. pkg_dict[pkgname] = sorted(pkgconfigflags.keys())
  68. return pkg_dict
  69. def collect_flags(pkg_dict):
  70. ''' Collect available PACKAGECONFIG flags and all affected pkgs '''
  71. # flag_dict = {'flag': ['pkg1', 'pkg2',...]}
  72. flag_dict = {}
  73. for pkgname, flaglist in pkg_dict.items():
  74. for flag in flaglist:
  75. if flag in flag_dict:
  76. flag_dict[flag].append(pkgname)
  77. else:
  78. flag_dict[flag] = [pkgname]
  79. return flag_dict
  80. def display_pkgs(pkg_dict):
  81. ''' Display available pkgs which have PACKAGECONFIG flags '''
  82. pkgname_len = len("RECIPE NAME") + 1
  83. for pkgname in pkg_dict:
  84. if pkgname_len < len(pkgname):
  85. pkgname_len = len(pkgname)
  86. pkgname_len += 1
  87. header = '%-*s%s' % (pkgname_len, str("RECIPE NAME"), str("PACKAGECONFIG FLAGS"))
  88. print(header)
  89. print(str("").ljust(len(header), '='))
  90. for pkgname in sorted(pkg_dict):
  91. print('%-*s%s' % (pkgname_len, pkgname, ' '.join(pkg_dict[pkgname])))
  92. def display_flags(flag_dict):
  93. ''' Display available PACKAGECONFIG flags and all affected pkgs '''
  94. flag_len = len("PACKAGECONFIG FLAG") + 5
  95. header = '%-*s%s' % (flag_len, str("PACKAGECONFIG FLAG"), str("RECIPE NAMES"))
  96. print(header)
  97. print(str("").ljust(len(header), '='))
  98. for flag in sorted(flag_dict):
  99. print('%-*s%s' % (flag_len, flag, ' '.join(sorted(flag_dict[flag]))))
  100. def display_all(data_dict):
  101. ''' Display all pkgs and PACKAGECONFIG information '''
  102. print(str("").ljust(50, '='))
  103. for fn in data_dict:
  104. print('%s' % data_dict[fn].getVar("P", True))
  105. print(fn)
  106. packageconfig = data_dict[fn].getVar("PACKAGECONFIG", True) or ''
  107. if packageconfig.strip() == '':
  108. packageconfig = 'None'
  109. print('PACKAGECONFIG %s' % packageconfig)
  110. for flag,flag_val in data_dict[fn].getVarFlags("PACKAGECONFIG").items():
  111. if flag == "doc":
  112. continue
  113. print('PACKAGECONFIG[%s] %s' % (flag, flag_val))
  114. print('')
  115. def main():
  116. pkg_dict = {}
  117. flag_dict = {}
  118. # Collect and validate input
  119. parser = optparse.OptionParser(
  120. description = "Lists recipes and PACKAGECONFIG flags. Without -a or -f, recipes and their available PACKAGECONFIG flags are listed.",
  121. usage = """
  122. %prog [options]""")
  123. parser.add_option("-f", "--flags",
  124. help = "list available PACKAGECONFIG flags and affected recipes",
  125. action="store_const", dest="listtype", const="flags", default="recipes")
  126. parser.add_option("-a", "--all",
  127. help = "list all recipes and PACKAGECONFIG information",
  128. action="store_const", dest="listtype", const="all")
  129. parser.add_option("-p", "--preferred-only",
  130. help = "where multiple recipe versions are available, list only the preferred version",
  131. action="store_true", dest="preferred", default=False)
  132. options, args = parser.parse_args(sys.argv)
  133. bbhandler = bb.tinfoil.Tinfoil()
  134. bbhandler.prepare()
  135. print("Gathering recipe data...")
  136. data_dict = get_recipesdata(bbhandler, options.preferred)
  137. if options.listtype == 'flags':
  138. pkg_dict = collect_pkgs(data_dict)
  139. flag_dict = collect_flags(pkg_dict)
  140. display_flags(flag_dict)
  141. elif options.listtype == 'recipes':
  142. pkg_dict = collect_pkgs(data_dict)
  143. display_pkgs(pkg_dict)
  144. elif options.listtype == 'all':
  145. display_all(data_dict)
  146. if __name__ == "__main__":
  147. main()