Kefir C17/C23 编译器
摘要
# kefir:独立 C17/C23 编译器
源码:[https://sr.ht/~jprotopopov/kefir/](https://sr.ht/~jprotopopov/kefir/) [723abe5](https://git.sr.ht/~jprotopopov/kefir/commit/723abe5)`重构目标 IR 指令存储以实现更安全的原地初始化` 8 小时前 [c1c07bf](https://git.sr.ht/~jprotopopov/kefir/commit/c1c07bf)`实现原地目标 IR 指令构造` 1 天前
Kefir 是一个面向 C17/C23 编程语言的独立编译器,由 [Jevgenij Protopopov](https://sr.ht/~jprotopopov) 开发
暂无内容
查看缓存全文
缓存时间:
2026/04/21 04:56
# kefir:独立的 C17/C23 编译器
源码:https://sr.ht/~jprotopopov/kefir/
723abe5(https://git.sr.ht/~jprotopopov/kefir/commit/723abe5)`重构目标 IR 指令存储以实现更安全的原地初始化`
8 小时前
c1c07bf(https://git.sr.ht/~jprotopopov/kefir/commit/c1c07bf)`实现原地目标 IR 指令构造`
1 天前
Kefir 是由 Jevgenij Protopopov(https://www.protopopov.lv/)开发的独立 C17/C23 编程语言编译器。Kefir 已通过包含 100 个软件项目的测试套件进行了验证,其中包括 GNU coreutils 和 binutils、Curl、Nginx、OpenSSL、Perl、Postgresql、Tcl 等诸多项目。编译器目标平台为 x86_64 架构和 System-V AMD64 ABI,支持 Linux、FreeBSD、NetBSD、OpenBSD 和 DragonflyBSD。该项目旨在提供一个功能完善、兼容且符合标准的编译器,包括基于 SSA 的优化流水线、调试信息生成、位置无关代码支持以及位相同的自举构建。Kefir 与系统工具链的其余部分(汇编器、链接器和共享库)集成。
### #(https://sr.ht/~jprotopopov/kefir/#at-a-glance)概览
Kefir:
- 支持 C17 标准——包括复数和虚数、原子操作、变长数组等(参见*实现细节*)。
- 支持 C23 标准——包括位精确整数和 `_Decimal` 浮点数支持(参见*实现细节*)。
- 支持部分广泛使用的 GNU C 内置函数、特定扩展、内联汇编、128 位整数。
- 使用 C11 编写——运行时依赖仅限于标准库、少量 POSIX 和 shell。
- 目标平台为 x86_64 和 System-V ABI——主要支持 Linux(glibc 和 musl libc),次要支持 FreeBSD、NetBSD、OpenBSD 和 DragonflyBSD(参见*支持的平台*)。
- 在真实开源软件测试套件上进行了广泛验证——包括数十个知名项目(参见*测试与验证*)。
- 实现基于 SSA 的优化流水线,包含两个 SSA 阶段——主要针对本地标量:本地变量提升至寄存器、死代码消除、常量折叠、全局值编号、循环不变量代码移动、函数内联、尾调用优化,但也提供保守的全局内存访问优化以及目标平台特定优化(参见*优化与代码生成*)。
- 支持 DWARF5 调试信息、位置无关代码、GNU As 的 AT&T 和 Intel 语法,并对 Yasm 提供有限支持。
- 实现位相同的自举构建——在固定环境中,Kefir 生成完全相同的自身副本。
- 能够生成独立于运行时的汇编代码——除线程本地存储(可能需要根据 ABI 进行外部调用)、`_Decimal` 浮点数和非原生大小的原子操作(需要兼容 libatomic 的库)外。
- 提供与 `cc` 兼容的命令行接口。
- 能够以机器可读的 JSON 格式输出内部表示(token、抽象语法树、中间表示)。
- 为最新版本发布前的测试提供可审计的日志和所有构建产物。
- 编译器采用 GNU GPLv3(仅此一种)许可,运行时头文件采用 BSD-3 条款(参见*许可*)。
- 由单一开发者编写和维护。
- 以发酵乳饮料命名(https://en.wikipedia.org/wiki/Kefir)——**无意包含其他任何含义**。
**重要提示:** 由于该项目由单一人员开发和维护,且无资金支持、仅利用业余时间,作者提醒在生产环境中使用 Kefir 可能不可取,因为作者无法提供足够的支持级别。
**重要提示 #2:** 据作者所知,以上所有声明均为真(且许多声明可通过测试套件可重现地演示)。然而,即使进行了充分验证,许多 bug、非故意遗漏、不一致和误解仍可能遗漏。作者致力于如实地描述项目的能力,并对任何夸大表述特别敏感。如果您有任何疑问、异议或不同意上述声明,请立即联系作者(参见*作者与联系方式*)——在确认缺陷后将立即发布更正。
### #(https://sr.ht/~jprotopopov/kefir/#installation-and-usage)安装与使用
在支持的平台上,Kefir 的构建和测试方式如下:
```
make test all # Linux glibc
make test all USE_SHARED=no CC=musl-gcc KEFIR_TEST_USE_MUSL=yes # Linux musl
gmake test all CC=clang # FreeBSD
gmake test all CC=clang AS=gas # OpenBSD
gmake test all CC=gcc AS=gas # NetBSD
gmake test all LD=/usr/local/bin/ld AS=/usr/local/bin/as # DragonflyBSD
```
安装通过 `\(g\)make install prefix=...` 完成。默认 prefix 为 `/opt/kefir`。
Kefir 构建时依赖:
- C11 编译器——已通过 gcc 和 clang 测试。
- Bash
- GNU Make
- GNU Coreutils
- Groff
- m4
- mandoc
Kefir 运行时依赖:
- C 标准库和 POSIX
- Shell
- 此外,为实现正确的端到端编译,Kefir 需要:
- 外部汇编器——全面支持 GNU As,有限支持 Yasm
- 外部链接器——GNU ld
- 外部 libc——Linux 上的 glibc 或 musl libc,*BSD 系统上的系统 libc。注意这可能与 Kefir 本身链接的 libc 不同。
- 外部启动文件——`crti.o`、`Scrt.o` 等。
- 兼容 `libatomic` 的库(即 gcc 的 `libatomic` 或 clang 的 `compiler_rt`)。
- 如果需要十进制浮点数支持,则需要 `libgcc`。
用户可查阅 `dist/Dockerfile*` 文件了解 Ubuntu(`base` 目标)、Fedora 和 Alpine 所需环境,以及 `dist/PKGBUILD` 了解 Arch Linux。对于 *BSD 系统,请查阅相应的 `.builds/*.yml` 文件。
**注意:** 构建时,Kefir 会检测宿主系统工具链(汇编器、链接器、头文件路径和库路径)并相应地进行配置。更新工具链后,Kefir 提供 `kefir-detect-host-env --environment` 命令,其输出应放入 `$(prefix)/etc/kefir.local` 文件。
**注意 #2:** 上述依赖不包括可选的开发依赖和完整测试套件依赖。请查阅 `dist/Dockerfile` 的 `dev` 和 `full` 目标以了解详情。
目前,Kefir 在 Ubuntu 24.04、FreeBSD 14.x、OpenBSD 7.7 和 NetBSD 10.x 环境中进行自动测试;Arch Linux 用作主要开发环境。DragonflyBSD 支持在发布前手动测试。
##### #(https://sr.ht/~jprotopopov/kefir/#decimal-floating-point-support)十进制浮点数支持
Kefir 提供对 `_Decimal` 浮点数的支持,依赖 `libgcc` 算术例程。要启用此支持,Kefir 必须由 gcc 宿主编译器直接或传递(即自举)编译。Kefir 生成的十进制算术代码需要链接 `libgcc`;如果需要位精确整数与十进制浮点数之间的转换,则需要 14 或更高版本的 `libgcc`。BID 和 DPD 两种编码均支持,BID 为默认编码。要启用 DPD,在构建 Kefir 时传递以下 Make 选项:`EXTRA_CFLAGS="-DKEFIR_PLATFORM_DECIMAL_DPD"`。
Kefir 可以自动自举 `libgcc` 4.7.4:
```
make bootstrap_libgcc474 -j$(nproc)
```
##### #(https://sr.ht/~jprotopopov/kefir/#libatomic)Libatomic
Kefir 可以通过以下方式从 `compiler_rt` 项目构建所需的 libatomic 例程:
```
make build_libatomic -j$(nproc)
```
#### #(https://sr.ht/~jprotopopov/kefir/#usage)使用
Kefir 实现与 `cc` 兼容的命令行接口,因此可作为标准编译流程中 `cc` 的近似直接替代品(参见*实现细节*):
```
which kefir # 安装后应输出正确的 kefir 路径
# 示例用法
kefir -O1 -g -fPIC -o hello_world ./hello_world.c
./hello_world
```
此外,kefir 提供手册页记录命令行选项和环境注意事项:
```
man kefir # 确保 kefir 安装目录对 man 命令可用
kefir --help # 与手册页内容相同
```
#### #(https://sr.ht/~jprotopopov/kefir/#portable-kefir)便携式 Kefir
Kefir 提供脚本用于构建 Linux 上的便携式独立 Kefir 分发包。该包包含静态链接的 Kefir C 编译器、musl libc 和精选的 GNU Binutils 工具。该包旨在提供独立于宿主系统工具的最小化 C 开发工具链。
```
make portable_bootstrap -j$(nproc)
# 构建产物位于 bin/portable/kefir-portable-*.tar.gz
```
### #(https://sr.ht/~jprotopopov/kefir/#supported-environments)支持的平台
Kefir 目标平台为 x86_64 指令集架构和 System-V AMD64 ABI。支持的平台包括现代版本的 Linux(glibc 和 musl libc)、FreeBSD、OpenBSD、NetBSD 和 DragonflyBSD 操作系统。如果满足以下条件,则认为平台受支持:
- Kefir 可使用系统编译器构建并成功执行自身测试套件(参见*测试与验证*)。
- Kefir 可使用自身构建并成功执行自身测试套件。
- Kefir 通过 `c-testuite` 和 `gcc-torture` 测试(参见*测试与验证*了解具体测试、条件等)。
- Kefir 可编译 Lua 并运行其基础测试套件。
- Kefir 可在固定环境中执行可重现的(即位相同的自举)自身构建。
要声称平台受支持,不施加其他要求。*测试与验证*部分描述的其他测试和验证主要聚焦于 Linux 以确保整体编译过程正确。通常,Linux 和 BSD 系统代码生成之间差异很小,因此完整*测试与验证*序列仅需在单一平台上执行即可。
请注意,libc 头文件特性通常是兼容性的主要障碍,因此可能需要额外的宏定义或个别头文件覆盖。Musl libc 提供最流畅的体验,但 Kefir 积累了对 GNU C 扩展的充分支持,可以相当合理地使用 glibc 和 BSD libc 实现(详细示例请查阅*实现细节*以及*测试与验证*的外部测试套件部分,以及所选平台相应的 `.build/*.yml` 文件)。
正如*安装*部分所述,Kefir 在构建时检测系统工具链配置并使用。编译器还支持一组环境变量,这些变量优先于内置配置。请查阅手册页相应部分了解支持的环境变量详情。
#### #(https://sr.ht/~jprotopopov/kefir/#standard-library-considerations)标准库注意事项
在 Linux 上,Kefir 可与 glibc 和 musl libc 配合使用。Musl 头文件更符合标准,通常提供更流畅的兼容性。相比之下,glibc 可能与非主流编译器产生不兼容(参见*实现细节*)。
在 FreeBSD、OpenBSD 和 NetBSD 上,可使用系统标准库,但可能需要额外的宏定义(例如 `__GNUC__`、`__GNUC_MINOR__`)才能成功构建。
### #(https://sr.ht/~jprotopopov/kefir/#implementation-quirks)实现细节
需要考虑以下细节:
- Kefir 对 C23 标准的实现提供对 `_Decimal` 浮点数的支持,依赖 `libgcc` 例程进行十进制算术运算(参见*安装与使用*)。
- C23 标准要求对 `char8_t`、`char16_t` 和 `char32_t` 类型和字面量使用 Unicode。Kefir 依赖标准库宽字符编码功能,因此在系统 locale 为基于 Unicode 的条件下实现此要求。作者认为这是一个合理的假设。
- 通常,作者对 C17 及更早版本特性的兼容性有更高的信心。作为当前外部测试套件版本(参见*测试与验证*),绝大多数第三方项目不依赖任何 C23 特性,这使得 C23 支持的外部验证非常有限。因此,作者确认已认真阅读了 C23 标准包含的更改,并以真诚和尽最大能力实现了这些更改,包括为相应特性编写了自己的测试。
- 在 Linux 上使用 glibc 时,存在一些库在非主流编译器上破坏某些特性的边缘情况。例如,glibc 用空宏覆盖 `__attribute__` 规范,忽略 `packed` 属性等,尽管 Kefir 支持相应特性但仍破坏了兼容性。Kefir 安装包含用于修复最突出问题的 `` 头文件垫片,但无法保证绝对兼容。作者建议熟悉外部测试套件(参见*测试与验证*)中的项目构建配置。
- 原子操作主要实现顺序一致语义,无论指定的内存顺序如何,但原生标量原子存储除外,后者区分 `release` 和 `seq_cst` 语义。这种行为是安全的,不应破坏任何软件。非原生大小的原子操作依赖外部软件原子库(gcc 的 `libatomic` 或 clang 的 `compiler_rt`)。Kefir 在除 musl libc 外的所有配置中自动链接结果可执行文件与该库。此外,使用 Clang 的 `` 系统头文件需要 `-D__GNUC__=4 -D__GNUC_MINOR__=20` 命令行参数。
- 如果使用 `long double` 变量(标量和复数)的原子操作,需要小心,因为每个 `long double` 存储单元的最后 48 位可能未初始化。Kefir 实现对未初始化填充的清零以缓解潜在问题。
- 对宿主 C 标准库的依赖意味着 Kefir 需要实现出现在库头文件中的任何内置函数或编译器扩展。作者已在编译器中引入了大量内置函数,但不能保证这方面的完整性。如果由于缺少内置函数或扩展而导致标准 C 库函数在任何受支持的平台上不可用,这将被视为 bug。
- 所有相关版本的 C 语言标准都只能以高昂的价格正式获取。开发编译器时,作者依赖公开可用的标准草案(参见*有用的资源与链接*)。如果这些草案与最终标准存在矛盾,作者有兴趣了解具体细节。
#### #(https://sr.ht/~jprotopopov/kefir/#in-practice)实践中
用户可能需要考虑以下实际注意事项:
- Kefir 无法在原始性能、可移植性或广度方面与 GCC 或 Clang 等成熟的主流编译器直接竞争。Kefir 项目的目的是生产一个具有完善架构和明确定义范围的独立 C17/C23 编译器,且对于单一开发者来说是可行的实现。
- 特别是在原始性能方面,Kefir 可能不如更注重性能的项目。作者仍认为在寄存器分配、优化过程、指令选择、调度等方面存在许多低垂的果实。
- 在 GNU C 兼容性方面,Kefir 实现了足够多的扩展和内置函数以具有实际用途。内置函数的详尽列表可在 `source/tests/end2end/supported_bu
相似文章
Hacker News Top
Kefir C 编译器的主要开发者宣布停止公开开发,将项目无限期转为私有模式,以保持个人兴趣和可持续性。
Hacker News Top
QBE 是一个紧凑的、爱好级别的编译器后端,仅用 10% 的代码即可实现工业级优化编译器 70% 的性能,支持 amd64、arm64 和 riscv64,并采用简单的基于 SSA 的中间语言。
Lobsters Hottest
QBE 1.3 是一个重要的编译器后端版本,新增了 7000 行代码,引入了一种新的 IL 匹配算法,针对 coremark 基准测试进行了优化(性能从 gcc -O2 的 40% 提升到超过 63%),支持 Windows ABI 和位置无关代码生成。
Anthropic Engineering
Anthropic研究员展示了如何使用16个并行Claude实例自主构建一个基于Rust的C编译器,该编译器能够编译Linux内核。文章详细介绍了这一多智能体自主编码实验的架构、成本和经验教训。
Hacker News Top
新的 Zig ELF 链接器现在支持外部库和 C 源码的快速增量编译,在 x86_64 Linux 上能够实现毫秒级重建。