Handling optional module packaging

From Yocto Project
Revision as of 10:04, 22 August 2012 by PaulEggleton (talk | contribs)
Jump to navigationJump to search

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 automatically.

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.

do_split_packages reference

    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.
    postinst       -- postinstall script to use for all packages (as a
                      string)
    recursive      -- perform a recursive search
    hook           -- a hook function to be called for each package
    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. Must include %s.
    postrm         -- postrm script to use for all packages (as a string)
    allow_dirs     -- allow directories to be matched
    prepend        -- if True, prepend created packages to PACKAGES instead
                      of appending 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. Must include %s.
    allow_links    -- allow symlinks to be matched
 

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.