# libbpf: the stand-alone build of the BPF CO-RE library

> This repository is the packaging and submodule mirror for libbpf, not the place where the library is developed. Here is what that means for installs, versions and contributions.

**libbpf/libbpf** — Automated upstream mirror for libbpf stand-alone build.

- Repository: https://github.com/libbpf/libbpf
- Stars: 2,756 · Forks: 508
- Language: C
- License: NOASSERTION
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/libbpf-libbpf

## What libbpf solves, and why the mirror exists

libbpf is a C library for loading and interacting with BPF programs from user space. The README describes it as the official home of the library, with the authoritative source developed inside the bpf-next Linux source tree under tools/lib/bpf and periodically synced to GitHub. The repository you are reading is that sync target. That split is the first thing to understand, because it determines where bugs are fixed and where pull requests go.

The README is explicit: all libbpf changes should be sent to the BPF mailing list, and PRs here should be opened only for GitHub-specific parts, for example the GitHub-specific Makefile. So the mirror is a distribution and packaging convenience, not a development fork. The README lists the benefits of packaging from the mirror over packaging from kernel sources: consistent versioning across distributions, and no ties to any specific kernel.

Who it is for: distribution packagers, and developers who want libbpf as a Git submodule in their own project. The README says to use this GitHub repository for building and packaging libbpf and when using it through a Git submodule. If you are writing a BPF application in C and want it to run on a target machine without a compiler, this is the library you link against.

## BPF CO-RE is the actual mechanism

The reason libbpf is worth packaging separately from BCC is CO-RE, which the README expands as Compile Once, Run Everywhere. The contrast it draws is with BCC: CO-RE applications do not require Clang/LLVM runtime on the target servers, and they do not rely on kernel-devel headers being present.

That portability does not come free. It relies on the kernel being built with BTF type information. The README lists distributions whose kernels ship BTF already: Fedora 31 and later, RHEL 8.2 and later, OpenSUSE Tumbleweed, Arch Linux from kernel 5.7.1.arch1-1, Manjaro from kernel 5.4 if compiled after 2021-06-18, Ubuntu 20.10, and Debian 11 on amd64 and arm64. Everything outside that list is your problem to solve.

The README gives the check directly: look for /sys/kernel/btf/vmlinux. If it is absent, you have to build a custom kernel with CONFIG_DEBUG_INFO_BTF=y and use pahole 1.16 or newer, part of the dwarves package, to convert DWARF to BTF. That is a real constraint on where a CO-RE binary can be deployed, and it is the single most common reason a working build fails on an older host.

To develop and build the BPF programs themselves you need Clang/LLVM 10 or newer. The README lists Fedora 32 and later, Ubuntu 20.04 and later, Arch Linux, Ubuntu 20.10 with LLVM 11, Debian 11 with LLVM 11, and Alpine 3.13 and later as having that packaged by default. Note the asymmetry: the compiler is needed on the build machine, not on the machine that runs the compiled object.

## Building libbpf from this mirror

libelf is an internal dependency, so it must be installed on the system for applications to link and work. pkg-config is used by default to locate libelf, and the program it calls can be overridden with PKG_CONFIG. If you do not want pkg-config involved at build time, the README says to set NO_PKG_CONFIG=1 when calling make.

To build both the static libbpf.a and the shared libbpf.so, the README gives this sequence. You should end up with both artifacts in the src directory.

```bash
$ cd src
$ make
```

For a static-only build, the README shows how to place objects in build/ and install the library together with the headers into a staging directory root/. The environment variables are BUILD_STATIC_ONLY, OBJDIR and DESTDIR.

```bash
$ cd src
$ mkdir build root
$ BUILD_STATIC_ONLY=y OBJDIR=build DESTDIR=root make install
```

If libelf lives somewhere non-standard, for example under /build/root/, the README points pkg-config at it with PKG_CONFIG_PATH and installs into the same prefix. This is the pattern you want when cross-compiling or when a distribution build must not touch the host's pkg-config search path.

```bash
$ cd src
$ PKG_CONFIG_PATH=/build/root/lib64/pkgconfig DESTDIR=/build/root make install
```

Before writing any user-space code, confirm the target kernel exposes BTF. The README uses this check and shows the expected shape of the output.

```shell
$ ls -la /sys/kernel/btf/vmlinux
-r--r--r--. 1 root root 3541561 Jun  2 18:16 /sys/kernel/btf/vmlinux
```

For a working first application, the README does not walk through one. It points to libbpf-bootstrap and its companion blog post, and to libbpf-tools in the iovisor/bcc repository as real-world examples. Those are the places to copy a starting layout from; this repository is the library, not the scaffold.

## Where this repository is the wrong place to work

The most consequential limitation is procedural, and it is easy to miss. If you file an issue or open a pull request here about library behaviour, you are in the wrong queue. The README states that authoritative development happens in bpf-next under tools/lib/bpf, that changes should go to the BPF mailing list, and that this repository's PRs and issues should be opened only for issues about how this mirror is set up and organized.

