This is an old revision of the document!


OpenWrt packages

The OpenWrt system is maintained and distributed as a collection of packages.

Allmost all pieces of software found in a typical OpenWrt firmware image are provided by such a package with notable exception being the Linux kernel itself.

The term OpenWrt package may either refer to an OpenWrt source package which essentially is a directory consisting of at least an OpenWrt package Makefile describing the acquisition, building and packaging procedures for a piece of software, an optional supplemental directory with OpenWrt package patches which modify the acquired source code and optionally further, static supplemental files shipped along with the package, such as init script files, default configurations, scripts or other support files.

Furthermore, an OpenWrt package may also refer to an OpenWrt binary package which is a GNU tar compatible archive containing binary executable software artifacts along with accompanying package control files for installation on a running system, similar to Debian .deb or Linux .rpm files used on distributions such as CentOS, SuSE etc.

OpenWrt binary package are almost exclusively produced from source packages by invoking either the OpenWrt buildroot or the OpenWrt SDK in order to translate the source package Makefile descriptions into executable binary artifacts tailored for a given target system.

Allthough it is possible to manually assemble binary packages by invoking tools such as tar and placing the appropriate control files in the correct directories, it is strongly discouraged to do so since such binary packages are usually not easily reproducable and verifiable.

Source packages are developed in multiple OpenWrt package feeds hosted in different locations and following different purposes. Each package feed is a collection of source package definitions residing within a publicly or privately reachable source code repository.

Source packages describe how a piece of software has to be downloaded, patched, compiled and packaged in order to form a binary software artifact suitable for use on a running target system. They also describe relations to other source packages required either at build time or at run time.

Each source package should have a globally unique name closely resembling the name of the software described by it. OpenWrt often follows the lead of other distributions when deciding about the naming of packages and sticks to the same naming conventions in many cases.

A source package is a subdirectory within its corresponding package feed containing at least one Openwrt Makefile and optionally src, files or patches directories.

Makefile

An OpenWrt source package Makefile contains a series of header variable assignments, action recipes and one or multiple OpenWrt specific signature footer lines identifying it as OpenWrt specific package Makefile.

See Creating packages for details on Makefile contents.

The files directory

Static files accompanying a source package, such as OpenWrt specific init scripts or configuration files, must be placed inside a directory called files, residing within the same subdirectory as the Makefile. There are no strict rules on how such static files are to be named and organized within the files directory but by convention, the extension .conf is used for OpenWrt UCI configration files and the extension .init is used to denote OpenWrt specific init scripts.

The actual placement and naming of the resources within the files directory on the target system is controlled by the source package Makefile and unrelated to the structure and naming within the files directory.

The patches directory

The patches directory must be placed in the same parent directory as the Makefile file and may only contain patch files used to modify the source code being packaged.

Patch files must be in unified diff format and carry the extension .patch. The file names must also carry a numerical prefix to denote the order in which the patch files must be applied. Patch file names should be short and concise and avoid special characters such as white spaces, special characters and so on.

Suitable patch file names could look like:

  • 000-patch-makefile.patch
  • 010-backport-frobnicate-crash-fix.patch
  • 999-add-local-hack-for-openwrt-compatibility.patch

It is adviced to use Quilt to manage source package patch collections.

The src directory

Some packages do not actually fetch their program code from an external source but bundle the code to be compiled and packages directly within the package feed. This is usually done for packages which are specific to OpenWrt and do not exist outside of their respective package feed.

Sometimes the src directory may also be used to supply additional code to the compilation process, in addition to the program code fetched from external sources.

If present, the OpenWrt build system will automatically copy the contents of the src directory verbatim to the compilation scratch directory (build directory) of the package, retaining the structure and naming of the files.

A source package may depend on a number of other packages, either to satisfy compilation requirements or to enforce the presence of specific functionality, such as shared libraries or support programs at runtime on the target system.

There are two kinds of dependencies; build dependencies, specified by the PKG_BUILD_DEPENDS Makefile variable and runtime dependencies, declared in the DEPENDS variable of the corresponding define Package/... Makefile sections.

Build dependencies are resolved at package compilation time and instruct the build system to download, patch and compile each mentioned dependency before the source package itself is compiled. This is required when the compilation process of a package depends on resources such as header files from another package. Build dependencies are not transformed into runtime dependencies and should only be used when the resources of the packages being depended upon are solely required at compilation time. This usually is the case for header-only libraries such as the C++ Boost project or static .a library archives that result in no dynamic runtime requirements.

