Library / SDK
google/cpu_features avatar
google/cpu_features

cpu_features: asking the CPU what it can do at runtime

A cross platform C99 library to get cpu features at runtime.

2,620 stars310 forksC++Apache-2.0

At a glance

What is it?
A small cross-platform C library from Google that answers the question every portable performance library needs to ask, and whose maintenance burden is visible in how often its AArch64 tables are refreshed against new Linux kernels.
Who is it for?
cpu_features is worth adopting when your code runs on more than one architecture and branches on instruction availability at runtime, since it replaces a pile of per-platform conditionals with one header and one call, and it keeps those conditionals correct as new hardware ships. It is not worth adopting for a project that compiles for one fixed target, where a compile-time check does the same job with less code.
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 10 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 8, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A detection shim for code that must run on more than one CPU

The library's stated job is one sentence long: retrieve CPU features, such as available instructions, at runtime. That is deliberately a smaller promise than a dispatch layer or a math library. There is no kernel selection, no function multiversioning machinery, no runtime code patching. You get an answer to a question, and you decide what to do with it.

That narrowness is the design. A library that tries to be a portable SIMD dispatcher becomes something you must trust with correctness, since it picks the implementation and a wrong pick is a wrong answer. A library that only reports what the hardware supports stays out of that category, and the calling code keeps the branch visible where a reader can see it.

The interesting part is what that question costs to answer portably. There is no single instruction that reports features across architectures, so each architecture and operating system combination needs its own detection path, and the results have to be presented behind one interface. The repository description calls it a C99 library and the README calls it a cross-platform C library, while GitHub lists the primary language as C++, which is a fair reflection of a codebase that is C headers and C sources with C++ test and build machinery around it.

The CI matrix is the real specification

Rather than prose, the README leads with a support table crossing seven architectures against three operating systems, with each cell covering CMake, Bazel and Zig builds. The architectures are amd64, AArch64, ARM, MIPS, POWER, RISCV and s390x. The operating systems are Linux, macOS and Windows.

The pattern in that table is more informative than a green tick would be. The amd64 row has live badges in all three operating system columns. Every other architecture has live badges in the Linux column and greyed n/a markers for macOS and Windows. So the honest summary is that this is a Linux library with broad architecture coverage, and that amd64 support is the one combination verified everywhere. Any plan to ship this on a Mac or on Windows and rely on it for ARM is not backed by the project's own CI.

The badges are generated rather than maintained by hand, which is a small but telling detail. The README says the lines come from a script, scripts/generate_badges.d, that can be run online, so the table cannot silently drift out of date relative to the workflows it reports. For a library whose entire job is accuracy about hardware, having the support matrix be machine-derived is the right call.

AArch64 is where the ongoing maintenance goes

Read the release notes as a sequence and one fact dominates: the AArch64 feature tables are refreshed against Linux kernel versions over and over. The 0.10.0 release updated AArch64 features to Linux 6.6, a later change in the same line moved them to Linux 6.10.6, and the 0.11.0 release moved them again to Linux 6.12.

That is not busywork. On AArch64, feature availability is exposed by the kernel through hardware capability interfaces that gain new bits as the kernel evolves, so a library that wants to report whether a given instruction is usable has to know the layout the running kernel uses. A stale table is not a build error, it is a wrong answer at runtime on exactly the newest machines, which is the population you most wanted to support.

The same releases show the test infrastructure chasing hardware. The aarch64_linux_bazel workflow was moved to run on an ARM processor rather than emulated, QEMU was bumped for the emulated paths, and the 0.11.0 release switched CI to macos-15-intel runners. The FreeBSD Arm64 support added in 0.10.0 fits the same pattern: broad platform reach, maintained one architecture and one kernel interface at a time.

New silicon shows up as a release entry

The clearest way to see how this library is used is to look at what each release adds. Version 0.11.0, published in June 2026, added support for AMD Zen 5, Intel Arrow Lake and Intel Lunar Lake microarchitectures. That is the whole point of the project: a program compiled years ago, running on a CPU that did not exist when it was written, needs to discover what that CPU can do, and the person who adds a microarchitecture entry is usually reacting to a real report from someone running that hardware.

This also means the library's coverage is tied to the release cycle of the hardware rather than to a plan. There is no published roadmap of upcoming microarchitectures, and there does not need to be, because the mechanism is reactive. If your target CPU is newer than the latest release, the specific microarchitecture may simply not be named, even though its instruction set is largely one the library already knows how to detect.

