blob: ca434638200895912f026a87c5ef58b9be1fe8e5 [file] [log] [blame]
Andrew Geissler517393d2023-01-13 08:55:19 -06001.. SPDX-License-Identifier: CC-BY-SA-2.0-UK
2
3Working with Pre-Built Libraries
4********************************
5
6Introduction
7============
8
9Some library vendors do not release source code for their software but do
10release pre-built binaries. When shared libraries are built, they should
11be versioned (see `this article
12<https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html>`__
13for some background), but sometimes this is not done.
14
15To summarize, a versioned library must meet two conditions:
16
17#. The filename must have the version appended, for example: ``libfoo.so.1.2.3``.
18#. The library must have the ELF tag ``SONAME`` set to the major version
19 of the library, for example: ``libfoo.so.1``. You can check this by
20 running ``readelf -d filename | grep SONAME``.
21
22This section shows how to deal with both versioned and unversioned
23pre-built libraries.
24
25Versioned Libraries
26===================
27
28In this example we work with pre-built libraries for the FT4222H USB I/O chip.
29Libraries are built for several target architecture variants and packaged in
30an archive as follows::
31
32 ├── build-arm-hisiv300
33 │   └── libft4222.so.1.4.4.44
34 ├── build-arm-v5-sf
35 │   └── libft4222.so.1.4.4.44
36 ├── build-arm-v6-hf
37 │   └── libft4222.so.1.4.4.44
38 ├── build-arm-v7-hf
39 │   └── libft4222.so.1.4.4.44
40 ├── build-arm-v8
41 │   └── libft4222.so.1.4.4.44
42 ├── build-i386
43 │   └── libft4222.so.1.4.4.44
44 ├── build-i486
45 │   └── libft4222.so.1.4.4.44
46 ├── build-mips-eglibc-hf
47 │   └── libft4222.so.1.4.4.44
48 ├── build-pentium
49 │   └── libft4222.so.1.4.4.44
50 ├── build-x86_64
51 │   └── libft4222.so.1.4.4.44
52 ├── examples
53 │   ├── get-version.c
54 │   ├── i2cm.c
55 │   ├── spim.c
56 │   └── spis.c
57 ├── ftd2xx.h
58 ├── install4222.sh
59 ├── libft4222.h
60 ├── ReadMe.txt
61 └── WinTypes.h
62
63To write a recipe to use such a library in your system:
64
65- The vendor will probably have a proprietary licence, so set
66 :term:`LICENSE_FLAGS` in your recipe.
67- The vendor provides a tarball containing libraries so set :term:`SRC_URI`
68 appropriately.
69- Set :term:`COMPATIBLE_HOST` so that the recipe cannot be used with an
70 unsupported architecture. In the following example, we only support the 32
71 and 64 bit variants of the ``x86`` architecture.
72- As the vendor provides versioned libraries, we can use ``oe_soinstall``
73 from :ref:`ref-classes-utils` to install the shared library and create
74 symbolic links. If the vendor does not do this, we need to follow the
75 non-versioned library guidelines in the next section.
76- As the vendor likely used :term:`LDFLAGS` different from those in your Yocto
77 Project build, disable the corresponding checks by adding ``ldflags``
78 to :term:`INSANE_SKIP`.
79- The vendor will typically ship release builds without debugging symbols.
80 Avoid errors by preventing the packaging task from stripping out the symbols
81 and adding them to a separate debug package. This is done by setting the
82 ``INHIBIT_`` flags shown below.
83
84The complete recipe would look like this::
85
86 SUMMARY = "FTDI FT4222H Library"
87 SECTION = "libs"
88 LICENSE_FLAGS = "ftdi"
89 LICENSE = "CLOSED"
90
91 COMPATIBLE_HOST = "(i.86|x86_64).*-linux"
92
93 # Sources available in a .tgz file in .zip archive
94 # at https://ftdichip.com/wp-content/uploads/2021/01/libft4222-linux-1.4.4.44.zip
95 # Found on https://ftdichip.com/software-examples/ft4222h-software-examples/
96 # Since dealing with this particular type of archive is out of topic here,
97 # we use a local link.
98 SRC_URI = "file://libft4222-linux-${PV}.tgz"
99
100 S = "${WORKDIR}"
101
102 ARCH_DIR:x86-64 = "build-x86_64"
103 ARCH_DIR:i586 = "build-i386"
104 ARCH_DIR:i686 = "build-i386"
105
106 INSANE_SKIP:${PN} = "ldflags"
107 INHIBIT_PACKAGE_STRIP = "1"
108 INHIBIT_SYSROOT_STRIP = "1"
109 INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
110
111 do_install () {
112 install -m 0755 -d ${D}${libdir}
113 oe_soinstall ${S}/${ARCH_DIR}/libft4222.so.${PV} ${D}${libdir}
114 install -d ${D}${includedir}
115 install -m 0755 ${S}/*.h ${D}${includedir}
116 }
117
118If the precompiled binaries are not statically linked and have dependencies on
119other libraries, then by adding those libraries to :term:`DEPENDS`, the linking
120can be examined and the appropriate :term:`RDEPENDS` automatically added.
121
122Non-Versioned Libraries
123=======================
124
125Some Background
126---------------
127
128Libraries in Linux systems are generally versioned so that it is possible
129to have multiple versions of the same library installed, which eases upgrades
130and support for older software. For example, suppose that in a versioned
131library, an actual library is called ``libfoo.so.1.2``, a symbolic link named
132``libfoo.so.1`` points to ``libfoo.so.1.2``, and a symbolic link named
133``libfoo.so`` points to ``libfoo.so.1.2``. Given these conditions, when you
134link a binary against a library, you typically provide the unversioned file
135name (i.e. ``-lfoo`` to the linker). However, the linker follows the symbolic
136link and actually links against the versioned filename. The unversioned symbolic
137link is only used at development time. Consequently, the library is packaged
138along with the headers in the development package ``${PN}-dev`` along with the
139actual library and versioned symbolic links in ``${PN}``. Because versioned
140libraries are far more common than unversioned libraries, the default packaging
141rules assume versioned libraries.
142
143Yocto Library Packaging Overview
144--------------------------------
145
146It follows that packaging an unversioned library requires a bit of work in the
147recipe. By default, ``libfoo.so`` gets packaged into ``${PN}-dev``, which
148triggers a QA warning that a non-symlink library is in a ``-dev`` package,
149and binaries in the same recipe link to the library in ``${PN}-dev``,
150which triggers more QA warnings. To solve this problem, you need to package the
151unversioned library into ``${PN}`` where it belongs. The following are the abridged
152default :term:`FILES` variables in ``bitbake.conf``::
153
154 SOLIBS = ".so.*"
155 SOLIBSDEV = ".so"
156 FILES_${PN} = "... ${libdir}/lib*${SOLIBS} ..."
157 FILES_SOLIBSDEV ?= "... ${libdir}/lib*${SOLIBSDEV} ..."
158 FILES_${PN}-dev = "... ${FILES_SOLIBSDEV} ..."
159
160:term:`SOLIBS` defines a pattern that matches real shared object libraries.
161:term:`SOLIBSDEV` matches the development form (unversioned symlink). These two
162variables are then used in ``FILES:${PN}`` and ``FILES:${PN}-dev``, which puts
163the real libraries into ``${PN}`` and the unversioned symbolic link into ``${PN}-dev``.
164To package unversioned libraries, you need to modify the variables in the recipe
165as follows::
166
167 SOLIBS = ".so"
168 FILES_SOLIBSDEV = ""
169
170The modifications cause the ``.so`` file to be the real library
171and unset :term:`FILES_SOLIBSDEV` so that no libraries get packaged into
172``${PN}-dev``. The changes are required because unless :term:`PACKAGES` is changed,
173``${PN}-dev`` collects files before `${PN}`. ``${PN}-dev`` must not collect any of
174the files you want in ``${PN}``.
175
176Finally, loadable modules, essentially unversioned libraries that are linked
177at runtime using ``dlopen()`` instead of at build time, should generally be
178installed in a private directory. However, if they are installed in ``${libdir}``,
179then the modules can be treated as unversioned libraries.
180
181Example
182-------
183
184The example below installs an unversioned x86-64 pre-built library named
185``libfoo.so``. The :term:`COMPATIBLE_HOST` variable limits recipes to the
186x86-64 architecture while the :term:`INSANE_SKIP`, :term:`INHIBIT_PACKAGE_STRIP`
187and :term:`INHIBIT_SYSROOT_STRIP` variables are all set as in the above
188versioned library example. The "magic" is setting the :term:`SOLIBS` and
189:term:`FILES_SOLIBSDEV` variables as explained above::
190
191 SUMMARY = "libfoo sample recipe"
192 SECTION = "libs"
193 LICENSE = "CLOSED"
194
195 SRC_URI = "file://libfoo.so"
196
197 COMPATIBLE_HOST = "x86_64.*-linux"
198
199 INSANE_SKIP:${PN} = "ldflags"
200 INHIBIT_PACKAGE_STRIP = "1"
201 INHIBIT_SYSROOT_STRIP = "1"
202 SOLIBS = ".so"
203 FILES_SOLIBSDEV = ""
204
205 do_install () {
206 install -d ${D}${libdir}
207 install -m 0755 ${WORKDIR}/libfoo.so ${D}${libdir}
208 }
209