Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 1 | .. SPDX-License-Identifier: CC-BY-SA-2.0-UK |
| 2 | |
| 3 | Working With Libraries |
| 4 | ********************** |
| 5 | |
| 6 | Libraries are an integral part of your system. This section describes |
| 7 | some common practices you might find helpful when working with libraries |
| 8 | to build your system: |
| 9 | |
| 10 | - :ref:`How to include static library files |
| 11 | <dev-manual/libraries:including static library files>` |
| 12 | |
| 13 | - :ref:`How to use the Multilib feature to combine multiple versions of |
| 14 | library files into a single image |
| 15 | <dev-manual/libraries:combining multiple versions of library files into one image>` |
| 16 | |
| 17 | - :ref:`How to install multiple versions of the same library in parallel on |
| 18 | the same system |
| 19 | <dev-manual/libraries:installing multiple versions of the same library>` |
| 20 | |
| 21 | Including Static Library Files |
| 22 | ============================== |
| 23 | |
| 24 | If you are building a library and the library offers static linking, you |
| 25 | can control which static library files (``*.a`` files) get included in |
| 26 | the built library. |
| 27 | |
| 28 | The :term:`PACKAGES` and |
| 29 | :term:`FILES:* <FILES>` variables in the |
| 30 | ``meta/conf/bitbake.conf`` configuration file define how files installed |
| 31 | by the :ref:`ref-tasks-install` task are packaged. By default, the :term:`PACKAGES` |
| 32 | variable includes ``${PN}-staticdev``, which represents all static |
| 33 | library files. |
| 34 | |
| 35 | .. note:: |
| 36 | |
| 37 | Some previously released versions of the Yocto Project defined the |
| 38 | static library files through ``${PN}-dev``. |
| 39 | |
| 40 | Following is part of the BitBake configuration file, where you can see |
| 41 | how the static library files are defined:: |
| 42 | |
| 43 | PACKAGE_BEFORE_PN ?= "" |
| 44 | PACKAGES = "${PN}-src ${PN}-dbg ${PN}-staticdev ${PN}-dev ${PN}-doc ${PN}-locale ${PACKAGE_BEFORE_PN} ${PN}" |
| 45 | PACKAGES_DYNAMIC = "^${PN}-locale-.*" |
| 46 | FILES = "" |
| 47 | |
| 48 | FILES:${PN} = "${bindir}/* ${sbindir}/* ${libexecdir}/* ${libdir}/lib*${SOLIBS} \ |
| 49 | ${sysconfdir} ${sharedstatedir} ${localstatedir} \ |
| 50 | ${base_bindir}/* ${base_sbindir}/* \ |
| 51 | ${base_libdir}/*${SOLIBS} \ |
| 52 | ${base_prefix}/lib/udev ${prefix}/lib/udev \ |
| 53 | ${base_libdir}/udev ${libdir}/udev \ |
| 54 | ${datadir}/${BPN} ${libdir}/${BPN}/* \ |
| 55 | ${datadir}/pixmaps ${datadir}/applications \ |
| 56 | ${datadir}/idl ${datadir}/omf ${datadir}/sounds \ |
| 57 | ${libdir}/bonobo/servers" |
| 58 | |
| 59 | FILES:${PN}-bin = "${bindir}/* ${sbindir}/*" |
| 60 | |
| 61 | FILES:${PN}-doc = "${docdir} ${mandir} ${infodir} ${datadir}/gtk-doc \ |
| 62 | ${datadir}/gnome/help" |
| 63 | SECTION:${PN}-doc = "doc" |
| 64 | |
| 65 | FILES_SOLIBSDEV ?= "${base_libdir}/lib*${SOLIBSDEV} ${libdir}/lib*${SOLIBSDEV}" |
| 66 | FILES:${PN}-dev = "${includedir} ${FILES_SOLIBSDEV} ${libdir}/*.la \ |
| 67 | ${libdir}/*.o ${libdir}/pkgconfig ${datadir}/pkgconfig \ |
| 68 | ${datadir}/aclocal ${base_libdir}/*.o \ |
| 69 | ${libdir}/${BPN}/*.la ${base_libdir}/*.la \ |
| 70 | ${libdir}/cmake ${datadir}/cmake" |
| 71 | SECTION:${PN}-dev = "devel" |
| 72 | ALLOW_EMPTY:${PN}-dev = "1" |
| 73 | RDEPENDS:${PN}-dev = "${PN} (= ${EXTENDPKGV})" |
| 74 | |
| 75 | FILES:${PN}-staticdev = "${libdir}/*.a ${base_libdir}/*.a ${libdir}/${BPN}/*.a" |
| 76 | SECTION:${PN}-staticdev = "devel" |
| 77 | RDEPENDS:${PN}-staticdev = "${PN}-dev (= ${EXTENDPKGV})" |
| 78 | |
| 79 | Combining Multiple Versions of Library Files into One Image |
| 80 | =========================================================== |
| 81 | |
| 82 | The build system offers the ability to build libraries with different |
| 83 | target optimizations or architecture formats and combine these together |
| 84 | into one system image. You can link different binaries in the image |
| 85 | against the different libraries as needed for specific use cases. This |
| 86 | feature is called "Multilib". |
| 87 | |
| 88 | An example would be where you have most of a system compiled in 32-bit |
| 89 | mode using 32-bit libraries, but you have something large, like a |
| 90 | database engine, that needs to be a 64-bit application and uses 64-bit |
| 91 | libraries. Multilib allows you to get the best of both 32-bit and 64-bit |
| 92 | libraries. |
| 93 | |
| 94 | While the Multilib feature is most commonly used for 32 and 64-bit |
| 95 | differences, the approach the build system uses facilitates different |
| 96 | target optimizations. You could compile some binaries to use one set of |
| 97 | libraries and other binaries to use a different set of libraries. The |
| 98 | libraries could differ in architecture, compiler options, or other |
| 99 | optimizations. |
| 100 | |
| 101 | There are several examples in the ``meta-skeleton`` layer found in the |
| 102 | :term:`Source Directory`: |
| 103 | |
| 104 | - :oe_git:`conf/multilib-example.conf </openembedded-core/tree/meta-skeleton/conf/multilib-example.conf>` |
| 105 | configuration file. |
| 106 | |
| 107 | - :oe_git:`conf/multilib-example2.conf </openembedded-core/tree/meta-skeleton/conf/multilib-example2.conf>` |
| 108 | configuration file. |
| 109 | |
| 110 | - :oe_git:`recipes-multilib/images/core-image-multilib-example.bb </openembedded-core/tree/meta-skeleton/recipes-multilib/images/core-image-multilib-example.bb>` |
| 111 | recipe |
| 112 | |
| 113 | Preparing to Use Multilib |
| 114 | ------------------------- |
| 115 | |
| 116 | User-specific requirements drive the Multilib feature. Consequently, |
| 117 | there is no one "out-of-the-box" configuration that would |
| 118 | meet your needs. |
| 119 | |
| 120 | In order to enable Multilib, you first need to ensure your recipe is |
| 121 | extended to support multiple libraries. Many standard recipes are |
| 122 | already extended and support multiple libraries. You can check in the |
| 123 | ``meta/conf/multilib.conf`` configuration file in the |
| 124 | :term:`Source Directory` to see how this is |
| 125 | done using the |
| 126 | :term:`BBCLASSEXTEND` variable. |
| 127 | Eventually, all recipes will be covered and this list will not be |
| 128 | needed. |
| 129 | |
| 130 | For the most part, the :ref:`Multilib <ref-classes-multilib*>` |
| 131 | class extension works automatically to |
| 132 | extend the package name from ``${PN}`` to ``${MLPREFIX}${PN}``, where |
| 133 | :term:`MLPREFIX` is the particular multilib (e.g. "lib32-" or "lib64-"). |
| 134 | Standard variables such as |
| 135 | :term:`DEPENDS`, |
| 136 | :term:`RDEPENDS`, |
| 137 | :term:`RPROVIDES`, |
| 138 | :term:`RRECOMMENDS`, |
| 139 | :term:`PACKAGES`, and |
| 140 | :term:`PACKAGES_DYNAMIC` are |
| 141 | automatically extended by the system. If you are extending any manual |
| 142 | code in the recipe, you can use the ``${MLPREFIX}`` variable to ensure |
| 143 | those names are extended correctly. |
| 144 | |
| 145 | Using Multilib |
| 146 | -------------- |
| 147 | |
| 148 | After you have set up the recipes, you need to define the actual |
| 149 | combination of multiple libraries you want to build. You accomplish this |
| 150 | through your ``local.conf`` configuration file in the |
| 151 | :term:`Build Directory`. An example configuration would be as follows:: |
| 152 | |
| 153 | MACHINE = "qemux86-64" |
| 154 | require conf/multilib.conf |
| 155 | MULTILIBS = "multilib:lib32" |
| 156 | DEFAULTTUNE:virtclass-multilib-lib32 = "x86" |
| 157 | IMAGE_INSTALL:append = " lib32-glib-2.0" |
| 158 | |
| 159 | This example enables an additional library named |
| 160 | ``lib32`` alongside the normal target packages. When combining these |
| 161 | "lib32" alternatives, the example uses "x86" for tuning. For information |
| 162 | on this particular tuning, see |
| 163 | ``meta/conf/machine/include/ia32/arch-ia32.inc``. |
| 164 | |
| 165 | The example then includes ``lib32-glib-2.0`` in all the images, which |
| 166 | illustrates one method of including a multiple library dependency. You |
| 167 | can use a normal image build to include this dependency, for example:: |
| 168 | |
| 169 | $ bitbake core-image-sato |
| 170 | |
| 171 | You can also build Multilib packages |
| 172 | specifically with a command like this:: |
| 173 | |
| 174 | $ bitbake lib32-glib-2.0 |
| 175 | |
| 176 | Additional Implementation Details |
| 177 | --------------------------------- |
| 178 | |
| 179 | There are generic implementation details as well as details that are specific to |
| 180 | package management systems. Following are implementation details |
| 181 | that exist regardless of the package management system: |
| 182 | |
| 183 | - The typical convention used for the class extension code as used by |
| 184 | Multilib assumes that all package names specified in |
| 185 | :term:`PACKAGES` that contain |
| 186 | ``${PN}`` have ``${PN}`` at the start of the name. When that |
| 187 | convention is not followed and ``${PN}`` appears at the middle or the |
| 188 | end of a name, problems occur. |
| 189 | |
| 190 | - The :term:`TARGET_VENDOR` |
| 191 | value under Multilib will be extended to "-vendormlmultilib" (e.g. |
| 192 | "-pokymllib32" for a "lib32" Multilib with Poky). The reason for this |
| 193 | slightly unwieldy contraction is that any "-" characters in the |
| 194 | vendor string presently break Autoconf's ``config.sub``, and other |
| 195 | separators are problematic for different reasons. |
| 196 | |
| 197 | Here are the implementation details for the RPM Package Management System: |
| 198 | |
| 199 | - A unique architecture is defined for the Multilib packages, along |
| 200 | with creating a unique deploy folder under ``tmp/deploy/rpm`` in the |
| 201 | :term:`Build Directory`. For example, consider ``lib32`` in a |
| 202 | ``qemux86-64`` image. The possible architectures in the system are "all", |
| 203 | "qemux86_64", "lib32:qemux86_64", and "lib32:x86". |
| 204 | |
| 205 | - The ``${MLPREFIX}`` variable is stripped from ``${PN}`` during RPM |
| 206 | packaging. The naming for a normal RPM package and a Multilib RPM |
| 207 | package in a ``qemux86-64`` system resolves to something similar to |
| 208 | ``bash-4.1-r2.x86_64.rpm`` and ``bash-4.1.r2.lib32_x86.rpm``, |
| 209 | respectively. |
| 210 | |
| 211 | - When installing a Multilib image, the RPM backend first installs the |
| 212 | base image and then installs the Multilib libraries. |
| 213 | |
| 214 | - The build system relies on RPM to resolve the identical files in the |
| 215 | two (or more) Multilib packages. |
| 216 | |
| 217 | Here are the implementation details for the IPK Package Management System: |
| 218 | |
| 219 | - The ``${MLPREFIX}`` is not stripped from ``${PN}`` during IPK |
| 220 | packaging. The naming for a normal RPM package and a Multilib IPK |
| 221 | package in a ``qemux86-64`` system resolves to something like |
| 222 | ``bash_4.1-r2.x86_64.ipk`` and ``lib32-bash_4.1-rw:x86.ipk``, |
| 223 | respectively. |
| 224 | |
| 225 | - The IPK deploy folder is not modified with ``${MLPREFIX}`` because |
| 226 | packages with and without the Multilib feature can exist in the same |
| 227 | folder due to the ``${PN}`` differences. |
| 228 | |
| 229 | - IPK defines a sanity check for Multilib installation using certain |
| 230 | rules for file comparison, overridden, etc. |
| 231 | |
| 232 | Installing Multiple Versions of the Same Library |
| 233 | ================================================ |
| 234 | |
| 235 | There are be situations where you need to install and use multiple versions |
| 236 | of the same library on the same system at the same time. This |
| 237 | almost always happens when a library API changes and you have |
| 238 | multiple pieces of software that depend on the separate versions of the |
| 239 | library. To accommodate these situations, you can install multiple |
| 240 | versions of the same library in parallel on the same system. |
| 241 | |
| 242 | The process is straightforward as long as the libraries use proper |
| 243 | versioning. With properly versioned libraries, all you need to do to |
| 244 | individually specify the libraries is create separate, appropriately |
| 245 | named recipes where the :term:`PN` part of |
| 246 | the name includes a portion that differentiates each library version |
| 247 | (e.g. the major part of the version number). Thus, instead of having a |
| 248 | single recipe that loads one version of a library (e.g. ``clutter``), |
| 249 | you provide multiple recipes that result in different versions of the |
| 250 | libraries you want. As an example, the following two recipes would allow |
| 251 | the two separate versions of the ``clutter`` library to co-exist on the |
| 252 | same system: |
| 253 | |
| 254 | .. code-block:: none |
| 255 | |
| 256 | clutter-1.6_1.6.20.bb |
| 257 | clutter-1.8_1.8.4.bb |
| 258 | |
| 259 | Additionally, if |
| 260 | you have other recipes that depend on a given library, you need to use |
| 261 | the :term:`DEPENDS` variable to |
| 262 | create the dependency. Continuing with the same example, if you want to |
| 263 | have a recipe depend on the 1.8 version of the ``clutter`` library, use |
| 264 | the following in your recipe:: |
| 265 | |
| 266 | DEPENDS = "clutter-1.8" |
| 267 | |