Red Hat Enterprise Linux 9: Application Compatibility Guide

Updated -

Red Hat Enterprise Linux 9:
Application Compatibility Guide
May 2022

Note: This article discusses application compatibility for Red Hat Enterprise Linux 9. For Red hat Enterprise Linux 8, please see the Red Hat Enterprise Linux 8: Application Compatibility GUIDE.

Table of Contents

Executive summary

This guide is intended to provide software developers with Red Hat’s guidelines regarding support of third-party applications across multiple releases of the Red Hat® Enterprise Linux® platform. ISV and customer applications can reduce or avoid migration issues between major and minor Red Hat® Enterprise Linux® versions by following these guidelines during application development.

This document describes the recommended uses of the system application programming (API) and binary interfaces (ABI) that are intended to provide compatibility across Red Hat® Enterprise Linux® releases. It outlines the tiered framework under which applications are considered compatible or not compatible.

Introduction

The purpose of this document is to provide guidance regarding the stability of applications and libraries written for RHEL and run under newer releases of RHEL. The document focuses primarily on issues of software backwards-compatibility. Although backwards compatibility is the goal, development of new capabilities or security concerns sometimes makes that impractical. Hence, the guidelines and published policy may sometimes be overridden by the objective of providing our customers with the most competitive, secure, and capable systems possible; situational testing is always recommended.
If additional clarification of these compatibility guidelines is required, please contact your Red Hat representative.

Terminology

The following are basic terms used in this document:

  • Application programming interface (API)
    An API is a public interface implemented by a software program that enables it to interact with other software, including operating system components. The API is enforced at compile time and determines source compatibility, that is, whether application source code will compile similarly across different versions of the operating environment. It covers details such as:

    • C and C++ headers for developer use

    • Language syntax, but only where it applies to a published standard

    • Public interface definitions

    • Command line interfaces, but only where it applies to documented public interfaces

  • Application binary interface (ABI)
    An ABI is a set of runtime conventions that interact with a compiled binary representation of a program. The ABI is enforced at runtime and it describes the low-level interface between an application and the operating environment. It covers details such as:

    • Data type, size, and alignment

    • Layout of aggregate types, C++ run-time type information, virtual tables

    • The calling standard, which defines how function arguments are passed and return values retrieved

    • The binary format of object files and program libraries

    • Presence and format of (asynchronous) unwinding information

    • Function and / or data symbol names and their versions, and symbol sizes (for data symbols)

    • Bytecode or any intermediate representation and the public interfaces to the virtual machine

      Tools such as compilers, linkers, runtime libraries, and the operating system itself needs to work with the ABI. The output of CLI tools is not considered a stable ABI.

  • ABI conformance
    A compiler conforms to an ABI if it generates code that follows all of the specifications enumerated by that ABI. A library conforms to an ABI if it is implemented according to that ABI. An application conforms to an ABI if it is built using tools that conform to that ABI and does not contain source code that changes behavior specified by the ABI or that otherwise bypasses the ABI.

  • Binary compatibility
    Binary compatibility means application binaries that are compiled for a specific ABI, generally for a combination of RHEL and a particular hardware architecture, will load and run similarly across different versions of RHEL. Application binaries consist of executable files, Dynamic Shared Objects (DSO), source, bytecode for interpreted just-in-time compiled languages, and their required data files.

  • Core persistent system infrastructure
    The core persistent system infrastructure refers to interfaces and externally available data structures that represent system state or provide a means of communicating with the system (for instance, system calls and header files).

  • Compatibility in a virtualized environment
    Virtual environments emulate bare-metal environments such that unprivileged applications that run on bare-metal environments will run, unmodified, in corresponding virtual environments. Virtual environments present simplified abstracted views of physical resources, so some differences may exist.

  • Compatibility in a containerized environment
    Container environments provide isolation from the host OS, and at a minimum allow the application to run in an isolated manner from the host OS libraries and binaries, but still share the same OS kernel as all other containers on the host.

  • Major and minor releases
    A Red Hat major release represents a significant step in the development of a product (wholesale changes are usually reserved for major releases). Minor releases appear more frequently within the scope of a major release and generally represent smaller, incremental developmental steps.

  • Component
    An installable language, application, database, or other functional set of packages that run on RHEL. Components are made available in a number of formats, please see the Package manifest for more details.

  • SystemTap static probes
    SystemTap static probes are part of the SystemTap profiling and tracing framework. The probes are integrated into key system libraries to support profiling and debugging of applications and libraries.

  • File Hierarchy Standard (FHS)
    A file system structure which defines the names, locations, and permissions for various file types and directories. FHS-compliant file systems are compatible with each other and have the ability to mount a /usr/ partition as read only. The latter is important because the partition contains common executables and should not be changed by users.

  • CodeReady Linux Builder repository
    The CodeReady Linux Builder repository contains components that a developer would use during the development of their RHEL application, but which are not intended to be deployed in production. Please see the CodeReady Linux Builder reference within the Red Hat Enterprise Linux 9 Package manifest for further details.

Compatibility levels

All components and packages in Red Hat Enterprise Linux are classified under one of the following four compatibility levels:

  • Compatibility level 1

    • APIs and ABIs are stable within the lifetime of a major release and ABIs are also stable across the next two major releases; the release that introduces a new or revised ABI, and the two following major releases (n, n+1, n+2). In the case of this document, release n starts with Red Hat Enterprise Linux 9. If a change to a library causes an incompatibility with existing binaries, a separate version of the library will be provided with the older ABI to run the application without modification.
  • Compatibility level 2

    • APIs and ABIs are stable within the lifetime of a single major release. Compatibility level 2 application interfaces will not change from minor release to minor release and can be relied upon by the application to be stable for the duration of the major release. Compatibility level 2 is the default for packages in Red Hat Enterprise Linux 9. Packages not identified as having another compatibility level may be considered compatibility level 2.
  • Compatibility level 3

    • This level applies to languages, tools, and applications included in Red Hat Enterprise Linux as Application Streams. Please see Red Hat Enterprise Linux Application Streams Life Cycle for details. Each component will specify a lifetime during which the API and ABI will be supported. Newer versions (e.g. PHP 8.1 and PHP 8.2) will attempt to be as API and ABI compatible from version to version as possible. Version to version compatibility is not guaranteed, however.

    • Components and developer tools that receive continuous updates, referred to as rolling streams, should be considered compatibility level 3. Please see Red Hat Enterprise Linux Application Streams Life Cycle for details. Developers should use caution and understand how these components change with each release.

  • Compatibility level 4

    • No compatibility is provided. ABI and API can change at any point. These components should not be used by applications needing long term support.

Notes on compatibility levels

Compatibility levels for bare-metal configurations also apply to virtualized and containerized configurations except for any features that directly interact with hardware. Those features directly related to hardware have no API or ABI compatibility level. For example, applications that rely on Graphics Processing Unit (GPU) features cannot expect binary compatibility.

Red Hat requests that application developers validate that any behavior they depend on is explicitly defined in formal API documentation to prevent introducing dependencies on unspecified implementation-specific behavior or dependencies on bugs in a particular implementation of an API. For example, new releases of the GNU C library (glibc) may not be compatible with older releases if an application uses an undocumented API or relies on undefined behavior.

Your support representative will be happy to guide you through any specific questions you may have.

Compatibility exceptions

The following are exceptions to compatibility in RHEL.

SystemTap static probes

  • No assurances are made at this time that integrated SystemTap static probes will continue to have the same probe name, probe location, or interpretation or number of arguments. Since the probes are primarily designed for deep analysis and debugging, the probes must be able to change as the underlying implementation changes.

Static linking with the C/C++ runtime

  • Static linking with the C/C runtime is not supported. This includes linking with any files that are part of the `glibc-static` or `libstdc`-static packages. You may choose to link statically, but the resulting application binaries may fail to operate if any package in the installation is changed.

C/C++ application sanitizers

  • C/C++ applications built with the compiler option -fsanitize=[option] cannot participate in the API or ABI guarantees provided in this document. The sanitizer libraries which implement the sanitizer runtimes are part of Compatibility Level 4 and have no compatibility guarantees.

CodeReady Linux Builder repository

  • All packages in the CodeReady Linux Builder repository are unsupported. Packages in this repository are maintained for use by developers, often for specific use cases. Developers are welcome to use these packages understanding that no compatibility levels apply.

  • If a binary RPM in the distribution contains features accessible only through a CodeReady Linux Builder development package, such as headers or shared object symlink, then those features should be considered as if they were available only in CodeReady Linux Builder.

Guidelines for preserving binary compatibility

Red Hat recommends that application developers adopt the following principles in order to improve binary compatibility:

  1. Use only libraries and applications listed in the compatibility level that suits your application needs.

  2. Build applications using the published interfaces of a library. Non-published (internal) interfaces are subject to change at any time, which can cause instability in the dependent application if relied upon.

    • If the library provides a development package, you must install and use that development package, including any provided headers, for your own development. If the library does not provide a development package or does not provide a set of headers and shared object for linking, then the API and the ABI of that library is not covered by any compatibility guarantees.

    • You must link with all libraries that are required by your application. Failing to link against all required libraries is called “underlinking.” An underlinked application cannot take advantage of ABI compatibility.

    • If the application dynamically calls an ELF versioned symbol, it must use the glibc dlvsym API in order to request that specific symbol at that specific version. If you use the dlsym API (no version specified), you always get the latest version of the symbol, and thus the latest API behavior, which may not be suitable for your application.

  3. An application is only guaranteed to run correctly if it executes in an environment that is as new as the environment it was built in or newer. For example, compiling your application on Red Hat Enterprise Linux 9.0 means your application is only guaranteed to run correctly on Red Hat Enterprise Linux 9.0 or later depending on the compatibility level of the components you depend upon.

  4. Application developers should validate that any behavior they depend on is described in the published API documentation to prevent introducing dependencies on unspecified implementation-specific semantics or introducing dependencies on bugs in a particular implementation of an API. For example, new releases of the GNU C library are not guaranteed to be compatible with older releases if the old behavior was not consistent with a published specification.

  5. Avoid static linking of libraries (C/C++). Static linking causes the executables to have their own version of the library. This increases the chance of an application not running predictably on a later version of the operating system as these library dependencies might have changed along the way. Linking applications dynamically is strongly recommended in order to avoid this problem.

  6. Package applications using the RPM mechanism. RPM provides a software-packaging mechanism that includes a detailed specification of application dependencies. When creating RPMs, the following should be kept in mind:

    • Explicitly state all required runtime and build dependencies using the appropriate RPM syntax. It is recommended you rely on automatic dependency tracking where possible and avoid disabling automatic depenencies via AutoReqProv, AutoReq, and AutoProv tags.

    • Do not modify, replace, or recompile files managed by Red Hat-provided packages. Doing so may lead to unpredictable behavior.

    • When considering dependencies, do not assume that all possible packages will be installed on every Red Hat Enterprise Linux system. The default installed packages may change between major releases, between product variants of the same version, and on a customer’s system. Always depend on all the packages your application needs to work and do not expect that transitive dependencies will remain unchanged.

  7. Follow the Filesystem Hierarchy Standard (FHS) version 2.3 or higher when installing programs. Third-party software should be installed to the '/opt' subdirectory. More information on the FHS is available at http://www.pathname.com/fhs/.

  8. Do not design applications that rely on configuration files provided by system packages or other components. These files can change between versions unless the upstream community is explicitly committed to preserving them.

  9. Do not install packages, modules, or other global identifiers with the same names as system components shipped by Red Hat. This includes RPM package names (including Provides), shared object names (sonames, e.g. libpthread.so.0), and symbol names (e.g. log), but also Python package names, and D-Bus endpoints used by the systems.

  10. If you require functionality from a component that is currently not listed in any of the application compatibility levels, or if you would like a component to be moved to a different compatibility level, please contact your support representative for review.

  11. Do not depend on components with a shorter compatibility guarantees than your application. Please see Compatibility levels for specific packages and libraries for a list of packages and their compatibility level.

  12. Do not depend on a specific Linux kernel version. Avoid reading from proc, sys, and debug filesystems, or any other pseudo-filesystem. Avoid using ioctls to directly interact with hardware.

Note: During the life cycle of a major release, Red Hat makes commercially reasonable efforts to maintain the binary compatibility of the runtime environment across all minor releases and errata advisories. If necessary, Red Hat may make exceptions to this compatibility goal for critical impact security or other significant issues. Furthermore, as described above and in Compatibility levels for specific packages and libraries, major releases of Red Hat Enterprise Linux contain a limited set of backward-compatible libraries included in previous major releases to allow for the easy migration of applications. Typically, Red Hat applies changes in such a way as to minimize the amount of change and to maintain binary compatibility.

Compatibility levels for specific packages and libraries

For each compatibility level Red Hat defines the binary packages which provide APIs and ABIs that are part of the compatibility level. The specific compatibility level for each package can be reviewed within the Red Hat Enterprise Linux 9 Package manifest.

Comments