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