The fix in 0.11.0 for CPU_FEATURES_OS_MACOS and CPU_FEATURES_OS_IPHONE detection is a good example of the other kind of work this repository does. Those are the internal macros that decide which platform code path compiles, so a bug there means every feature query on that platform returns nothing useful. Fixes like that are invisible in a changelog headline and essential in practice.

Three build systems and an Android compatibility shim

The repository carries a full set of build files for three ecosystems, which is unusual for a library this small. The cmake directory and CMakeLists.txt cover the cmake path. BUILD.bazel, MODULE.bazel, WORKSPACE and a .bazelrc cover Bazel, in both the older workspace style and the newer module style. build.zig and build.zig.zon cover Zig, and the 0.11.0 release notes credit a series of pull requests for building with Zig, so that path is new enough in this release to still be settling.

Two other directories explain themselves by their names. ndk_compat is there for Android's NDK toolchain, which is a distinct enough environment to warrant its own compatibility layer. scripts holds the release and CI tooling, including the badge generator named earlier and a release script that the 0.10.1 release had to fix.

The licensing is the simplest part: Apache License 2.0, with a LICENSE file at the root and a CONTRIBUTING.md for pull requests. The repository is not archived and its last push was on 2026-09-03, so it is a live project with releases roughly a year apart at present, v0.10.0 and v0.10.1 in May 2025 followed by v0.11.0 in June 2026.

Read the known issues before pinning a version

The 0.10.0 release is the one to look at for how this project handles its own mistakes, because it ships with a known issues section at the top rather than burying them. Two problems are named: the Bazel version in MODULE.bazel was set to 0.9.0 when it should have been 0.10.0, and the tests in that release failed to compile after a change in the minimum C++ version required by GoogleTest. Both were fixed in 0.10.1, released eleven days later.

Publishing a release that ships its own bug list is unusual and, for a library other projects vendor, useful. A wrong version pin in a build file is the kind of failure that looks like the consumer's mistake, so documenting it at the point of release saves an afternoon. It also suggests the release script is run by hand and can be run with the wrong arguments, which the 0.10.1 fix to scripts/make_release.sh would address.

The other limitation to name is the one the support table implies rather than states. This library reports what the CPU supports; it does not make use of it. There is no automatic dispatch, no vector-length abstraction and no tuned kernels here, so adopting it adds a branch to your code and leaves the fast path selection to you. That is a reasonable split, and it is also the difference between this and the larger portability libraries you may have been expecting.

Editorial conclusion

cpu_features is worth adopting when your code runs on more than one architecture and branches on instruction availability at runtime, since it replaces a pile of per-platform conditionals with one header and one call, and it keeps those conditionals correct as new hardware ships. It is not worth adopting for a project that compiles for one fixed target, where a compile-time check does the same job with less code. Two things to verify before you depend on it: that your architecture and operating system combination actually appears in the CI matrix rather than carrying an n/a badge, and that your chosen release is not one of the versions carrying a known issue. The include directory is the whole public surface, and the release notes are where the AArch64 feature tables are versioned, so both are worth a look before you pin a version.

Frequently asked questions

Which architectures and operating systems does cpu_features support?

The README support table covers amd64, AArch64, ARM, MIPS, POWER, RISCV and s390x against Linux, macOS and Windows. Only the amd64 row has live badges in all three operating system columns, with the other architectures verified on Linux and marked n/a elsewhere.

How do I build cpu_features, with CMake, Bazel or Zig?

All three are in the repository: CMakeLists.txt and a cmake directory, BUILD.bazel with MODULE.bazel and WORKSPACE plus a .bazelrc, and build.zig with build.zig.zon. Each cell in the README support table represents one combination of architecture, operating system and build system that CI exercises.

Does cpu_features support newly released CPUs like Zen 5?

Support tends to arrive in a release shortly after new hardware ships. Version 0.11.0 added AMD Zen 5, Intel Arrow Lake and Intel Lunar Lake, so if your CPU is newer than the latest release its specific microarchitecture may not be named yet even when the instructions it reports on are ones the library already knows.

What known issues did cpu_features 0.10.0 have?

The 0.10.0 release notes list two, both fixed in 0.10.1: the Bazel version in MODULE.bazel was set to 0.9.0 instead of 0.10.0, and the shipped tests failed to compile because of a change in the minimum C++ version required by GoogleTest.

Official sources

  1. google/cpu_features on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
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/google-cpu-features.svg)](https://hysenlabs.com/projects/google-cpu-features)