goc 专栏
goc 专栏
goc 是一个用 Go 写的 C 编译器,也带一个自研汇编器 goa。它做的事有点极端:
编译 C 代码,产物既不依赖 gcc,也不依赖 libc。
Windows 上产物是 PE32+,只导入 kernel32 / user32 / gdi32 这类系统 DLL;Linux 上产物是静态 ELF64,一条动态链接都没有,只走 syscall。两头都没有 msvcrt,也没有 glibc。
源码在 GitHub:yafengabc/goc(MIT 许可,公开仓库,已发布 v0.1.1)。
这个专栏写什么
这个专栏分四块:
| 篇章 | 内容 |
|---|---|
| 项目介绍 | goc 是什么、为什么这么做、架构怎么分的、和gcc 差在哪 |
| 上手教程 | 从装工具链到写出第一个程序,含Windows GUI 和 Linux 双目标 |
| 体积实测 | 同一份源码,goc / goc+LLVM 后端 / gcc 三方对比,全部自己跑出来的数字 |
| 项目状态 | 已经能做什么、还不能做什么、正在进行什么,附一份测试失败怎么读的经验 |
另有一份开发笔记(content/goc/devnotes/),记录 bug 排查与修复的完整过程——不走弯路的那部分不进教程。
为什么值得写
goc 最有意思的地方不是"又写了个编译器"——那没什么新鲜的。而是它把取舍做得非常明白:
- 不要 gcc:既然是 Go 写的编译器,那就纯到底,产物里不会出现任何 C 工具链的痕迹。
- 不要 libc:那
printf怎么办?答案是把它当成一个真正的库函数写在 C 里,按需发射——只调用putchar的程序不会背上printf的 512字节输出缓冲。 - 不要假设 CPU 会变好:验证环节直接上QEMU(Unicorn),因为手写解释器只能证明"代码生成器和我的理解一致",证明不了程序真的对。
这三条决定了 goc 的整个形态。后面几篇会逐一展开。
现状速览
写这个专栏时的实测状态(2026-10-06):
- 仓库 176 次提交,最新 tag
v0.1.1 run_tests.sh在 Windows 11 + MSYS2 下跑出 pass=253 fail=0- 85 个C 示例,81 份 golden
- 默认后端回归基线
gocregress pass=475(81 example × 6 腿) - C99主体 + C11 类型系统 + C23 实用子集全部落地
_BitInt(N)已实现,10 万位 π 二分算法 100,011 位对拍 Python 大整数通过
阅读顺序
- 第0 章:为什么再写一个 C 编译器 —— 项目介绍与设计取舍
- 第 1 章:5 分钟跑起来 —— 装工具链,编译第一个程序
- 第 2 章:写第一个 Windows GUI 程序 —— 用 MessageBox 弹个框
- 第 3 章:体积实测 —— goc / LLVM 后端 / gcc 对比
- 第 4 章:项目状态与 roadmap —— 能做什么,不能做什么
开发笔记
| 笔记 | 内容 |
|---|---|
| 变参窄整型丢符号性 | gocl 把经变参传的 32 位整型符号性丢掉:从误诊为"有符号除法"到定位为"8 字节参数槽没填满"的完整排查过程 |
⚠️ 说明:本专栏所有体积、测试数字均为在作者机器(Windows 11 + MSYS2)实测所得,标注了日期。goc 迭代很快,数字会变——但结论和方法相对稳定。