diff options
| author | Michael Opdenacker <michael.opdenacker@bootlin.com> | 2022-01-11 09:13:51 +0100 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2022-02-03 13:47:50 +0000 |
| commit | a9fdd010b9382c05a0fd5aefb14280dc125f1808 (patch) | |
| tree | 4bffd56a579ef2543aa75f5bb71b839c6e1f9fd5 /documentation/dev-manual | |
| parent | 3f27dfa9c9d02ec76775da9285fd292e69581f15 (diff) | |
| download | poky-a9fdd010b9382c05a0fd5aefb14280dc125f1808.tar.gz | |
dev-manual: new "working with pre-compiled libraries" section
This explains how to deal with versioned and unversioned
pre-built libraries from vendors.
Content and examples adapted from
https://wiki.yoctoproject.org/wiki/TipsAndTricks/Packaging_Prebuilt_Libraries,
originally written by Henry Bruce in 2016.
(From yocto-docs rev: 5e46cad9e4b4ab03e33f4d5aea34e56f6b15fe27)
Signed-off-by: Michael Opdenacker <michael.opdenacker@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'documentation/dev-manual')
| -rw-r--r-- | documentation/dev-manual/common-tasks.rst | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/documentation/dev-manual/common-tasks.rst b/documentation/dev-manual/common-tasks.rst index 938a580cd3..f8ee774077 100644 --- a/documentation/dev-manual/common-tasks.rst +++ b/documentation/dev-manual/common-tasks.rst | |||
| @@ -4894,6 +4894,213 @@ the following in your recipe:: | |||
| 4894 | 4894 | ||
| 4895 | DEPENDS = "clutter-1.8" | 4895 | DEPENDS = "clutter-1.8" |
| 4896 | 4896 | ||
| 4897 | Working with Pre-Built Libraries | ||
| 4898 | ================================ | ||
| 4899 | |||
| 4900 | Introduction | ||
| 4901 | ------------- | ||
| 4902 | |||
| 4903 | Some library vendors do not release source code for their software but do | ||
| 4904 | release pre-built binaries. When shared libraries are built, they should | ||
| 4905 | be versioned (see `this article | ||
| 4906 | <https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html>`__ | ||
| 4907 | for some background), but sometimes this is not done. | ||
| 4908 | |||
| 4909 | To summarize, a versioned library must meet two conditions: | ||
| 4910 | |||
| 4911 | #. The filename must have the version appended, for example: ``libfoo.so.1.2.3``. | ||
| 4912 | #. The library must have the ELF tag ``SONAME`` set to the major version | ||
| 4913 | of the library, for example: ``libfoo.so.1``. You can check this by | ||
| 4914 | running ``readelf -d filename | grep SONAME``. | ||
| 4915 | |||
| 4916 | This section shows how to deal with both versioned and unversioned | ||
| 4917 | pre-built libraries. | ||
| 4918 | |||
| 4919 | Versioned Libraries | ||
| 4920 | ------------------- | ||
| 4921 | |||
| 4922 | In this example we work with pre-built libraries for the FT4222H USB I/O chip. | ||
| 4923 | Libraries are built for several target architecture variants and packaged in | ||
| 4924 | an archive as follows:: | ||
| 4925 | |||
| 4926 | ├── build-arm-hisiv300 | ||
| 4927 | │ └── libft4222.so.1.4.4.44 | ||
| 4928 | ├── build-arm-v5-sf | ||
| 4929 | │ └── libft4222.so.1.4.4.44 | ||
| 4930 | ├── build-arm-v6-hf | ||
| 4931 | │ └── libft4222.so.1.4.4.44 | ||
| 4932 | ├── build-arm-v7-hf | ||
| 4933 | │ └── libft4222.so.1.4.4.44 | ||
| 4934 | ├── build-arm-v8 | ||
| 4935 | │ └── libft4222.so.1.4.4.44 | ||
| 4936 | ├── build-i386 | ||
| 4937 | │ └── libft4222.so.1.4.4.44 | ||
| 4938 | ├── build-i486 | ||
| 4939 | │ └── libft4222.so.1.4.4.44 | ||
| 4940 | ├── build-mips-eglibc-hf | ||
| 4941 | │ └── libft4222.so.1.4.4.44 | ||
| 4942 | ├── build-pentium | ||
| 4943 | │ └── libft4222.so.1.4.4.44 | ||
| 4944 | ├── build-x86_64 | ||
| 4945 | │ └── libft4222.so.1.4.4.44 | ||
| 4946 | ├── examples | ||
| 4947 | │ ├── get-version.c | ||
| 4948 | │ ├── i2cm.c | ||
| 4949 | │ ├── spim.c | ||
| 4950 | │ └── spis.c | ||
| 4951 | ├── ftd2xx.h | ||
| 4952 | ├── install4222.sh | ||
| 4953 | ├── libft4222.h | ||
| 4954 | ├── ReadMe.txt | ||
| 4955 | └── WinTypes.h | ||
| 4956 | |||
| 4957 | To write a recipe to use such a library in your system: | ||
| 4958 | |||
| 4959 | - The vendor will probably have a proprietary licence, so set | ||
| 4960 | :term:`LICENSE_FLAGS` in your recipe. | ||
| 4961 | - The vendor provides a tarball containing libraries so set :term:`SRC_URI` | ||
| 4962 | appropriately. | ||
| 4963 | - Set :term:`COMPATIBLE_HOST` so that the recipe cannot be used with an | ||
| 4964 | unsupported architecture. In the following example, we only support the 32 | ||
| 4965 | and 64 bit variants of the ``x86`` architecture. | ||
| 4966 | - As the vendor provides versioned libraries, we can use ``oe_soinstall`` | ||
| 4967 | from :ref:`ref-classes-utils` to install the shared library and create | ||
| 4968 | symbolic links. If the vendor does not do this, we need to follow the | ||
| 4969 | non-versioned library guidelines in the next section. | ||
| 4970 | - As the vendor likely used :term:`LDFLAGS` different from those in your Yocto | ||
| 4971 | Project build, disable the corresponding checks by adding ``ldflags`` | ||
| 4972 | to :term:`INSANE_SKIP`. | ||
| 4973 | - The vendor will typically ship release builds without debugging symbols. | ||
| 4974 | Avoid errors by preventing the packaging task from stripping out the symbols | ||
| 4975 | and adding them to a separate debug package. This is done by setting the | ||
| 4976 | ``INHIBIT_`` flags shown below. | ||
| 4977 | |||
| 4978 | The complete recipe would look like this:: | ||
| 4979 | |||
| 4980 | SUMMARY = "FTDI FT4222H Library" | ||
| 4981 | SECTION = "libs" | ||
| 4982 | LICENSE_FLAGS = "ftdi" | ||
| 4983 | LICENSE = "CLOSED" | ||
| 4984 | |||
| 4985 | COMPATIBLE_HOST = "(i.86|x86_64).*-linux" | ||
| 4986 | |||
| 4987 | # Sources available in a .tgz file in .zip archive | ||
| 4988 | # at https://ftdichip.com/wp-content/uploads/2021/01/libft4222-linux-1.4.4.44.zip | ||
| 4989 | # Found on https://ftdichip.com/software-examples/ft4222h-software-examples/ | ||
| 4990 | # Since dealing with this particular type of archive is out of topic here, | ||
| 4991 | # we use a local link. | ||
| 4992 | SRC_URI = "file://libft4222-linux-${PV}.tgz" | ||
| 4993 | |||
| 4994 | S = "${WORKDIR}" | ||
| 4995 | |||
| 4996 | ARCH_DIR:x86-64 = "build-x86_64" | ||
| 4997 | ARCH_DIR:i586 = "build-i386" | ||
| 4998 | ARCH_DIR:i686 = "build-i386" | ||
| 4999 | |||
| 5000 | INSANE_SKIP:${PN} = "ldflags" | ||
| 5001 | INHIBIT_PACKAGE_STRIP = "1" | ||
| 5002 | INHIBIT_SYSROOT_STRIP = "1" | ||
| 5003 | INHIBIT_PACKAGE_DEBUG_SPLIT = "1" | ||
| 5004 | |||
| 5005 | do_install () { | ||
| 5006 | install -m 0755 -d ${D}${libdir} | ||
| 5007 | oe_soinstall ${S}/${ARCH_DIR}/libft4222.so.${PV} ${D}${libdir} | ||
| 5008 | install -d ${D}${includedir} | ||
| 5009 | install -m 0755 ${S}/*.h ${D}${includedir} | ||
| 5010 | } | ||
| 5011 | |||
| 5012 | If the precompiled binaries are not statically linked and have dependencies on | ||
| 5013 | other libraries, then by adding those libraries to :term:`DEPENDS`, the linking | ||
| 5014 | can be examined and the appropriate :term:`RDEPENDS` automatically added. | ||
| 5015 | |||
| 5016 | Non-Versioned Libraries | ||
| 5017 | ----------------------- | ||
| 5018 | |||
| 5019 | Some Background | ||
| 5020 | ~~~~~~~~~~~~~~~ | ||
| 5021 | |||
| 5022 | Libraries in Linux systems are generally versioned so that it is possible | ||
| 5023 | to have multiple versions of the same library installed, which eases upgrades | ||
| 5024 | and support for older software. For example, suppose that in a versioned | ||
| 5025 | library, an actual library is called ``libfoo.so.1.2``, a symbolic link named | ||
| 5026 | ``libfoo.so.1`` points to ``libfoo.so.1.2``, and a symbolic link named | ||
| 5027 | ``libfoo.so`` points to ``libfoo.so.1.2``. Given these conditions, when you | ||
| 5028 | link a binary against a library, you typically provide the unversioned file | ||
| 5029 | name (i.e. ``-lfoo`` to the linker). However, the linker follows the symbolic | ||
| 5030 | link and actually links against the versioned filename. The unversioned symbolic | ||
| 5031 | link is only used at development time. Consequently, the library is packaged | ||
| 5032 | along with the headers in the development package ``${PN}-dev`` along with the | ||
| 5033 | actual library and versioned symbolic links in ``${PN}``. Because versioned | ||
| 5034 | libraries are far more common than unversioned libraries, the default packaging | ||
| 5035 | rules assume versioned libraries. | ||
| 5036 | |||
| 5037 | Yocto Library Packaging Overview | ||
| 5038 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 5039 | |||
| 5040 | It follows that packaging an unversioned library requires a bit of work in the | ||
| 5041 | recipe. By default, ``libfoo.so`` gets packaged into ``${PN}-dev``, which | ||
| 5042 | triggers a QA warning that a non-symlink library is in a ``-dev`` package, | ||
| 5043 | and binaries in the same recipe link to the library in ``${PN}-dev``, | ||
| 5044 | which triggers more QA warnings. To solve this problem, you need to package the | ||
| 5045 | unversioned library into ``${PN}`` where it belongs. The following are the abridged | ||
| 5046 | default :term:`FILES` variables in ``bitbake.conf``:: | ||
| 5047 | |||
| 5048 | SOLIBS = ".so.*" | ||
| 5049 | SOLIBSDEV = ".so" | ||
| 5050 | FILES_${PN} = "... ${libdir}/lib*${SOLIBS} ..." | ||
| 5051 | FILES_SOLIBSDEV ?= "... ${libdir}/lib*${SOLIBSDEV} ..." | ||
| 5052 | FILES_${PN}-dev = "... ${FILES_SOLIBSDEV} ..." | ||
| 5053 | |||
| 5054 | :term:`SOLIBS` defines a pattern that matches real shared object libraries. | ||
| 5055 | :term:`SOLIBSDEV` matches the development form (unversioned symlink). These two | ||
| 5056 | variables are then used in ``FILES:${PN}`` and ``FILES:${PN}-dev``, which puts | ||
| 5057 | the real libraries into ``${PN}`` and the unversioned symbolic link into ``${PN}-dev``. | ||
| 5058 | To package unversioned libraries, you need to modify the variables in the recipe | ||
| 5059 | as follows:: | ||
| 5060 | |||
| 5061 | SOLIBS = ".so" | ||
| 5062 | FILES_SOLIBSDEV = "" | ||
| 5063 | |||
| 5064 | The modifications cause the ``.so`` file to be the real library | ||
| 5065 | and unset :term:`FILES_SOLIBSDEV` so that no libraries get packaged into | ||
| 5066 | ``${PN}-dev``. The changes are required because unless :term:`PACKAGES` is changed, | ||
| 5067 | ``${PN}-dev`` collects files before `${PN}`. ``${PN}-dev`` must not collect any of | ||
| 5068 | the files you want in ``${PN}``. | ||
| 5069 | |||
| 5070 | Finally, loadable modules, essentially unversioned libraries that are linked | ||
| 5071 | at runtime using ``dlopen()`` instead of at build time, should generally be | ||
| 5072 | installed in a private directory. However, if they are installed in ``${libdir}``, | ||
| 5073 | then the modules can be treated as unversioned libraries. | ||
| 5074 | |||
| 5075 | Example | ||
| 5076 | ~~~~~~~ | ||
| 5077 | |||
| 5078 | The example below installs an unversioned x86-64 pre-built library named | ||
| 5079 | ``libfoo.so``. The :term:`COMPATIBLE_HOST` variable limits recipes to the | ||
| 5080 | x86-64 architecture while the :term:`INSANE_SKIP`, :term:`INHIBIT_PACKAGE_STRIP` | ||
| 5081 | and :term:`INHIBIT_SYSROOT_STRIP` variables are all set as in the above | ||
| 5082 | versioned library example. The "magic" is setting the :term:`SOLIBS` and | ||
| 5083 | :term:`FILES_SOLIBSDEV` variables as explained above:: | ||
| 5084 | |||
| 5085 | SUMMARY = "libfoo sample recipe" | ||
| 5086 | SECTION = "libs" | ||
| 5087 | LICENSE = "CLOSED" | ||
| 5088 | |||
| 5089 | SRC_URI = "file://libfoo.so" | ||
| 5090 | |||
| 5091 | COMPATIBLE_HOST = "x86_64.*-linux" | ||
| 5092 | |||
| 5093 | INSANE_SKIP:${PN} = "ldflags" | ||
| 5094 | INHIBIT_PACKAGE_STRIP = "1" | ||
| 5095 | INHIBIT_SYSROOT_STRIP = "1" | ||
| 5096 | SOLIBS = ".so" | ||
| 5097 | FILES_SOLIBSDEV = "" | ||
| 5098 | |||
| 5099 | do_install () { | ||
| 5100 | install -d ${D}${libdir} | ||
| 5101 | install -m 0755 ${WORKDIR}/libfoo.so ${D}${libdir} | ||
| 5102 | } | ||
| 5103 | |||
| 4897 | Using x32 psABI | 5104 | Using x32 psABI |
| 4898 | =============== | 5105 | =============== |
| 4899 | 5106 | ||
