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