Skip to content

Repository files navigation

gcc-kernel

Which GCC builds which Linux kernel? This repository answers that by trying it. It pins every kernel release from 0.01 to today, every GCC release it can build from source, and every platform QEMU can boot, then builds each pairing it picks, boots the result, runs the kernel's own tests, and publishes a matrix. Every edge of that matrix comes with an explanation: the first GCC that works for a kernel, the last one that does, why the ones outside fail, and the kernel commit that fixed it.

It exists because of rucc, a C compiler in Rust that aims to be compatible with GCC 16, and rucc-kernel, the harness that builds kernels with it. Both depend on facts about GCC that nobody has written down in one place, such as which kernels GCC 16 itself builds and boots, and whether the GCC a kernel era is graded against really works for every version in that era. gcc-kernel never runs rucc. It only measures real GCCs, so it stays an independent reference, and its results flow one way into rucc-kernel.

Recent kernels come first, because that is where rucc is going. Old kernels are there as reference, to show how the kernel and GCC moved together.

Status

This section is written by gk publish from matrix/matrix.json and is replaced every time the results are published. Last published 2026-10-03, with 75 cells in the matrix.

Progress

The current stripe of G1 is every Current kernel with every upstream GCC column on the tier 1 platforms, with defconfig+gk and tinyconfig+gk. The GCC 16 column is every release from 5.0 on with the newest GCC 16.

x86_64 defconfig+gk      β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‹β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘   24/84    28%
x86_64 tinyconfig+gk     β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    0/84     0%
i386 defconfig+gk        β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘   11/84    13%
i386 tinyconfig+gk       β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    0/84     0%
arm64 defconfig+gk       β–Šβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    2/84     2%
arm64 tinyconfig+gk      ▍░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    1/84     1%
total                    β–ˆβ–ˆβ–β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘   38/504    7%
x86_64 gcc-16.2.0        β–‹β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    1/50     2%
i386 gcc-16.2.0          β–‹β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    1/50     2%
arm64 gcc-16.2.0         β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    0/50     0%
total                    β–Œβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    2/150    1%

Verdicts

The newest cell at each crossing, over every platform and configuration.

🟩 works      β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 21
🟨 runs       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Œ          16
🟧 builds     β–ˆβ–‰                                       1
πŸŸ₯ fails                                               0

The same cells by the rung they reached (spec 02.2), L8 being clean all the way through KUnit and the splat check.

L0                                                    0
L1                                                    0
L2                                                    0
L3                                                    0
L4                                                    0
L5           β–ˆβ–‰                                       1
L6           β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‰                  12
L7           β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‹                                 4
L8           β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 21

The median build time of defconfig+gk cells per GCC column, in minutes. The machines are shared, so these move with their load.

8.5.0        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–               21 min, 4 cells
9.5.0        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–                     16 min, 3 cells
10.5.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–                          12 min, 3 cells
11.5.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Ž                         13 min, 3 cells
12.2.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‰                        14 min, 4 cells
12.5.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Ž                         13 min, 3 cells
13.5.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‹                        14 min, 3 cells
14.2.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 34 min, 4 cells
14.4.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ                       15 min, 2 cells
15.3.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ                        14 min, 3 cells
16.1.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Š                       15 min, 3 cells
16.2.0       β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Š                      16 min, 2 cells

By GCC column

The newest cell at each crossing again, over every kernel, platform and configuration.

GCC Cells 🟩 🟨 🟧 πŸŸ₯ ⚠️ Works
8.5.0 4 2 2 0 0 1 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘ 50%
9.5.0 3 1 2 0 0 1 β–ˆβ–ˆβ–ˆβ–β–‘β–‘β–‘β–‘β–‘β–‘ 33%
10.5.0 3 2 1 0 0 1 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Šβ–‘β–‘β–‘ 66%
11.5.0 3 2 1 0 0 0 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Šβ–‘β–‘β–‘ 66%
12.2.0 4 3 1 0 0 0 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Œβ–‘β–‘ 75%
12.5.0 3 2 1 0 0 0 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Šβ–‘β–‘β–‘ 66%
13.5.0 3 1 2 0 0 1 β–ˆβ–ˆβ–ˆβ–β–‘β–‘β–‘β–‘β–‘β–‘ 33%
14.2.0 4 2 2 0 0 2 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘ 50%
14.4.0 2 1 1 0 0 0 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘ 50%
15.3.0 3 2 0 1 0 1 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Šβ–‘β–‘β–‘ 66%
16.1.0 3 2 1 0 0 0 β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Šβ–‘β–‘β–‘ 66%
16.2.0 3 1 2 0 0 1 β–ˆβ–ˆβ–ˆβ–β–‘β–‘β–‘β–‘β–‘β–‘ 33%