Runtime dependencies on the other hand specify the relation of binary packages, instructing the package manager to fetch and install the listed dependencies before installing the binary package itself. A runtime dependency automatically implies a build dependency, so if a DEPENDS variable within a define Package/... section of a given source package specifies the name of a define Package/... section of another source package, the build system will take care of compiling the other package before compiling the source package specifiying the runtime dependency.

Package dependencies, regardless of whether they're build-time or runtime ones, should only require packages within the same package feed or provided by the base feed located within the main OpenWrt package/ directory.

Dependencies among packages in different, non-base feeds are strongly discouraged as it is not guaranteed that each build system has access to all feeds.

Packages providing shared libraries require additional care to ensure that software depending on these libraries remains functional and is not accidentally broken by incompatible updates, changed APIs, removed functionality and so on.

While the package dependency mechanisms will ensure that the build system compiles libarary packages before the program packages requiring them, they do not guarantee that such programs are getting rebuilt when the library package itself is updated.

Also, in the case of binary package repositories, installing a newer, incompatible version of library packages would break installed programs relying on this library unless an additional version constraint is applied to the dependency.

The OpenWrt build system introduced the concept of an ABI_VERSION to address the issue of program dependencies on specific versions of a shared library, requiring exactly the ABI the program was initially compiled and linked against. The ABI_VERSION value is supposed to reflect the SONAME of the library being packaged.

Most upstream libraries contain an ELF SONAME attribute denoting the canonical name of the library including a version suffix specifying the version of the exposed ABI. Changes breaking the exposed ABI usually result in a change to the SONAME.

When a program is linked against such a library, the linker will resolve the SONAME of the requested shared object and put it into the DT_NEEDED section of the resulting program executable. Upon starting the program, the dynamic linker on the target system will consult the DT_NEEDED section to find the required libraries within the standard library search path.

Setting an ABI_VERSION variable on a library package definition will cause the buildsystem to track the value of this variable and trigger recompilations in all packages depending on this library package whenever the value is incremented. This is useful to force re-linking of all programs after a library has been changed to an incompatible version.

The ABI_VERSION value is also appended to the binary package name and all dependencies mentioning the binary library package will be automatically expanded to contain the ABI_VERSION suffix. If for example a library package libfoo specifies ABI_VERSION:=1.0, the resulting binary package will be called libfoo1.0 and when a package bar specifies DEPENDS:=+libfoo, the resulting runtime dependency will be Depends: libfoo1.0.

This ensures that incompatible updates to the libfoo library, denoted by an ABI_VERSION increase, will cause programs linked against it from then on to have a different runtime dependency, allowing the OpenWrt package manager to notice the change.

Example: when libfoo is updated to a new, incompatible version and its SONAME property changed from libfoo.so.1.0 to libfoo.so.1.1, then ABI_VERSION should be increased from 1.0 to 1.1, causing the resulting liboo runtime package to be called libfoo1.1. Source packages linking libfoo from then on, will have runtime dependencies on libfoo1.1.

When a shared library is packaged, the ABI_VERSION variable of the corresponding define Package/lib... section should be set to the SONAME of the .so library file contained within the binary package. The SONAME usually reflects the libraries internal ABI version and is incremented whenever incompatible changes to the public APIs are made within the library, e.g. when changing a function call signature or when removing exported symbols.

The public ABI tracker is useful to decide whether an ABI_VERSION change is required when updating an existing library package to a newer upstream version.

Some upstream library projects do not use a SONAME at all or do not properly version their libraries, in such cases, the ABI_VERSION must be set to a value in the form YYYYMMDD, reflecting the source code change date of the last incompatible change being made.

In order to allow multiple versions of binary library packages to coexist on the same system, each library package should only contain shared object files specific to the SONAME version of the library getting packaged.

A typical upstream library libbar with version 1.2.3 and SONAME of libbar.so.1 will usually provide these files after compilation:

libbar.so       -> libbar.so.1.2.3 (symlink)
libbar.so.1     -> libbar.so.1.2.3 (symlink)
libbar.so.1.2.3      (shared library object)

The binary libbar1 package should only contain libbar.so.1 and libbar.so.1.2.3 as the common libbar.so symlink would clash with a libbar2 package providing version 2.0.0 of libbar.

Versionless symlinks are usually not needed for libraries using the SONAME attribute and are only used during the linking phase when compiling programs depending on the library.

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
  • Last modified: 2019/01/19 23:21
  • by tmomas