There is a second, quieter cost: version skew between the mirror and the kernel tree. Because the mirror is synced periodically, the README's framing of consistent versioning across distributions is a statement about packaging, not a guarantee that the mirror is at the same commit as any given kernel. The repository carries SYNC.md, BPF-CHECKPOINT-COMMIT and CHECKPOINT-COMMIT at the top level, which is where that sync state is recorded. If you need to know exactly which upstream revision a tag corresponds to, that is the file to read, not the release page.

Deployment is the third boundary. This is a C library for CO-RE applications. If your target kernels lack BTF and you cannot rebuild them, libbpf's portability story does not apply to you, and the README's own remedy is a custom kernel build with pahole. That is a heavier commitment than installing a runtime dependency, and it should be weighed before choosing the CO-RE route at all.

## libbpf against BCC, aya and libbpf-rs

The README names BCC as the comparison point, and the difference is architectural rather than cosmetic. BCC compiles and injects BPF programs at runtime, which is why the README says BCC-based applications require Clang/LLVM runtime deployed on target servers and rely on kernel-devel headers. libbpf with CO-RE moves that work to build time, producing an object that the library loads on the target. The trade is that you now depend on kernel BTF instead of on a compiler and headers. The README also links a HOWTO for converting from BCC to libbpf, which tells you the maintainers treat these as two states of the same tooling rather than unrelated projects.

For Rust, the relevant names are aya and libbpf-rs. They are not the same kind of thing. aya is a Rust-native BPF library, while libbpf-rs is a Rust wrapper around the C library described here, so choosing it means keeping a C dependency in your build. This repository does not document either one, and the README's examples are C. If your team writes Rust and wants no C toolchain in the picture, that decision is made outside this repository, and nothing here will help you make it.

One more alternative is simply not using the mirror: taking libbpf from your distribution's package, or from the kernel tree directly. The README lists Fedora, Gentoo, Debian, Arch, Ubuntu and Alpine as distributions packaging libbpf from this mirror, so for many users the practical answer is to install the packaged version and never run make at all.

## Maintenance, licensing and what a version bump costs

The repository is not archived, and the last push was on 2026-09-15. The most recent release listed is v1.7.0 from 2026-03-16, after v1.6.3 on 2026-02-04 and v1.6.2 on 2025-08-21. The cadence between those tags is uneven, which is consistent with a mirror that follows upstream rather than a project running its own release train.

That has a direct cost for anyone pinning a version. Upgrading means moving to a new tag and re-checking that your BPF objects still load, because the library and the kernel-side verifier move independently. The README does not document rollback, and it does not describe a compatibility policy between libbpf releases and kernel versions. If your deployment pins a libbpf tag across a fleet with mixed kernels, that gap is something you have to close yourself.

Licensing needs care here. The repository is classified as NOASSERTION, and the top level contains both LICENSE.BSD-2-Clause and LICENSE.LGPL-2.1-only alongside LICENSE. That combination is typical of BPF tooling, where different parts carry different terms, but the split is not explained in the README. Read the individual files and the headers of the sources you actually link before you ship, and get your own legal review; nothing in this article is legal advice.

## Conclusion

Adopt this mirror if you are packaging libbpf for a distribution, vendoring it as a Git submodule, or writing a CO-RE C application that must run on kernels without Clang/LLVM installed. Do not adopt it if you expect pull requests to be merged here, or if you are working in Rust and want a safe wrapper: libbpf-rs and aya are separate projects. Before you commit, check that /sys/kernel/btf/vmlinux exists on every target kernel and that your toolchain is Clang/LLVM 10 or newer, then read SYNC.md to see which upstream commit this mirror currently tracks.

## FAQ

### What is libbpf?

It is a C library for loading and interacting with BPF programs from user space, and this repository is the official stand-alone build and submodule mirror of it. The authoritative source is developed in the bpf-next Linux tree under tools/lib/bpf and synced here periodically.

### How do I install libbpf on Ubuntu?

The README does not give distribution install commands. It lists Ubuntu among the distributions that package libbpf from this mirror, and documents building from source instead: cd src followed by make produces libbpf.a and libbpf.so. libelf must be installed on the system first, since it is an internal dependency.

### How do I build libbpf from source?

From the src directory, running make builds both the static libbpf.a and the shared libbpf.so. For a static-only staging install the README uses BUILD_STATIC_ONLY=y OBJDIR=build DESTDIR=root make install, and pkg-config can be bypassed with NO_PKG_CONFIG=1.

### What is the difference between libbpf and BCC?

According to the README, CO-RE applications built with libbpf do not require Clang/LLVM runtime on target servers and do not rely on kernel-devel headers being available, while BCC-based applications do. The trade is that libbpf CO-RE depends on the kernel being built with BTF type information.

### How is libbpf related to aya and libbpf-rs?

The README does not cover either project, so it documents no relationship. The distinction that matters for a choice is that aya is a Rust-native BPF library while libbpf-rs wraps this C library, which keeps a C dependency in the build.

## Sources

- [Issues](https://github.com/libbpf/libbpf/issues)
- [libbpf/libbpf on GitHub](https://github.com/libbpf/libbpf)
- [README](https://github.com/libbpf/libbpf/blob/master/README.md)
- [Releases](https://github.com/libbpf/libbpf/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/libbpf-libbpf
