recipe_sanity.bbclass 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. def __note(msg, d):
  2. bb.note("%s: recipe_sanity: %s" % (d.getVar("P", True), msg))
  3. __recipe_sanity_badruntimevars = "RDEPENDS RPROVIDES RRECOMMENDS RCONFLICTS"
  4. def bad_runtime_vars(cfgdata, d):
  5. if bb.data.inherits_class("native", d) or \
  6. bb.data.inherits_class("cross", d):
  7. return
  8. for var in d.getVar("__recipe_sanity_badruntimevars", True).split():
  9. val = d.getVar(var, 0)
  10. if val and val != cfgdata.get(var):
  11. __note("%s should be %s_${PN}" % (var, var), d)
  12. __recipe_sanity_reqvars = "DESCRIPTION"
  13. __recipe_sanity_reqdiffvars = ""
  14. def req_vars(cfgdata, d):
  15. for var in d.getVar("__recipe_sanity_reqvars", True).split():
  16. if not d.getVar(var, 0):
  17. __note("%s should be set" % var, d)
  18. for var in d.getVar("__recipe_sanity_reqdiffvars", True).split():
  19. val = d.getVar(var, 0)
  20. cfgval = cfgdata.get(var)
  21. if not val:
  22. __note("%s should be set" % var, d)
  23. elif val == cfgval:
  24. __note("%s should be defined to something other than default (%s)" % (var, cfgval), d)
  25. def var_renames_overwrite(cfgdata, d):
  26. renames = d.getVar("__recipe_sanity_renames", 0)
  27. if renames:
  28. for (key, newkey, oldvalue, newvalue) in renames:
  29. if oldvalue != newvalue and oldvalue != cfgdata.get(newkey):
  30. __note("rename of variable '%s' to '%s' overwrote existing value '%s' with '%s'." % (key, newkey, oldvalue, newvalue), d)
  31. def incorrect_nonempty_PACKAGES(cfgdata, d):
  32. if bb.data.inherits_class("native", d) or \
  33. bb.data.inherits_class("cross", d):
  34. if d.getVar("PACKAGES", True):
  35. return True
  36. def can_use_autotools_base(cfgdata, d):
  37. cfg = d.getVar("do_configure", True)
  38. if not bb.data.inherits_class("autotools", d):
  39. return False
  40. for i in ["autoreconf"] + ["%s_do_configure" % cls for cls in ["gnomebase", "gnome", "e", "autotools", "efl", "gpephone", "openmoko", "openmoko2", "xfce", "xlibs"]]:
  41. if cfg.find(i) != -1:
  42. return False
  43. for clsfile in d.getVar("__inherit_cache", 0):
  44. (base, _) = os.path.splitext(os.path.basename(clsfile))
  45. if cfg.find("%s_do_configure" % base) != -1:
  46. __note("autotools_base usage needs verification, spotted %s_do_configure" % base, d)
  47. return True
  48. def can_remove_FILESPATH(cfgdata, d):
  49. expected = cfgdata.get("FILESPATH")
  50. #expected = "${@':'.join([os.path.normpath(os.path.join(fp, p, o)) for fp in d.getVar('FILESPATHBASE', True).split(':') for p in d.getVar('FILESPATHPKG', True).split(':') for o in (d.getVar('OVERRIDES', True) + ':').split(':') if os.path.exists(os.path.join(fp, p, o))])}:${FILESDIR}"
  51. expectedpaths = d.expand(expected)
  52. unexpanded = d.getVar("FILESPATH", 0)
  53. filespath = d.getVar("FILESPATH", True).split(":")
  54. filespath = [os.path.normpath(f) for f in filespath if os.path.exists(f)]
  55. for fp in filespath:
  56. if not fp in expectedpaths:
  57. # __note("Path %s in FILESPATH not in the expected paths %s" %
  58. # (fp, expectedpaths), d)
  59. return False
  60. return expected != unexpanded
  61. def can_remove_FILESDIR(cfgdata, d):
  62. expected = cfgdata.get("FILESDIR")
  63. #expected = "${@bb.which(d.getVar('FILESPATH', True), '.')}"
  64. unexpanded = d.getVar("FILESDIR", 0)
  65. if unexpanded is None:
  66. return False
  67. expanded = os.path.normpath(d.getVar("FILESDIR", True))
  68. filespath = d.getVar("FILESPATH", True).split(":")
  69. filespath = [os.path.normpath(f) for f in filespath if os.path.exists(f)]
  70. return unexpanded != expected and \
  71. os.path.exists(expanded) and \
  72. (expanded in filespath or
  73. expanded == d.expand(expected))
  74. def can_remove_others(p, cfgdata, d):
  75. for k in ["S", "PV", "PN", "DESCRIPTION", "DEPENDS",
  76. "SECTION", "PACKAGES", "EXTRA_OECONF", "EXTRA_OEMAKE"]:
  77. #for k in cfgdata:
  78. unexpanded = d.getVar(k, 0)
  79. cfgunexpanded = cfgdata.get(k)
  80. if not cfgunexpanded:
  81. continue
  82. try:
  83. expanded = d.getVar(k, True)
  84. cfgexpanded = d.expand(cfgunexpanded)
  85. except bb.fetch.ParameterError:
  86. continue
  87. if unexpanded != cfgunexpanded and \
  88. cfgexpanded == expanded:
  89. __note("candidate for removal of %s" % k, d)
  90. bb.debug(1, "%s: recipe_sanity: cfg's '%s' and d's '%s' both expand to %s" %
  91. (p, cfgunexpanded, unexpanded, expanded))
  92. python do_recipe_sanity () {
  93. p = d.getVar("P", True)
  94. p = "%s %s %s" % (d.getVar("PN", True), d.getVar("PV", True), d.getVar("PR", True))
  95. sanitychecks = [
  96. (can_remove_FILESDIR, "candidate for removal of FILESDIR"),
  97. (can_remove_FILESPATH, "candidate for removal of FILESPATH"),
  98. #(can_use_autotools_base, "candidate for use of autotools_base"),
  99. (incorrect_nonempty_PACKAGES, "native or cross recipe with non-empty PACKAGES"),
  100. ]
  101. cfgdata = d.getVar("__recipe_sanity_cfgdata", 0)
  102. for (func, msg) in sanitychecks:
  103. if func(cfgdata, d):
  104. __note(msg, d)
  105. can_remove_others(p, cfgdata, d)
  106. var_renames_overwrite(cfgdata, d)
  107. req_vars(cfgdata, d)
  108. bad_runtime_vars(cfgdata, d)
  109. }
  110. do_recipe_sanity[nostamp] = "1"
  111. addtask recipe_sanity
  112. do_recipe_sanity_all[nostamp] = "1"
  113. do_recipe_sanity_all[recrdeptask] = "do_recipe_sanity_all do_recipe_sanity"
  114. do_recipe_sanity_all () {
  115. :
  116. }
  117. addtask recipe_sanity_all after do_recipe_sanity
  118. python recipe_sanity_eh () {
  119. d = e.data
  120. cfgdata = {}
  121. for k in d.keys():
  122. #for k in ["S", "PR", "PV", "PN", "DESCRIPTION", "LICENSE", "DEPENDS",
  123. # "SECTION"]:
  124. cfgdata[k] = d.getVar(k, 0)
  125. d.setVar("__recipe_sanity_cfgdata", cfgdata)
  126. #d.setVar("__recipe_sanity_cfgdata", d)
  127. # Sick, very sick..
  128. from bb.data_smart import DataSmart
  129. old = DataSmart.renameVar
  130. def myrename(self, key, newkey):
  131. oldvalue = self.getVar(newkey, 0)
  132. old(self, key, newkey)
  133. newvalue = self.getVar(newkey, 0)
  134. if oldvalue:
  135. renames = self.getVar("__recipe_sanity_renames", 0) or set()
  136. renames.add((key, newkey, oldvalue, newvalue))
  137. self.setVar("__recipe_sanity_renames", renames)
  138. DataSmart.renameVar = myrename
  139. }
  140. addhandler recipe_sanity_eh
  141. recipe_sanity_eh[eventmask] = "bb.event.ConfigParsed"