recipetool: create: add additional extension mechanisms

Add a means of extending the dependency extraction for autotools and
cmake.

Note: in order to have this work, you need to have an __init__.py in the
lib/recipetool directory within your layer along with the module
implementing the handlers, and the __init__.py needs to contain:

  # Enable other layers to have modules in the same named directory
  from pkgutil import extend_path
  __path__ = extend_path(__path__, __name__)

(From OE-Core rev: 915dea9f89cd737e5ba167c384e8d314c5c23c49)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Paul Eggleton 2016-02-19 22:39:01 +13:00 committed by Richard Purdie
parent b2d44729e9
commit 7b6e5b025e
2 changed files with 113 additions and 8 deletions

View File

@ -22,6 +22,12 @@ from recipetool.create import RecipeHandler, validate_pv
logger = logging.getLogger('recipetool')
tinfoil = None
plugins = None
def plugin_init(pluginlist):
# Take a reference to the list so we can use it later
global plugins
plugins = pluginlist
def tinfoil_init(instance):
global tinfoil
@ -48,6 +54,13 @@ class CmakeRecipeHandler(RecipeHandler):
@staticmethod
def extract_cmake_deps(outlines, srctree, extravalues, cmakelistsfile=None):
# Find all plugins that want to register handlers
logger.debug('Loading cmake handlers')
handlers = []
for plugin in plugins:
if hasattr(plugin, 'register_cmake_handlers'):
plugin.register_cmake_handlers(handlers)
values = {}
inherits = []
@ -152,6 +165,9 @@ class CmakeRecipeHandler(RecipeHandler):
with open(fn, 'r') as f:
for line in f:
line = line.strip()
for handler in handlers:
if handler.process_line(srctree, fn, line, libdeps, pcdeps, deps, outlines, inherits, values):
continue
res = include_re.match(line)
if res:
includefn = bb.utils.which(':'.join(searchpaths), res.group(1))
@ -194,7 +210,15 @@ class CmakeRecipeHandler(RecipeHandler):
if res:
origpkg = res.group(1)
pkg = interpret_value(origpkg.lower())
if pkg == 'gettext':
found = False
for handler in handlers:
if handler.process_findpackage(srctree, fn, pkg, deps, outlines, inherits, values):
logger.debug('Mapped CMake package %s via handler %s' % (pkg, handler.__class__.__name__))
found = True
break
if found:
continue
elif pkg == 'gettext':
inherits.append('gettext')
elif pkg == 'perl':
inherits.append('perlnative')
@ -207,6 +231,7 @@ class CmakeRecipeHandler(RecipeHandler):
else:
dep = cmake_pkgmap.get(pkg, None)
if dep:
logger.debug('Mapped CMake package %s to recipe %s via internal list' % (pkg, dep))
deps.append(dep)
elif dep is None:
unmappedpkgs.append(origpkg)
@ -236,11 +261,39 @@ class CmakeRecipeHandler(RecipeHandler):
RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data)
for handler in handlers:
handler.post_process(srctree, libdeps, pcdeps, deps, outlines, inherits, values)
if inherits:
values['inherit'] = ' '.join(list(set(inherits)))
return values
class CmakeExtensionHandler(object):
'''Base class for CMake extension handlers'''
def process_line(self, srctree, fn, line, libdeps, pcdeps, deps, outlines, inherits, values):
'''
Handle a line parsed out of an CMake file.
Return True if you've completely handled the passed in line, otherwise return False.
'''
return False
def process_findpackage(self, srctree, fn, pkg, deps, outlines, inherits, values):
'''
Handle a find_package package parsed out of a CMake file.
Return True if you've completely handled the passed in package, otherwise return False.
'''
return False
def post_process(self, srctree, fn, pkg, deps, outlines, inherits, values):
'''
Apply any desired post-processing on the output
'''
return
class SconsRecipeHandler(RecipeHandler):
def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
if 'buildsystem' in handled:
@ -255,6 +308,7 @@ class SconsRecipeHandler(RecipeHandler):
return True
return False
class QmakeRecipeHandler(RecipeHandler):
def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
if 'buildsystem' in handled:
@ -266,6 +320,7 @@ class QmakeRecipeHandler(RecipeHandler):
return True
return False
class AutotoolsRecipeHandler(RecipeHandler):
def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
if 'buildsystem' in handled:
@ -322,6 +377,13 @@ class AutotoolsRecipeHandler(RecipeHandler):
def extract_autotools_deps(outlines, srctree, extravalues=None, acfile=None):
import shlex
# Find all plugins that want to register handlers
logger.debug('Loading autotools handlers')
handlers = []
for plugin in plugins:
if hasattr(plugin, 'register_autotools_handlers'):
plugin.register_autotools_handlers(handlers)
values = {}
inherits = []
@ -384,6 +446,9 @@ class AutotoolsRecipeHandler(RecipeHandler):
unmapped = []
def process_macro(keyword, value):
for handler in handlers:
if handler.process_macro(srctree, keyword, value, process_value, libdeps, pcdeps, deps, outlines, inherits, values):
return
if keyword == 'PKG_CHECK_MODULES':
res = pkg_re.search(value)
if res:
@ -409,6 +474,9 @@ class AutotoolsRecipeHandler(RecipeHandler):
if res:
for prog in shlex.split(res.group(1)):
prog = prog.split()[0]
for handler in handlers:
if handler.process_prog(srctree, keyword, value, prog, deps, outlines, inherits, values):
return
progclass = progclassmap.get(prog, None)
if progclass:
inherits.append(progclass)
@ -537,6 +605,10 @@ class AutotoolsRecipeHandler(RecipeHandler):
'AM_INIT_AUTOMAKE',
'define(',
]
for handler in handlers:
handler.extend_keywords(keywords)
for srcfile in srcfiles:
nesting = 0
in_keyword = ''
@ -581,12 +653,44 @@ class AutotoolsRecipeHandler(RecipeHandler):
RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data)
for handler in handlers:
handler.post_process(srctree, libdeps, pcdeps, deps, outlines, inherits, values)
if inherits:
values['inherit'] = ' '.join(list(set(inherits)))
return values
class AutotoolsExtensionHandler(object):
'''Base class for Autotools extension handlers'''
def process_macro(self, srctree, keyword, value, process_value, libdeps, pcdeps, deps, outlines, inherits, values):
'''
Handle a macro parsed out of an autotools file. Note that if you want this to be called
for any macro other than the ones AutotoolsRecipeHandler already looks for, you'll need
to add it to the keywords list in extend_keywords().
Return True if you've completely handled the passed in macro, otherwise return False.
'''
return False
def extend_keywords(self, keywords):
'''Adds keywords to be recognised by the parser (so that you get a call to process_macro)'''
return
def process_prog(self, srctree, keyword, value, prog, deps, outlines, inherits, values):
'''
Handle an AC_PATH_PROG, AC_CHECK_PROG etc. line
Return True if you've completely handled the passed in macro, otherwise return False.
'''
return False
def post_process(self, srctree, fn, pkg, deps, outlines, inherits, values):
'''
Apply any desired post-processing on the output
'''
return
class MakefileRecipeHandler(RecipeHandler):
def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
if 'buildsystem' in handled:
@ -703,11 +807,12 @@ class SpecFileRecipeHandler(RecipeHandler):
break
def register_recipe_handlers(handlers):
# These are in a specific order so that the right one is detected first
handlers.append(CmakeRecipeHandler())
handlers.append(AutotoolsRecipeHandler())
handlers.append(SconsRecipeHandler())
handlers.append(QmakeRecipeHandler())
handlers.append(MakefileRecipeHandler())
# Set priorities with some gaps so that other plugins can insert
# their own handlers (so avoid changing these numbers)
handlers.append((CmakeRecipeHandler(), 50))
handlers.append((AutotoolsRecipeHandler(), 40))
handlers.append((SconsRecipeHandler(), 30))
handlers.append((QmakeRecipeHandler(), 20))
handlers.append((MakefileRecipeHandler(), 10))
handlers.append((VersionFileRecipeHandler(), -1))
handlers.append((SpecFileRecipeHandler(), -1))

View File

@ -716,4 +716,4 @@ def has_non_literals(value):
def register_recipe_handlers(handlers):
# We need to make sure this is ahead of the makefile fallback handler
handlers.insert(0, PythonRecipeHandler())
handlers.append((PythonRecipeHandler(), 70))