268 lines
11 KiB
ReStructuredText
268 lines
11 KiB
ReStructuredText
|
.. SPDX-License-Identifier: CC-BY-SA-2.0-UK
|
||
|
|
||
|
Working With Libraries
|
||
|
**********************
|
||
|
|
||
|
Libraries are an integral part of your system. This section describes
|
||
|
some common practices you might find helpful when working with libraries
|
||
|
to build your system:
|
||
|
|
||
|
- :ref:`How to include static library files
|
||
|
<dev-manual/libraries:including static library files>`
|
||
|
|
||
|
- :ref:`How to use the Multilib feature to combine multiple versions of
|
||
|
library files into a single image
|
||
|
<dev-manual/libraries:combining multiple versions of library files into one image>`
|
||
|
|
||
|
- :ref:`How to install multiple versions of the same library in parallel on
|
||
|
the same system
|
||
|
<dev-manual/libraries:installing multiple versions of the same library>`
|
||
|
|
||
|
Including Static Library Files
|
||
|
==============================
|
||
|
|
||
|
If you are building a library and the library offers static linking, you
|
||
|
can control which static library files (``*.a`` files) get included in
|
||
|
the built library.
|
||
|
|
||
|
The :term:`PACKAGES` and
|
||
|
:term:`FILES:* <FILES>` variables in the
|
||
|
``meta/conf/bitbake.conf`` configuration file define how files installed
|
||
|
by the :ref:`ref-tasks-install` task are packaged. By default, the :term:`PACKAGES`
|
||
|
variable includes ``${PN}-staticdev``, which represents all static
|
||
|
library files.
|
||
|
|
||
|
.. note::
|
||
|
|
||
|
Some previously released versions of the Yocto Project defined the
|
||
|
static library files through ``${PN}-dev``.
|
||
|
|
||
|
Following is part of the BitBake configuration file, where you can see
|
||
|
how the static library files are defined::
|
||
|
|
||
|
PACKAGE_BEFORE_PN ?= ""
|
||
|
PACKAGES = "${PN}-src ${PN}-dbg ${PN}-staticdev ${PN}-dev ${PN}-doc ${PN}-locale ${PACKAGE_BEFORE_PN} ${PN}"
|
||
|
PACKAGES_DYNAMIC = "^${PN}-locale-.*"
|
||
|
FILES = ""
|
||
|
|
||
|
FILES:${PN} = "${bindir}/* ${sbindir}/* ${libexecdir}/* ${libdir}/lib*${SOLIBS} \
|
||
|
${sysconfdir} ${sharedstatedir} ${localstatedir} \
|
||
|
${base_bindir}/* ${base_sbindir}/* \
|
||
|
${base_libdir}/*${SOLIBS} \
|
||
|
${base_prefix}/lib/udev ${prefix}/lib/udev \
|
||
|
${base_libdir}/udev ${libdir}/udev \
|
||
|
${datadir}/${BPN} ${libdir}/${BPN}/* \
|
||
|
${datadir}/pixmaps ${datadir}/applications \
|
||
|
${datadir}/idl ${datadir}/omf ${datadir}/sounds \
|
||
|
${libdir}/bonobo/servers"
|
||
|
|
||
|
FILES:${PN}-bin = "${bindir}/* ${sbindir}/*"
|
||
|
|
||
|
FILES:${PN}-doc = "${docdir} ${mandir} ${infodir} ${datadir}/gtk-doc \
|
||
|
${datadir}/gnome/help"
|
||
|
SECTION:${PN}-doc = "doc"
|
||
|
|
||
|
FILES_SOLIBSDEV ?= "${base_libdir}/lib*${SOLIBSDEV} ${libdir}/lib*${SOLIBSDEV}"
|
||
|
FILES:${PN}-dev = "${includedir} ${FILES_SOLIBSDEV} ${libdir}/*.la \
|
||
|
${libdir}/*.o ${libdir}/pkgconfig ${datadir}/pkgconfig \
|
||
|
${datadir}/aclocal ${base_libdir}/*.o \
|
||
|
${libdir}/${BPN}/*.la ${base_libdir}/*.la \
|
||
|
${libdir}/cmake ${datadir}/cmake"
|
||
|
SECTION:${PN}-dev = "devel"
|
||
|
ALLOW_EMPTY:${PN}-dev = "1"
|
||
|
RDEPENDS:${PN}-dev = "${PN} (= ${EXTENDPKGV})"
|
||
|
|
||
|
FILES:${PN}-staticdev = "${libdir}/*.a ${base_libdir}/*.a ${libdir}/${BPN}/*.a"
|
||
|
SECTION:${PN}-staticdev = "devel"
|
||
|
RDEPENDS:${PN}-staticdev = "${PN}-dev (= ${EXTENDPKGV})"
|
||
|
|
||
|
Combining Multiple Versions of Library Files into One Image
|
||
|
===========================================================
|
||
|
|
||
|
The build system offers the ability to build libraries with different
|
||
|
target optimizations or architecture formats and combine these together
|
||
|
into one system image. You can link different binaries in the image
|
||
|
against the different libraries as needed for specific use cases. This
|
||
|
feature is called "Multilib".
|
||
|
|
||
|
An example would be where you have most of a system compiled in 32-bit
|
||
|
mode using 32-bit libraries, but you have something large, like a
|
||
|
database engine, that needs to be a 64-bit application and uses 64-bit
|
||
|
libraries. Multilib allows you to get the best of both 32-bit and 64-bit
|
||
|
libraries.
|
||
|
|
||
|
While the Multilib feature is most commonly used for 32 and 64-bit
|
||
|
differences, the approach the build system uses facilitates different
|
||
|
target optimizations. You could compile some binaries to use one set of
|
||
|
libraries and other binaries to use a different set of libraries. The
|
||
|
libraries could differ in architecture, compiler options, or other
|
||
|
optimizations.
|
||
|
|
||
|
There are several examples in the ``meta-skeleton`` layer found in the
|
||
|
:term:`Source Directory`:
|
||
|
|
||
|
- :oe_git:`conf/multilib-example.conf </openembedded-core/tree/meta-skeleton/conf/multilib-example.conf>`
|
||
|
configuration file.
|
||
|
|
||
|
- :oe_git:`conf/multilib-example2.conf </openembedded-core/tree/meta-skeleton/conf/multilib-example2.conf>`
|
||
|
configuration file.
|
||
|
|
||
|
- :oe_git:`recipes-multilib/images/core-image-multilib-example.bb </openembedded-core/tree/meta-skeleton/recipes-multilib/images/core-image-multilib-example.bb>`
|
||
|
recipe
|
||
|
|
||
|
Preparing to Use Multilib
|
||
|
-------------------------
|
||
|
|
||
|
User-specific requirements drive the Multilib feature. Consequently,
|
||
|
there is no one "out-of-the-box" configuration that would
|
||
|
meet your needs.
|
||
|
|
||
|
In order to enable Multilib, you first need to ensure your recipe is
|
||
|
extended to support multiple libraries. Many standard recipes are
|
||
|
already extended and support multiple libraries. You can check in the
|
||
|
``meta/conf/multilib.conf`` configuration file in the
|
||
|
:term:`Source Directory` to see how this is
|
||
|
done using the
|
||
|
:term:`BBCLASSEXTEND` variable.
|
||
|
Eventually, all recipes will be covered and this list will not be
|
||
|
needed.
|
||
|
|
||
|
For the most part, the :ref:`Multilib <ref-classes-multilib*>`
|
||
|
class extension works automatically to
|
||
|
extend the package name from ``${PN}`` to ``${MLPREFIX}${PN}``, where
|
||
|
:term:`MLPREFIX` is the particular multilib (e.g. "lib32-" or "lib64-").
|
||
|
Standard variables such as
|
||
|
:term:`DEPENDS`,
|
||
|
:term:`RDEPENDS`,
|
||
|
:term:`RPROVIDES`,
|
||
|
:term:`RRECOMMENDS`,
|
||
|
:term:`PACKAGES`, and
|
||
|
:term:`PACKAGES_DYNAMIC` are
|
||
|
automatically extended by the system. If you are extending any manual
|
||
|
code in the recipe, you can use the ``${MLPREFIX}`` variable to ensure
|
||
|
those names are extended correctly.
|
||
|
|
||
|
Using Multilib
|
||
|
--------------
|
||
|
|
||
|
After you have set up the recipes, you need to define the actual
|
||
|
combination of multiple libraries you want to build. You accomplish this
|
||
|
through your ``local.conf`` configuration file in the
|
||
|
:term:`Build Directory`. An example configuration would be as follows::
|
||
|
|
||
|
MACHINE = "qemux86-64"
|
||
|
require conf/multilib.conf
|
||
|
MULTILIBS = "multilib:lib32"
|
||
|
DEFAULTTUNE:virtclass-multilib-lib32 = "x86"
|
||
|
IMAGE_INSTALL:append = " lib32-glib-2.0"
|
||
|
|
||
|
This example enables an additional library named
|
||
|
``lib32`` alongside the normal target packages. When combining these
|
||
|
"lib32" alternatives, the example uses "x86" for tuning. For information
|
||
|
on this particular tuning, see
|
||
|
``meta/conf/machine/include/ia32/arch-ia32.inc``.
|
||
|
|
||
|
The example then includes ``lib32-glib-2.0`` in all the images, which
|
||
|
illustrates one method of including a multiple library dependency. You
|
||
|
can use a normal image build to include this dependency, for example::
|
||
|
|
||
|
$ bitbake core-image-sato
|
||
|
|
||
|
You can also build Multilib packages
|
||
|
specifically with a command like this::
|
||
|
|
||
|
$ bitbake lib32-glib-2.0
|
||
|
|
||
|
Additional Implementation Details
|
||
|
---------------------------------
|
||
|
|
||
|
There are generic implementation details as well as details that are specific to
|
||
|
package management systems. Following are implementation details
|
||
|
that exist regardless of the package management system:
|
||
|
|
||
|
- The typical convention used for the class extension code as used by
|
||
|
Multilib assumes that all package names specified in
|
||
|
:term:`PACKAGES` that contain
|
||
|
``${PN}`` have ``${PN}`` at the start of the name. When that
|
||
|
convention is not followed and ``${PN}`` appears at the middle or the
|
||
|
end of a name, problems occur.
|
||
|
|
||
|
- The :term:`TARGET_VENDOR`
|
||
|
value under Multilib will be extended to "-vendormlmultilib" (e.g.
|
||
|
"-pokymllib32" for a "lib32" Multilib with Poky). The reason for this
|
||
|
slightly unwieldy contraction is that any "-" characters in the
|
||
|
vendor string presently break Autoconf's ``config.sub``, and other
|
||
|
separators are problematic for different reasons.
|
||
|
|
||
|
Here are the implementation details for the RPM Package Management System:
|
||
|
|
||
|
- A unique architecture is defined for the Multilib packages, along
|
||
|
with creating a unique deploy folder under ``tmp/deploy/rpm`` in the
|
||
|
:term:`Build Directory`. For example, consider ``lib32`` in a
|
||
|
``qemux86-64`` image. The possible architectures in the system are "all",
|
||
|
"qemux86_64", "lib32:qemux86_64", and "lib32:x86".
|
||
|
|
||
|
- The ``${MLPREFIX}`` variable is stripped from ``${PN}`` during RPM
|
||
|
packaging. The naming for a normal RPM package and a Multilib RPM
|
||
|
package in a ``qemux86-64`` system resolves to something similar to
|
||
|
``bash-4.1-r2.x86_64.rpm`` and ``bash-4.1.r2.lib32_x86.rpm``,
|
||
|
respectively.
|
||
|
|
||
|
- When installing a Multilib image, the RPM backend first installs the
|
||
|
base image and then installs the Multilib libraries.
|
||
|
|
||
|
- The build system relies on RPM to resolve the identical files in the
|
||
|
two (or more) Multilib packages.
|
||
|
|
||
|
Here are the implementation details for the IPK Package Management System:
|
||
|
|
||
|
- The ``${MLPREFIX}`` is not stripped from ``${PN}`` during IPK
|
||
|
packaging. The naming for a normal RPM package and a Multilib IPK
|
||
|
package in a ``qemux86-64`` system resolves to something like
|
||
|
``bash_4.1-r2.x86_64.ipk`` and ``lib32-bash_4.1-rw:x86.ipk``,
|
||
|
respectively.
|
||
|
|
||
|
- The IPK deploy folder is not modified with ``${MLPREFIX}`` because
|
||
|
packages with and without the Multilib feature can exist in the same
|
||
|
folder due to the ``${PN}`` differences.
|
||
|
|
||
|
- IPK defines a sanity check for Multilib installation using certain
|
||
|
rules for file comparison, overridden, etc.
|
||
|
|
||
|
Installing Multiple Versions of the Same Library
|
||
|
================================================
|
||
|
|
||
|
There are be situations where you need to install and use multiple versions
|
||
|
of the same library on the same system at the same time. This
|
||
|
almost always happens when a library API changes and you have
|
||
|
multiple pieces of software that depend on the separate versions of the
|
||
|
library. To accommodate these situations, you can install multiple
|
||
|
versions of the same library in parallel on the same system.
|
||
|
|
||
|
The process is straightforward as long as the libraries use proper
|
||
|
versioning. With properly versioned libraries, all you need to do to
|
||
|
individually specify the libraries is create separate, appropriately
|
||
|
named recipes where the :term:`PN` part of
|
||
|
the name includes a portion that differentiates each library version
|
||
|
(e.g. the major part of the version number). Thus, instead of having a
|
||
|
single recipe that loads one version of a library (e.g. ``clutter``),
|
||
|
you provide multiple recipes that result in different versions of the
|
||
|
libraries you want. As an example, the following two recipes would allow
|
||
|
the two separate versions of the ``clutter`` library to co-exist on the
|
||
|
same system:
|
||
|
|
||
|
.. code-block:: none
|
||
|
|
||
|
clutter-1.6_1.6.20.bb
|
||
|
clutter-1.8_1.8.4.bb
|
||
|
|
||
|
Additionally, if
|
||
|
you have other recipes that depend on a given library, you need to use
|
||
|
the :term:`DEPENDS` variable to
|
||
|
create the dependency. Continuing with the same example, if you want to
|
||
|
have a recipe depend on the 1.8 version of the ``clutter`` library, use
|
||
|
the following in your recipe::
|
||
|
|
||
|
DEPENDS = "clutter-1.8"
|
||
|
|