diff options
| author | Paul Eggleton <paul.eggleton@linux.intel.com> | 2016-02-19 22:39:01 +1300 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-02-21 09:32:43 +0000 |
| commit | 7b6e5b025e2ba8a91be01d61f7b9093f4729e8cc (patch) | |
| tree | abd08b740a3097191827340b639b16722088bbf8 /scripts/lib/recipetool/create_buildsys.py | |
| parent | b2d44729e9c3c600203c89eaa92bda264121780d (diff) | |
| download | poky-7b6e5b025e2ba8a91be01d61f7b9093f4729e8cc.tar.gz | |
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>
Diffstat (limited to 'scripts/lib/recipetool/create_buildsys.py')
| -rw-r--r-- | scripts/lib/recipetool/create_buildsys.py | 119 |
1 files changed, 112 insertions, 7 deletions
diff --git a/scripts/lib/recipetool/create_buildsys.py b/scripts/lib/recipetool/create_buildsys.py index 4d11e0401e..1a06cac8c5 100644 --- a/scripts/lib/recipetool/create_buildsys.py +++ b/scripts/lib/recipetool/create_buildsys.py | |||
| @@ -22,6 +22,12 @@ from recipetool.create import RecipeHandler, validate_pv | |||
| 22 | logger = logging.getLogger('recipetool') | 22 | logger = logging.getLogger('recipetool') |
| 23 | 23 | ||
| 24 | tinfoil = None | 24 | tinfoil = None |
| 25 | plugins = None | ||
| 26 | |||
| 27 | def plugin_init(pluginlist): | ||
| 28 | # Take a reference to the list so we can use it later | ||
| 29 | global plugins | ||
| 30 | plugins = pluginlist | ||
| 25 | 31 | ||
| 26 | def tinfoil_init(instance): | 32 | def tinfoil_init(instance): |
| 27 | global tinfoil | 33 | global tinfoil |
| @@ -48,6 +54,13 @@ class CmakeRecipeHandler(RecipeHandler): | |||
| 48 | 54 | ||
| 49 | @staticmethod | 55 | @staticmethod |
| 50 | def extract_cmake_deps(outlines, srctree, extravalues, cmakelistsfile=None): | 56 | def extract_cmake_deps(outlines, srctree, extravalues, cmakelistsfile=None): |
| 57 | # Find all plugins that want to register handlers | ||
| 58 | logger.debug('Loading cmake handlers') | ||
| 59 | handlers = [] | ||
| 60 | for plugin in plugins: | ||
| 61 | if hasattr(plugin, 'register_cmake_handlers'): | ||
| 62 | plugin.register_cmake_handlers(handlers) | ||
| 63 | |||
| 51 | values = {} | 64 | values = {} |
| 52 | inherits = [] | 65 | inherits = [] |
| 53 | 66 | ||
| @@ -152,6 +165,9 @@ class CmakeRecipeHandler(RecipeHandler): | |||
| 152 | with open(fn, 'r') as f: | 165 | with open(fn, 'r') as f: |
| 153 | for line in f: | 166 | for line in f: |
| 154 | line = line.strip() | 167 | line = line.strip() |
| 168 | for handler in handlers: | ||
| 169 | if handler.process_line(srctree, fn, line, libdeps, pcdeps, deps, outlines, inherits, values): | ||
| 170 | continue | ||
| 155 | res = include_re.match(line) | 171 | res = include_re.match(line) |
| 156 | if res: | 172 | if res: |
| 157 | includefn = bb.utils.which(':'.join(searchpaths), res.group(1)) | 173 | includefn = bb.utils.which(':'.join(searchpaths), res.group(1)) |
| @@ -194,7 +210,15 @@ class CmakeRecipeHandler(RecipeHandler): | |||
| 194 | if res: | 210 | if res: |
| 195 | origpkg = res.group(1) | 211 | origpkg = res.group(1) |
| 196 | pkg = interpret_value(origpkg.lower()) | 212 | pkg = interpret_value(origpkg.lower()) |
| 197 | if pkg == 'gettext': | 213 | found = False |
| 214 | for handler in handlers: | ||
| 215 | if handler.process_findpackage(srctree, fn, pkg, deps, outlines, inherits, values): | ||
| 216 | logger.debug('Mapped CMake package %s via handler %s' % (pkg, handler.__class__.__name__)) | ||
| 217 | found = True | ||
| 218 | break | ||
| 219 | if found: | ||
| 220 | continue | ||
| 221 | elif pkg == 'gettext': | ||
| 198 | inherits.append('gettext') | 222 | inherits.append('gettext') |
| 199 | elif pkg == 'perl': | 223 | elif pkg == 'perl': |
| 200 | inherits.append('perlnative') | 224 | inherits.append('perlnative') |
| @@ -207,6 +231,7 @@ class CmakeRecipeHandler(RecipeHandler): | |||
| 207 | else: | 231 | else: |
| 208 | dep = cmake_pkgmap.get(pkg, None) | 232 | dep = cmake_pkgmap.get(pkg, None) |
| 209 | if dep: | 233 | if dep: |
| 234 | logger.debug('Mapped CMake package %s to recipe %s via internal list' % (pkg, dep)) | ||
| 210 | deps.append(dep) | 235 | deps.append(dep) |
| 211 | elif dep is None: | 236 | elif dep is None: |
| 212 | unmappedpkgs.append(origpkg) | 237 | unmappedpkgs.append(origpkg) |
| @@ -236,11 +261,39 @@ class CmakeRecipeHandler(RecipeHandler): | |||
| 236 | 261 | ||
| 237 | RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data) | 262 | RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data) |
| 238 | 263 | ||
| 264 | for handler in handlers: | ||
| 265 | handler.post_process(srctree, libdeps, pcdeps, deps, outlines, inherits, values) | ||
| 266 | |||
| 239 | if inherits: | 267 | if inherits: |
| 240 | values['inherit'] = ' '.join(list(set(inherits))) | 268 | values['inherit'] = ' '.join(list(set(inherits))) |
| 241 | 269 | ||
| 242 | return values | 270 | return values |
| 243 | 271 | ||
| 272 | |||
| 273 | class CmakeExtensionHandler(object): | ||
| 274 | '''Base class for CMake extension handlers''' | ||
| 275 | def process_line(self, srctree, fn, line, libdeps, pcdeps, deps, outlines, inherits, values): | ||
| 276 | ''' | ||
| 277 | Handle a line parsed out of an CMake file. | ||
| 278 | Return True if you've completely handled the passed in line, otherwise return False. | ||
| 279 | ''' | ||
| 280 | return False | ||
| 281 | |||
| 282 | def process_findpackage(self, srctree, fn, pkg, deps, outlines, inherits, values): | ||
| 283 | ''' | ||
| 284 | Handle a find_package package parsed out of a CMake file. | ||
| 285 | Return True if you've completely handled the passed in package, otherwise return False. | ||
| 286 | ''' | ||
| 287 | return False | ||
| 288 | |||
| 289 | def post_process(self, srctree, fn, pkg, deps, outlines, inherits, values): | ||
| 290 | ''' | ||
| 291 | Apply any desired post-processing on the output | ||
| 292 | ''' | ||
| 293 | return | ||
| 294 | |||
| 295 | |||
| 296 | |||
| 244 | class SconsRecipeHandler(RecipeHandler): | 297 | class SconsRecipeHandler(RecipeHandler): |
| 245 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): | 298 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): |
| 246 | if 'buildsystem' in handled: | 299 | if 'buildsystem' in handled: |
| @@ -255,6 +308,7 @@ class SconsRecipeHandler(RecipeHandler): | |||
| 255 | return True | 308 | return True |
| 256 | return False | 309 | return False |
| 257 | 310 | ||
| 311 | |||
| 258 | class QmakeRecipeHandler(RecipeHandler): | 312 | class QmakeRecipeHandler(RecipeHandler): |
| 259 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): | 313 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): |
| 260 | if 'buildsystem' in handled: | 314 | if 'buildsystem' in handled: |
| @@ -266,6 +320,7 @@ class QmakeRecipeHandler(RecipeHandler): | |||
| 266 | return True | 320 | return True |
| 267 | return False | 321 | return False |
| 268 | 322 | ||
| 323 | |||
| 269 | class AutotoolsRecipeHandler(RecipeHandler): | 324 | class AutotoolsRecipeHandler(RecipeHandler): |
| 270 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): | 325 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): |
| 271 | if 'buildsystem' in handled: | 326 | if 'buildsystem' in handled: |
| @@ -322,6 +377,13 @@ class AutotoolsRecipeHandler(RecipeHandler): | |||
| 322 | def extract_autotools_deps(outlines, srctree, extravalues=None, acfile=None): | 377 | def extract_autotools_deps(outlines, srctree, extravalues=None, acfile=None): |
| 323 | import shlex | 378 | import shlex |
| 324 | 379 | ||
| 380 | # Find all plugins that want to register handlers | ||
| 381 | logger.debug('Loading autotools handlers') | ||
| 382 | handlers = [] | ||
| 383 | for plugin in plugins: | ||
| 384 | if hasattr(plugin, 'register_autotools_handlers'): | ||
| 385 | plugin.register_autotools_handlers(handlers) | ||
| 386 | |||
| 325 | values = {} | 387 | values = {} |
| 326 | inherits = [] | 388 | inherits = [] |
| 327 | 389 | ||
| @@ -384,6 +446,9 @@ class AutotoolsRecipeHandler(RecipeHandler): | |||
| 384 | unmapped = [] | 446 | unmapped = [] |
| 385 | 447 | ||
| 386 | def process_macro(keyword, value): | 448 | def process_macro(keyword, value): |
| 449 | for handler in handlers: | ||
| 450 | if handler.process_macro(srctree, keyword, value, process_value, libdeps, pcdeps, deps, outlines, inherits, values): | ||
| 451 | return | ||
| 387 | if keyword == 'PKG_CHECK_MODULES': | 452 | if keyword == 'PKG_CHECK_MODULES': |
| 388 | res = pkg_re.search(value) | 453 | res = pkg_re.search(value) |
| 389 | if res: | 454 | if res: |
| @@ -409,6 +474,9 @@ class AutotoolsRecipeHandler(RecipeHandler): | |||
| 409 | if res: | 474 | if res: |
| 410 | for prog in shlex.split(res.group(1)): | 475 | for prog in shlex.split(res.group(1)): |
| 411 | prog = prog.split()[0] | 476 | prog = prog.split()[0] |
| 477 | for handler in handlers: | ||
| 478 | if handler.process_prog(srctree, keyword, value, prog, deps, outlines, inherits, values): | ||
| 479 | return | ||
| 412 | progclass = progclassmap.get(prog, None) | 480 | progclass = progclassmap.get(prog, None) |
| 413 | if progclass: | 481 | if progclass: |
| 414 | inherits.append(progclass) | 482 | inherits.append(progclass) |
| @@ -537,6 +605,10 @@ class AutotoolsRecipeHandler(RecipeHandler): | |||
| 537 | 'AM_INIT_AUTOMAKE', | 605 | 'AM_INIT_AUTOMAKE', |
| 538 | 'define(', | 606 | 'define(', |
| 539 | ] | 607 | ] |
| 608 | |||
| 609 | for handler in handlers: | ||
| 610 | handler.extend_keywords(keywords) | ||
| 611 | |||
| 540 | for srcfile in srcfiles: | 612 | for srcfile in srcfiles: |
| 541 | nesting = 0 | 613 | nesting = 0 |
| 542 | in_keyword = '' | 614 | in_keyword = '' |
| @@ -581,12 +653,44 @@ class AutotoolsRecipeHandler(RecipeHandler): | |||
| 581 | 653 | ||
| 582 | RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data) | 654 | RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data) |
| 583 | 655 | ||
| 656 | for handler in handlers: | ||
| 657 | handler.post_process(srctree, libdeps, pcdeps, deps, outlines, inherits, values) | ||
| 658 | |||
| 584 | if inherits: | 659 | if inherits: |
| 585 | values['inherit'] = ' '.join(list(set(inherits))) | 660 | values['inherit'] = ' '.join(list(set(inherits))) |
| 586 | 661 | ||
| 587 | return values | 662 | return values |
| 588 | 663 | ||
| 589 | 664 | ||
| 665 | class AutotoolsExtensionHandler(object): | ||
| 666 | '''Base class for Autotools extension handlers''' | ||
| 667 | def process_macro(self, srctree, keyword, value, process_value, libdeps, pcdeps, deps, outlines, inherits, values): | ||
| 668 | ''' | ||
| 669 | Handle a macro parsed out of an autotools file. Note that if you want this to be called | ||
| 670 | for any macro other than the ones AutotoolsRecipeHandler already looks for, you'll need | ||
| 671 | to add it to the keywords list in extend_keywords(). | ||
| 672 | Return True if you've completely handled the passed in macro, otherwise return False. | ||
| 673 | ''' | ||
| 674 | return False | ||
| 675 | |||
| 676 | def extend_keywords(self, keywords): | ||
| 677 | '''Adds keywords to be recognised by the parser (so that you get a call to process_macro)''' | ||
| 678 | return | ||
| 679 | |||
| 680 | def process_prog(self, srctree, keyword, value, prog, deps, outlines, inherits, values): | ||
| 681 | ''' | ||
| 682 | Handle an AC_PATH_PROG, AC_CHECK_PROG etc. line | ||
| 683 | Return True if you've completely handled the passed in macro, otherwise return False. | ||
| 684 | ''' | ||
| 685 | return False | ||
| 686 | |||
| 687 | def post_process(self, srctree, fn, pkg, deps, outlines, inherits, values): | ||
| 688 | ''' | ||
| 689 | Apply any desired post-processing on the output | ||
| 690 | ''' | ||
| 691 | return | ||
| 692 | |||
| 693 | |||
| 590 | class MakefileRecipeHandler(RecipeHandler): | 694 | class MakefileRecipeHandler(RecipeHandler): |
| 591 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): | 695 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): |
| 592 | if 'buildsystem' in handled: | 696 | if 'buildsystem' in handled: |
| @@ -703,11 +807,12 @@ class SpecFileRecipeHandler(RecipeHandler): | |||
| 703 | break | 807 | break |
| 704 | 808 | ||
| 705 | def register_recipe_handlers(handlers): | 809 | def register_recipe_handlers(handlers): |
| 706 | # These are in a specific order so that the right one is detected first | 810 | # Set priorities with some gaps so that other plugins can insert |
| 707 | handlers.append(CmakeRecipeHandler()) | 811 | # their own handlers (so avoid changing these numbers) |
| 708 | handlers.append(AutotoolsRecipeHandler()) | 812 | handlers.append((CmakeRecipeHandler(), 50)) |
| 709 | handlers.append(SconsRecipeHandler()) | 813 | handlers.append((AutotoolsRecipeHandler(), 40)) |
| 710 | handlers.append(QmakeRecipeHandler()) | 814 | handlers.append((SconsRecipeHandler(), 30)) |
| 711 | handlers.append(MakefileRecipeHandler()) | 815 | handlers.append((QmakeRecipeHandler(), 20)) |
| 816 | handlers.append((MakefileRecipeHandler(), 10)) | ||
| 712 | handlers.append((VersionFileRecipeHandler(), -1)) | 817 | handlers.append((VersionFileRecipeHandler(), -1)) |
| 713 | handlers.append((SpecFileRecipeHandler(), -1)) | 818 | handlers.append((SpecFileRecipeHandler(), -1)) |