Latest cells

Date Kernel GCC Platform Config Verdict Rung Minutes
2026-10-03 6.18.54 10.5.0 x86_64 defconfig+gk 🟩 works L8 22
2026-10-03 6.18.54 9.5.0 x86_64 defconfig+gk 🟨 runs L7 22
2026-10-03 6.18.54 8.5.0 x86_64 defconfig+gk 🟨 runs L7 21
2026-10-03 7.2.8 8.5.0 arm64 defconfig+gk 🟨⚠️ runs L7 55
2026-10-03 6.18.54 14.2.0 x86_64 defconfig+gk 🟨⚠️ runs L6 41
2026-10-02 7.2.8 16.2.0 x86_64 defconfig+gk 🟩 works L8 32
2026-10-02 7.2.8 14.2.0 arm64 defconfig+gk 🟩 works L8 62
2026-10-02 7.2.8 16.1.0 x86_64 defconfig+gk 🟩 works L8 32
2026-10-02 7.2.8 16.2.0 i386 defconfig+gk 🟨⚠️ runs L7 38
2026-10-02 7.2.8 15.3.0 x86_64 defconfig+gk 🟩 works L8 30

Matrices

One square per cell: 🟩 works, 🟨 runs, 🟧 builds, πŸŸ₯ fails, Β· n/a, and blank where the cell has not run yet. ⚠️ marks a flaky cell, whose boots disagreed and which keeps the lowest rung. A table appears once its first cell has run, and then every Current kernel has a row in it. The full heat maps, with warning counts, are in reports.

x86_64 defconfig+gk, 24 cells

Kernel 8.5.0 9.5.0 10.5.0 11.5.0 12.2.0 12.5.0 13.5.0 14.2.0 14.4.0 15.3.0 16.1.0 16.2.0
5.10.270
5.15.221
6.1.188
6.6.157
6.12.111 🟩
6.18.54 🟨 🟨 🟩 🟨 🟨 🟨 🟨 🟨⚠️ 🟨 🟧⚠️ 🟨
7.2.8 🟩 🟨⚠️ 🟨⚠️ 🟩 🟩 🟩 🟨⚠️ 🟨⚠️ 🟩 🟩 🟩 🟩

i386 defconfig+gk, 11 cells

Kernel 8.5.0 9.5.0 10.5.0 11.5.0 12.2.0 12.5.0 13.5.0 14.2.0 14.4.0 15.3.0 16.1.0 16.2.0
5.10.270
5.15.221
6.1.188
6.6.157
6.12.111
6.18.54
7.2.8 🟩 🟩 🟩 🟩 🟩 🟩 🟩 🟩 🟩 🟩 🟨⚠️

arm64 defconfig+gk, 2 cells

Kernel 8.5.0 9.5.0 10.5.0 11.5.0 12.2.0 12.5.0 13.5.0 14.2.0 14.4.0 15.3.0 16.1.0 16.2.0
5.10.270
5.15.221
6.1.188
6.6.157
6.12.111
6.18.54
7.2.8 🟨⚠️ 🟩

arm64 tinyconfig+gk, 1 cell

Kernel 8.5.0 9.5.0 10.5.0 11.5.0 12.2.0 12.5.0 13.5.0 14.2.0 14.4.0 15.3.0 16.1.0 16.2.0
5.10.270
5.15.221
6.1.188
6.6.157
6.12.111
6.18.54
7.2.8 🟨

How it works

A cell is one kernel, one GCC, one binutils, one platform, one configuration and one host environment. Each cell climbs a ladder, from L0 (the tree is fetched and checks out) through L4 (it links) and L6 (it boots and passes the smoke suite) to L8 (KUnit passes and the console is clean). The highest rung it reaches gives its verdict: works, runs, builds, fails, or n/a.

