Library / SDK
apache/apr avatar
apache/apr

APR gives C programs one portable interface for the things platforms do differently

Mirror of Apache Portable Runtime

534 stars219 forksCApache-2.0

At a glance

What is it?
The Apache Portable Runtime is a C library that wraps the platform-specific ways of doing threads, file I/O, memory mapping, shared memory and dynamic loading behind one API, with APR 2.0 adding utility functions absorbed from the old apr-util library. It is used by the Apache HTTP Server 2 and by Subversion, and it builds with autotools on Unix and CMake on Windows.
Who is it for?
Adopt APR if you are writing portable C and want one API for threads, files, memory-mapped I/O and shared memory instead of per-platform code, because the library covers the same ground on UNIX, Windows, Mac OS X and OS/2 and is already inside the Apache HTTP Server 2 and Subversion.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 77 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the portability guarantee actually promises

The Apache Portable Runtime Library provides a predictable and consistent interface to underlying platform-specific implementations, with an API to which software developers may code and be assured of predictable if not identical behavior regardless of the platform on which their software is built, relieving them of the need to code special-case conditions to work around or take advantage of platform-specific deficiencies or features.

Two phrases in that paragraph carry the design. Predictable if not identical behaviour is a lower promise than consistency, and it is the honest one: a mutex on one platform may not be the same object as a mutex on another, but the code you write behaves the same way. And the explicit mention of working around or taking advantage of platform-specific features is the point most portability layers skip. APR is not only about hiding the differences, it is about letting you exploit them deliberately when you want to.

APR and its companion libraries are implemented entirely in C and provide a common programming interface across a wide variety of operating system platforms without sacrificing performance. The supported platforms are UNIX variants, Windows, Mac OS X and OS/2.

The primary core subsystems of APR 1.3 are the ones you would expect from a systems library: atomic operations, dynamic shared object loading, file I/O, locks such as mutexes and condition variables, memory management with high performance allocators, memory-mapped files, multicast sockets, network I/O, shared memory, thread and process management, and various data structures including tables, hashes and priority queues.

The primary language is C, the licence is Apache-2.0, the default branch is trunk, and the last push was on 2026-08-07. There are no GitHub releases, and the repository description calls it a mirror of the Apache Portable Runtime, which is worth noting: the canonical source lives in the Apache SVN repository, and this copy is a git mirror of it.

APR 2.0 absorbed apr-util, and that changed what the library covers

APR 2.0 also provides a number of utility functions and library compatibility interfaces. These were formerly part of APR-util, a separate utility library in the version 1 releases.

The list of what moved is long and covers a very wide surface: hashing and UUID services, multiple SQL DBD client interfaces, multiple flat-database DBM client interfaces, a typesafe function Hooks abstraction, a MemCache interface, date parsing routines, resource lists, thread pools, queues, relocatable memory management functions, string filename-style pattern matching, URI parsing, charset translation based on iconv, and XML parsing based on expat.

So the modern APR is closer to a general-purpose systems toolkit than to the threading and files library that the name suggests. If you are evaluating APR for a new project, the utility half is often the more useful part, because thread pools, queues and hashing are exactly the things that get reinvented badly.

The merge also has an effect on how you should think about the dependency. In the 1.x era there were two libraries to link, apr and apr-util. In 2.0 there is one, and the DBD and DBM client interfaces that used to live in apr-util are now part of the main distribution.

That merge is also why the database provider section in the README is more than a footnote. Interfaces for the copy-left licensed MySQL and gdbm DBD drivers, and for Berkeley DB DBM, all ship as part of the distribution, but to avoid licensing incompatibilities they are not built by default. To enable support you use the --with-{provider} option, and the README warns that these licenses may introduce licensing implications for your compiled code. The bindings for proprietary drivers such as Oracle must also be explicitly enabled, and whenever you distribute apr-util in combination with database client drivers you are told to always review the license requirements of all components.

That is an unusual thing to have to think about in a systems library, and it is a real consequence of pulling the database bindings into the core.

Building on Unix, and the trap in passing compiler flags

The Unix build is autotools, and the README gives the sequence directly:

bash
   ./configure --prefix=/desired/path/of/apr
   make
   make test
   make install

If you are building from a Subversion checkout rather than a tarball, there is a prerequisite step. You must have autoconf, libtool and python installed, and the prerequisite is simply to run:

bash
  ./buildconf

From a distribution tarball, buildconf has already been run for you, and you do not need autoconf, libtool or python unless you have patched APR's buildconf inputs, such as configure.in, build.conf, virtually any file within the build/ tree, or you add or remove source files. And when updating from svn you must rerun ./buildconf to effect any changes to the build schema in your fresh update.

That last point is the one that catches people. The build schema is generated, and a stale generated tree after an update produces a build that does not match the sources.

The configure step has a subtlety the README spells out with an example:

bash
  CC="gcc -m64" ./configure --prefix=/desired/path/of/apr

That form informs APR that you are compiling to a 64 bit CPU, and autoconf must consider that when setting up all of APR's internal and external type declarations. The general warning is that some flags must be passed as part of the CC command, itself, in order for autoconf to make the right determinations.

For verbose test output the README points at the testall runner in the test directory, which can be invoked with a verbose flag after cd test. The separate test directory and the make test target are how the library's own suite runs.

Coverage data is also documented, with a sequence that runs buildconf, configures with coverage flags in both CFLAGS and LDFLAGS, builds, runs the tests and then makes gcov.

Windows and CMake, and the Visual Studio route

APR uses CMake to build on Windows, and the README gives two ways to do it.

The command line route:

bash
  cmake -B out/build -G Ninja -DCMAKE_INSTALL_PREFIX=out/install
  cmake --build out/build
  cmake --install out/build

The Visual Studio route is a three-step manual procedure. You make sure that C++ CMake tools for Windows component is installed, you use the Visual Studio Open Folder command to open the APR source code directory, and you use the Build command to build APR. The README points to README.cmake for more information about CMake options.

The split of build systems between platforms is a real cost of the project and a real cost for you. A library that wants to build everywhere from a checkout has to carry an autotools tree and a CMake tree, and every source change has to keep both working. The Makefile.in, configure.in, buildconf, build.conf and apr-config.in files at the top level are the autotools side, and the CMakeLists.txt, README.cmake and SConstruct are the other side. There is also an SConscript, so a third build system is carried.

The Visual Studio path deserves a note because it is unusual. Opening the source folder rather than a solution file means Visual Studio uses CMake natively to discover the targets, which avoids the step of generating a solution. It works for a developer building the library, but it is not the path for producing the distribution packages.

For Linux packagers the README documents the RPM route, which is the standard rpmbuild sequence: rpmbuild -ts to create the source RPMs from the tarballs, then rpmbuild -tb to build the binary RPMs, with dependencies resolved as appropriate. Two packages are built, apr and apr-util, which is a leftover from the 1.x split and a reminder that the utility library still ships as its own package even though the source has been merged.

The repository also carries a README.FREETDS, which is about a specific downstream integration with the FreeTDS database driver.

The directory tree, which is the API in outline

The top-level entries are the clearest documentation APR has, because each directory is named after the subsystem it implements, and the same naming appears in the API.

There is atomic/ for atomic operations, dso/ for dynamic shared object loading, file_io/ for file I/O, locks/ for mutexes and condition variables, memory/ for the allocators, mmap/ for memory-mapped files, network_io/ for network I/O, shmem/ for shared memory, threadproc/ for thread and process management, tables/ for the table data structure, and poll/ for the polling abstraction.

Then the utility half that arrived with APR 2.0. There is crypto/ and jose/ for the cryptographic and JSON object signing pieces, json/ for JSON, encoding/ for charset translation, uri/ for URI parsing, strings/ and strmatch/ for string handling and filename-style pattern matching, random/ for random numbers, time/ for date and time parsing, hooks/ for the typesafe function hooks abstraction, memory/ for the relocatable memory management functions. The thread pools live in threadproc/ alongside the threading, and the resources abstraction is in support/.

The database client interfaces are in their own directories, dbd/ for the SQL DBD drivers and dbm/ for the flat database DBM drivers,. The memcache/ directory holds the MemCache interface, passwd/ the password handling, helpers/ and misc/ the odds and ends, and tools/ the utilities.

Two other directories are unusual and worth naming. The redis/ directory suggests a Redis client interface alongside the MemCache one, and the json/ and jose/ pair suggests the project has moved into JSON handling and JSON object signing and encryption, which is a considerably more modern remit than the original portability brief.

The include/ directory is the public header surface, docs/ holds the documentation, test/ the test suite, and the emacs-mode/ directory is a leftover from the era when editors needed help with the coding conventions.

Where APR is the wrong choice

Three limits, and the first is about what a portability layer costs you.

The first is the abstraction cost. Every APR call is a function call into a layer that then calls into the operating system, and where the platform offers a better primitive than the portable one, APR sometimes gives you the portable one anyway. The README's own framing admits that behaviour is predictable if not identical, which is the honest way of saying a Windows condition variable and a POSIX condition variable are not the same object with a different name. On a codebase that only targets one platform, that indirection is pure cost, and the platform's own primitives are usually faster and better documented.

The second is the age and the direction of travel. The README describes APR 1.3 as the core and notes that users of APR 0.9 should be aware that migrating to the 1.x programming interfaces may require adjustments, since APR 1.x is neither source nor binary compatible with earlier 0.9 releases. Users of 1.x can expect consistent interfaces and binary backwards compatibility throughout the entire 1.x release cycle, as defined in the versioning rules.

The 1.x guarantee is the thing to notice. Binary compatibility across a major series means you can take a new APR release and drop it in without relinking your application, which for a library whose consumers are large deployments like the Apache HTTP Server is the whole point. But it also means the API cannot move. New subsystems get added, and the utility half from apr-util arrived as an addition rather than a redesign.

The third is the maintenance burden of the build itself. Two build systems, a generated build schema that must be regenerated after an update, an autotools prerequisite for anyone working from a checkout, and a package split that still produces separate apr and apr-util RPMs. None of that is APR's fault as a design, and all of it is what a project that has to build on Windows, three Unix families and OS/2 accumulates.

The alternative approach for most new work is the language's own standard library. If you are writing C, the C standard library plus POSIX gives you files, and the platform threading APIs are what every other C program on that platform uses. The trade is that you give up the portability, and that is only worth it if you are actually shipping on more than one platform.

There is a second alternative worth naming for existing software. If your project is already an Apache HTTP Server or Subversion deployment, APR is not a choice at all: it is already linked in, and following the project's own conventions means using it. That is the situation where APR makes the most sense, and it is why the library has survived this long.

Editorial conclusion

Adopt APR if you are writing portable C and want one API for threads, files, memory-mapped I/O and shared memory instead of per-platform code, because the library covers the same ground on UNIX, Windows, Mac OS X and OS/2 and is already inside the Apache HTTP Server 2 and Subversion. Do not adopt it for a new codebase that can use a language with these facilities in its standard library, since APR is a C library for a portability problem that many languages solved differently. Verify first that your platform is one of the four listed, that you read the licensing implications of the database providers before enabling any of them, and that you build from a distribution tarball rather than from a checkout unless you are prepared to install autoconf, libtool and python and run buildconf yourself.

Frequently asked questions

What is the Apache Portable Runtime and what does it abstract?

It provides a predictable and consistent interface to underlying platform-specific implementations, so developers get predictable if not identical behavior on any platform without coding special cases. It is implemented entirely in C and covers UNIX variants, Windows, Mac OS X and OS/2.

What changed between APR 1.x and APR 2.0?

APR 2.0 added utility functions and library compatibility interfaces that were formerly part of APR-util, a separate utility library in the 1.x releases. The absorbed set includes hashing and UUID services, SQL DBD and flat-database DBM client interfaces, a typesafe function hooks abstraction, a MemCache interface, thread pools, queues, URI parsing, iconv-based charset translation and expat-based XML parsing.

How do I build and install APR on Unix?

Run ./configure --prefix=/desired/path/of/apr, then make, make test and make install. If you are building from a Subversion checkout you first need autoconf, libtool and python installed and must run ./buildconf, and you must rerun it after any update that changes the build schema.

How do I build APR on Windows?

APR uses CMake on Windows. The command line route is cmake -B out/build -G Ninja with a CMAKE_INSTALL_PREFIX, then cmake --build and cmake --install. Alternatively, install the C++ CMake tools for Windows component in Visual Studio, open the APR source directory with the Open Folder command and use the Build command.

Do I need to enable the database providers in APR?

No, and that is deliberate. Interfaces for the copy-left licensed MySQL and gdbm DBD drivers and for Berkeley DB DBM ship with the distribution but are not built by default, to avoid licensing incompatibilities. You enable them with the --with-{provider} option, and the README warns these licences may introduce licensing implications for your compiled code, and that proprietary bindings such as Oracle must be enabled explicitly.

Which projects already depend on APR?

The README says APR is already used extensively by the Apache HTTP Server version 2 and by the Subversion revision control system, to name a few, and it points to the project's list of known users, asking readers to let the maintainers know if they find the libraries useful in their own projects.

Official sources

  1. apache/apr on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/apache-apr.svg)](https://hysenlabs.com/projects/apache-apr)

Was this useful?