diff --git a/bitbake/lib/bb/parse/ast.py b/bitbake/lib/bb/parse/ast.py index 6441c5cf7c..d30b688965 100644 --- a/bitbake/lib/bb/parse/ast.py +++ b/bitbake/lib/bb/parse/ast.py @@ -211,10 +211,12 @@ class ExportFuncsNode(AstNode): def eval(self, data): + sentinel = " # Export function set\n" for func in self.n: calledfunc = self.classname + "_" + func - if data.getVar(func, False) and not data.getVarFlag(func, 'export_func', False): + basevar = data.getVar(func, False) + if basevar and sentinel not in basevar: continue if data.getVar(func, False): @@ -231,12 +233,11 @@ class ExportFuncsNode(AstNode): data.setVarFlag(func, "lineno", 1) if data.getVarFlag(calledfunc, "python", False): - data.setVar(func, " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True) + data.setVar(func, sentinel + " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True) else: if "-" in self.classname: bb.fatal("The classname %s contains a dash character and is calling an sh function %s using EXPORT_FUNCTIONS. Since a dash is illegal in sh function names, this cannot work, please rename the class or don't use EXPORT_FUNCTIONS." % (self.classname, calledfunc)) - data.setVar(func, " " + calledfunc + "\n", parsing=True) - data.setVarFlag(func, 'export_func', '1') + data.setVar(func, sentinel + " " + calledfunc + "\n", parsing=True) class AddTaskNode(AstNode): def __init__(self, filename, lineno, func, before, after): diff --git a/bitbake/lib/bb/tests/parse.py b/bitbake/lib/bb/tests/parse.py index 304bbbe222..72d1962e7e 100644 --- a/bitbake/lib/bb/tests/parse.py +++ b/bitbake/lib/bb/tests/parse.py @@ -243,3 +243,101 @@ unset A[flag@.service] with self.assertRaises(bb.parse.ParseError): d = bb.parse.handle(f.name, self.d)[''] + export_function_recipe = """ +inherit someclass +""" + + export_function_recipe2 = """ +inherit someclass + +do_compile () { + false +} + +python do_compilepython () { + bb.note("Something else") +} + +""" + export_function_class = """ +someclass_do_compile() { + true +} + +python someclass_do_compilepython () { + bb.note("Something") +} + +EXPORT_FUNCTIONS do_compile do_compilepython +""" + + export_function_class2 = """ +secondclass_do_compile() { + true +} + +python secondclass_do_compilepython () { + bb.note("Something") +} + +EXPORT_FUNCTIONS do_compile do_compilepython +""" + + def test_parse_export_functions(self): + def check_function_flags(d): + self.assertEqual(d.getVarFlag("do_compile", "func"), 1) + self.assertEqual(d.getVarFlag("do_compilepython", "func"), 1) + self.assertEqual(d.getVarFlag("do_compile", "python"), None) + self.assertEqual(d.getVarFlag("do_compilepython", "python"), "1") + + with tempfile.TemporaryDirectory() as tempdir: + self.d.setVar("__bbclasstype", "recipe") + recipename = tempdir + "/recipe.bb" + os.makedirs(tempdir + "/classes") + with open(tempdir + "/classes/someclass.bbclass", "w") as f: + f.write(self.export_function_class) + f.flush() + with open(tempdir + "/classes/secondclass.bbclass", "w") as f: + f.write(self.export_function_class2) + f.flush() + + with open(recipename, "w") as f: + f.write(self.export_function_recipe) + f.flush() + os.chdir(tempdir) + d = bb.parse.handle(recipename, bb.data.createCopy(self.d))[''] + self.assertIn("someclass_do_compile", d.getVar("do_compile")) + self.assertIn("someclass_do_compilepython", d.getVar("do_compilepython")) + check_function_flags(d) + + recipename2 = tempdir + "/recipe2.bb" + with open(recipename2, "w") as f: + f.write(self.export_function_recipe2) + f.flush() + + d = bb.parse.handle(recipename2, bb.data.createCopy(self.d))[''] + self.assertNotIn("someclass_do_compile", d.getVar("do_compile")) + self.assertNotIn("someclass_do_compilepython", d.getVar("do_compilepython")) + self.assertIn("false", d.getVar("do_compile")) + self.assertIn("else", d.getVar("do_compilepython")) + check_function_flags(d) + + with open(recipename, "a+") as f: + f.write("\ninherit secondclass\n") + f.flush() + with open(recipename2, "a+") as f: + f.write("\ninherit secondclass\n") + f.flush() + + d = bb.parse.handle(recipename, bb.data.createCopy(self.d))[''] + self.assertIn("secondclass_do_compile", d.getVar("do_compile")) + self.assertIn("secondclass_do_compilepython", d.getVar("do_compilepython")) + check_function_flags(d) + + d = bb.parse.handle(recipename2, bb.data.createCopy(self.d))[''] + self.assertNotIn("someclass_do_compile", d.getVar("do_compile")) + self.assertNotIn("someclass_do_compilepython", d.getVar("do_compilepython")) + self.assertIn("false", d.getVar("do_compile")) + self.assertIn("else", d.getVar("do_compilepython")) + check_function_flags(d) +