The kernel picks the host. HOSTCC and the host tools come from a Debian container of the kernel's own era, and the GCC under test comes in as a static toolchain bundle through CROSS_COMPILE, so a failure along a row is the toolchain's and not the host's.

The matrix is not swept densely. Each row is searched outward from the GCC the kernel was built with when it was current, until the edges are found, with samples inside to catch holes. A few stripes are run in full: the kernels kernel.org maintains today, the last point of every longterm line, the GCC 16 column, and the era diagonal.

The rules

Nothing is patched. Kernels are unmodified tarballs checked by hash. GCC and binutils are built from release tarballs. Anything that cannot be built without a patch is recorded as unbuildable, with its log.

Every failure gets a name. The first error of every failing cell is matched against a catalog of signatures, each with the kernel commit that fixed it, and that commit is confirmed by bisection.

No hidden configuration. Everything that changes a cell is in a committed file: kernels, toolchains, hosts, platforms, configs, signatures and the search seed.

Same schema as rucc-kernel. The compiler shim gk-cc is rucc-kernel's rk-cc, and a gcc-kernel cell directory is a rucc-kernel build directory, so rucc-kernel's diff tools read it unchanged.

Platforms

Tier 1 is x86_64, i386 and arm64. Tier 2 is arm, riscv64, ppc64le, s390x and loongarch64. Tier 3 gets build only cells on current kernels.

Milestones

The full plan is in docs/spec. It is split into seven milestones, G0 to G6. Each one has a GitHub milestone and a tracking issue of the same name.

Scope
G0 the instrument: model, shim, modern forge, one dense row
G1 the current stripe on tier 1, boots and KUnit, the GCC 16 column
G2 GCC 4.6 to 7.5, kernels 3.0 to 4.20, the failure catalog, the eras report
G3 the legacy forge, 2.6.x, 2.4 and the museum, the 0.x experiment
G4 tier 2 platforms
G5 distribution GCCs and the binutils sweep
G6 steady state: new kernels and GCCs show up without anyone touching the repo

Building

cargo build --release builds gk. The Rust toolchain is pinned in rust-toolchain.toml. Right now gk knows check, pins, fetch, forge, hosts check, pins changed, probe, cell, store, ladder and version. gk check reads the pin files at the top of the repository and checks that they agree with each other. gk pins applies the rules in sets.toml to kernel.org and the GNU mirror and shows how the pins would change, and gk pins --write writes them. gk fetch downloads pinned tarballs into ~/.cache/gk and checks them against their pins and the signing keys in keys/. gk forge builds a static GCC and binutils bundle in a forge container, and gk forge verify checks every bundle in every host. gk hosts check runs each host and forge container and compares its GCC, binutils and make with hosts.toml. gk probe 7.2.8 gcc-16.2.0 --platform x86_64 asks whether that kernel accepts that GCC at all, by running defconfig and preprocessing init/main.c. gk cell with the same arguments builds the cell up to L4 in its host container, with gk-cc logging every compiler call, and writes the cell directory into the result store, under cells/<identity> in $GK_STORE or ~/.cache/gk/store. gk store lists the cells in it, gk store show prints one, gk store check finds cells that did not finish, and gk store pack writes the tarball a sweep publishes. It needs a static gk-cc next to gk, which cargo build --release --target x86_64-unknown-linux-musl -p gk-cc gives. gk pins changed BASE lists the accept probes that the pins changed since a git revision call for, and pr.yml runs them on every pull request that touches a pin file. The rest of the commands in docs/spec/10-gcc-kernel-repo.md arrive with the milestones that need them. Running cells will need Linux, Docker and QEMU.

House style

Prose in this repository is plain English with one paragraph per line, no em or en dashes and no horizontal rules. scripts/style.sh checks it on every pull request.

License

Apache-2.0. The kernel trees and toolchains it fetches are under their own licenses and are never stored here.

About

Which GCC builds which Linux kernel: every kernel release against every GCC release on QEMU platforms, built, booted, tested, with each failure explained

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages