Handling optional module packaging
Many pieces of software split functionality out into optional modules (or plugins), and which of these plugins are built may depend on configuration options. To avoid having to duplicate the logic for determining which modules are available in your recipe or packaging each module by hand, the build system provides functionality to handle module packaging dynamically.
Packaging
Firstly, you need to ensure that the module packaging actually gets done. This is accomplished using the do_split_packages function within the populate_packages_prepend python function in your recipe; this searches for a pattern of files or directories under a specified path and creates a package for each one it finds, by appending to the PACKAGES variable and setting the appropriate values for FILES_packagename, RDEPENDS_packagename, DESCRIPTION_packagename etc. Here is an example from the recipe for lighttpd:
python populate_packages_prepend () { lighttpd_libdir = d.expand('${libdir}') do_split_packages(d, lighttpd_libdir, '^mod_(.*)\.so$', 'lighttpd-module-%s', 'Lighttpd module for %s', extra_depends=) }
In the above example a number of things are specified in the call to do_split_packages: a directory in which to search (within the files installed by your recipe via do_install), a regular expression to match module files in that directory - note the parentheses () which mark the part of the expression from which the module name should be derived; a pattern to use for the package names, a description for each package, and an empty string for extra_depends which disables the default dependency on the main lighttpd package. Thus, if a file in ${libdir} called mod_alias.so is found, a package called lighttpd-module-alias will be created for it, with DESCRIPTION set to "Lighttpd module for alias".
Often packaging modules is as simple as above; however, there are more advanced options you can supply to do_split_packages to modify its behaviour, and if you need to you can add more logic by specifying a hook function to be called for each package. It is also perfectly acceptable to call do_split_packages multiple times if you have more than one set of modules to package.
For some other examples of do_split_packages usage, see meta/recipes-connectivity/connman/connman.inc and meta/classes/kernel.bbclass.
do_split_packages reference
Mandatory arguments
- root
- the path in which to search
- file_regex
- regular expression to match searched files. Use parentheses () to mark the part of this expression that should be used to derive the module name (to be substituted where %s is used in other function arguments as noted below)
- output_pattern
- pattern to use for the package names. Must include %s.
- description
- description to set for each package. Must include %s.
Optional arguments
- postinst
- postinstall script to use for all packages (as a string)
- recursive
- True to perform a recursive search - default False
- hook
- a hook function to be called for every match. The function will be called with the following arguments (in the order listed):
- f
- full path to the file/directory match
- pkg
- the package name
- file_regex
- as above
- output_pattern
- as above
- modulename
- the module name derived using file_regex
- extra_depends
- extra runtime dependencies (RDEPENDS) to be set for all packages. The default value of None causes a dependency on the main package (${PN}) - if you do not want this, pass for this parameter.
- aux_files_pattern
- extra item(s) to be added to FILES for each package. Can be a single string item or a list of strings for multiple items. Must include %s.
- postrm
- postrm script to use for all packages (as a string)
- allow_dirs
- True to allow directories to be matched - default False
- prepend
- if True, prepend created packages to PACKAGES instead of the default False which appends them
- match_path
- match file_regex on the whole relative path to the root rather than just the file name
- aux_files_pattern_verbatim
- extra item(s) to be added to FILES for each package, using the actual derived module name rather than converting it to something legal for a package name. Can be a single string item or a list of strings for multiple items. Must include %s.
- allow_links
- True to allow symlinks to be matched - default False
Satisfying dependencies
The second step is to ensure that any dependencies from other recipes on optional modules are satisfied by your recipe. To do this, use PACKAGES_DYNAMIC. Here is an example, again from the lighttpd recipe:
PACKAGES_DYNAMIC = "lighttpd-module-*"
The name here can of course be anything - here "lighttpd-module-" is specified as the prefix, and the wildcard * ensures that any RDEPENDS / RRECOMMENDS on a package name starting with that prefix will be satisfied, at least at build time. If you are using do_split_packages as described above, the value you put in PACKAGES_DYNAMIC should correspond to the name pattern specified in the call to do_split_packages.
Note: PACKAGES_DYNAMIC is simply a promise in order to satisfy dependencies, it does not actually do anything else by itself. If an RDEPENDS relationship (a hard runtime dependency) of another package is satisfied at build time via PACKAGES_DYNAMIC, but a package with that name is never actually produced, then the other package will be broken, and if you attempt to include it in an image you will get a dependency failure from the packaging system during do_rootfs. Typically, if there is a chance that such a situation will arise, and the package not being created is valid and not cause for an error, then RRECOMMENDS (a soft runtime dependency) would be used instead of RDEPENDS.