Skip to content

Commit f8774c8

Browse files
authored
Merge branch 'zigcc:main' into main
2 parents 2b2774c + 5199dee commit f8774c8

File tree

108 files changed

+7686
-322
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+7686
-322
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
strategy:
2323
matrix:
2424
os: [ubuntu-latest, macos-latest, windows-latest]
25-
version: [0.11.0, 0.12.1, 0.13.0, 0.14.0, ""]
25+
version: [0.11.0, 0.12.1, 0.13.0, 0.14.0, 0.15.1, ""]
2626
fail-fast: false
2727
runs-on: ${{ matrix.os }}
2828
steps:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ zig-cache
1212
.zig-cache
1313
.direnv
1414
PDF
15+
.DS_Store

15_zig_build_fix.txt

Lines changed: 0 additions & 262 deletions
This file was deleted.

AGENTS.md

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# AGENTS.md
2+
3+
本文档帮助 AI 助手理解 Zig 语言圣经项目的结构和开发规范。
4+
5+
## 项目概述
6+
7+
**Zig 语言圣经** 是一个全面的开源 Zig 编程语言中文教程。项目旨在为中文开发者提供高质量的 Zig 学习资源。
8+
9+
- **官方网站**: https://course.ziglang.cc/
10+
- **GitHub Pages**: https://zigcc.github.io/zig-course/
11+
- **代码仓库**: https://github.com/zigcc/zig-course
12+
- **开源协议**: MIT
13+
- **主要语言**: 简体中文
14+
- **文档语言**: 中文为主,技术术语保留英文
15+
16+
## 核心目标
17+
18+
1. 提供全面的 Zig 编程语言中文文档
19+
2. 支持多个 Zig 版本(0.11 至 0.16)
20+
3. 维护可运行的代码示例
21+
4. 记录版本升级指南和破坏性变更
22+
5. 构建高质量的中文 Zig 社区学习资源
23+
24+
## 项目结构
25+
26+
```
27+
zig-course/
28+
├── build.zig # 主构建编排器
29+
├── build/ # 版本特定的构建脚本
30+
│ ├── 0.11.zig # Zig 0.11 构建逻辑
31+
│ ├── 0.12.zig # Zig 0.12 构建逻辑
32+
│ ├── 0.13.zig # Zig 0.13 构建逻辑
33+
│ ├── 0.14.zig # Zig 0.14 构建逻辑
34+
│ ├── 0.15.zig # Zig 0.15 构建逻辑(当前重点)
35+
│ └── 0.16.zig # Zig 0.16 构建逻辑
36+
37+
├── course/ # 主要文档内容
38+
│ ├── .vitepress/ # VitePress 配置
39+
│ │ ├── config.mts # 站点主配置
40+
│ │ ├── sidebar.ts # 侧边栏导航结构
41+
│ │ ├── nav.ts # 顶部导航
42+
│ │ └── theme/ # 自定义主题组件
43+
│ │
44+
│ ├── environment/ # 环境搭建指南
45+
│ ├── basic/ # Zig 基础概念
46+
│ ├── advanced/ # 进阶主题
47+
│ ├── engineering/ # 软件工程实践
48+
│ ├── examples/ # 实战示例
49+
│ ├── update/ # 版本升级指南
50+
│ ├── appendix/ # 参考资料
51+
│ │
52+
│ ├── code/ # 可运行的代码示例
53+
│ │ ├── 11/ # Zig 0.11 示例
54+
│ │ ├── 12/ # Zig 0.12 示例
55+
│ │ ├── 13/ → ./12 # 符号链接(与 0.12 兼容)
56+
│ │ ├── 14/ # Zig 0.14 示例
57+
│ │ ├── 15/ # Zig 0.15 示例(当前活跃版本)
58+
│ │ └── release/ → ./15 # 符号链接到最新稳定版
59+
│ │
60+
│ ├── picture/ # 图片资源
61+
│ └── public/ # 静态网站资源
62+
63+
├── .github/
64+
│ └── workflows/ # CI/CD 流水线
65+
│ ├── build.yml # 多平台、多版本构建
66+
│ ├── deploy.yml # GitHub Pages 部署
67+
│ ├── check.yml # 代码格式检查
68+
│ ├── autocorrect.yml # 中文文本格式检查
69+
│ └── pdf.yml # PDF 导出流程
70+
71+
├── package.json # Node.js 依赖(Bun)
72+
├── bun.lock # Bun 锁文件
73+
└── flake.nix # Nix 开发环境
74+
```
75+
76+
## 开发工作流
77+
78+
### 构建和测试
79+
80+
项目使用多版本构建系统确保跨 Zig 版本兼容性:
81+
82+
```bash
83+
# 使用当前 Zig 版本构建所有示例
84+
zig build
85+
86+
# 主 build.zig 会根据检测到的 Zig 编译器版本
87+
# 自动分发到 build/ 目录下对应的版本特定脚本
88+
```
89+
90+
### 文档开发
91+
92+
文档站点使用 VitePress 构建:
93+
94+
```bash
95+
# 启动带热重载的开发服务器
96+
bun dev
97+
98+
# 构建生产站点
99+
bun build
100+
101+
# 预览构建后的站点
102+
bun preview
103+
104+
# 导出 PDF 版本
105+
bun export-pdf
106+
```
107+
108+
### 代码格式化
109+
110+
```bash
111+
# 格式化所有代码(Markdown、Zig、中文文本)
112+
bun format
113+
114+
# 检查格式但不修改文件
115+
bun check
116+
```
117+
118+
这会运行:
119+
120+
- Prettier 处理 Markdown/TypeScript/JavaScript
121+
- `zig fmt` 处理 Zig 源文件
122+
- AutoCorrect 处理中文文本格式
123+
124+
## 版本兼容性维护
125+
126+
### 多版本构建系统架构
127+
128+
项目采用版本分发架构来支持多个 Zig 版本:
129+
130+
1. **主构建入口** (`build.zig`): 检测当前 Zig 编译器版本,自动分发到对应的版本特定构建脚本
131+
2. **版本构建脚本** (`build/0.XX.zig`): 每个版本有独立的构建逻辑
132+
3. **代码示例目录** (`course/code/XX/`): 每个版本维护独立的示例代码
133+
134+
### 修复不同版本编译问题的工作流程
135+
136+
当需要修复特定 Zig 版本的编译问题时,需要处理以下目录:
137+
138+
#### 1. 更新构建脚本
139+
140+
**路径**: `build/0.XX.zig`
141+
142+
当 Zig 编译器 API 发生变更时需要更新:
143+
- 构建系统 API 变更(如 `std.Build` 接口改变)
144+
- 模块系统变更(如 `root_module` 相关 API)
145+
- 目标平台和优化选项变更
146+
147+
**示例场景**:
148+
- Zig 0.12 引入模块系统,需要从 `addExecutable` 迁移到 `addModule`
149+
- Zig 0.14 更改了目标解析方式,需要更新 `resolved_target` 相关代码
150+
151+
#### 2. 更新代码示例
152+
153+
**路径**: `course/code/XX/`
154+
155+
此目录包含两类文件需要维护:
156+
157+
##### a) 单文件示例(直接的 .zig 文件)
158+
这些文件会被构建脚本直接编译为可执行文件和测试:
159+
- `hello_world.zig`
160+
- `array.zig`
161+
- `comptime.zig`
162+
- 等等...
163+
164+
**修复重点**:
165+
- 标准库 API 变更(如 `std.debug.print``std.mem.Allocator`
166+
- 语法变更(如错误处理、可选类型语法)
167+
- 类型系统变更
168+
169+
##### b) 项目类型示例(子目录包含 build.zig)
170+
这些是完整的 Zig 项目,有自己的构建系统:
171+
- `build_system/` - 构建系统示例
172+
- `import_dependency_build/` - 依赖管理示例
173+
- `import_vcpkg/` - C 库集成示例
174+
175+
**修复重点**:
176+
- 项目自己的 `build.zig` 需要同步更新
177+
- 依赖声明方式的变更(如 `build.zig.zon`
178+
- 模块导入和导出方式的变更
179+
180+
#### 3. 版本符号链接维护
181+
182+
**当前符号链接**:
183+
- `course/code/13/``./12` (Zig 0.13 与 0.12 兼容)
184+
- `course/code/release/``./15` (指向最新稳定版)
185+
186+
**维护规则**:
187+
- 如果新版本完全兼容旧版本,可以创建符号链接而不是复制代码
188+
- 当有破坏性变更时,必须创建独立目录并更新所有示例
189+
190+
#### 4. 验证流程
191+
192+
在根目录运行 `zig build` 验证修复:
193+
194+
```bash
195+
# 主 build.zig 会自动选择对应版本的构建脚本
196+
zig build
197+
198+
# 构建过程会:
199+
# 1. 编译 course/code/XX/ 下的所有单文件示例
200+
# 2. 运行所有测试
201+
# 3. 递归构建子目录中的项目示例
202+
```
203+
204+
#### 5. 常见破坏性变更类型
205+
206+
**标准库变更**:
207+
- 分配器 API (`std.heap.GeneralPurposeAllocator`)
208+
- 文件系统 API (`std.fs`)
209+
- 网络 API (`std.net`)
210+
211+
**语言特性变更**:
212+
- 错误处理语法
213+
- 可选类型语法
214+
- 编译时特性
215+
216+
**构建系统变更**:
217+
- `std.Build` API
218+
- 模块系统
219+
- 依赖管理(`build.zig.zon`
220+
221+
#### 6. 实用技巧
222+
223+
**批量测试多个版本**:
224+
项目的 CI 系统(`.github/workflows/build.yml`)会在多个平台和 Zig 版本上运行构建,可以参考 CI 配置来本地测试多版本兼容性。
225+
226+
**创建新版本支持**:
227+
1. 复制最近版本的 `build/0.XX.zig` 到新版本
228+
2. 复制或链接 `course/code/XX/` 目录
229+
3. 在主 `build.zig` 中添加新版本的 case 分支
230+
4. 运行构建并修复所有编译错误
231+
5. 更新 `course/code/release/` 符号链接(如果是最新稳定版)
232+
233+
**检查依赖项目**:
234+
不要忘记检查子目录项目的构建:
235+
```bash
236+
cd course/code/15/build_system
237+
zig build
238+
```

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
./AGENTS.md

build.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub fn build(b: *Build) void {
1111
13 => @import("build/0.13.zig").build(b),
1212
14 => @import("build/0.14.zig").build(b),
1313
15 => @import("build/0.15.zig").build(b),
14+
16 => @import("build/0.16.zig").build(b),
1415
else => @compileError("unknown zig version"),
1516
}
1617
}

build/0.16.zig

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
const std = @import("std");
2+
const Build = std.Build;
3+
const ChildProcess = std.process.Child;
4+
5+
const log = std.log.scoped(.For_0_16_0);
6+
const version = "16";
7+
8+
const args = [_][]const u8{ "zig", "build" };
9+
10+
const relative_path = "course/code/" ++ version;
11+
12+
pub fn build(b: *Build) void {
13+
// get target and optimize
14+
const target = b.standardTargetOptions(.{});
15+
const optimize = b.standardOptimizeOption(.{});
16+
17+
var lazy_path = b.path(relative_path);
18+
19+
const full_path = lazy_path.getPath(b);
20+
21+
// open dir
22+
var dir = std.fs.openDirAbsolute(full_path, .{ .iterate = true }) catch |err| {
23+
log.err("open 15 path failed, err is {}", .{err});
24+
std.process.exit(1);
25+
};
26+
defer dir.close();
27+
28+
// make a iterate for release ath
29+
var iterate = dir.iterate();
30+
31+
while (iterate.next()) |val| {
32+
if (val) |entry| {
33+
// get the entry name, entry can be file or directory
34+
const output_name = std.mem.trimRight(u8, entry.name, ".zig");
35+
if (entry.kind == .file) {
36+
// connect path
37+
const path = std.fs.path.join(b.allocator, &[_][]const u8{ relative_path, entry.name }) catch |err| {
38+
log.err("fmt path for examples failed, err is {}", .{err});
39+
std.process.exit(1);
40+
};
41+
42+
// build exe
43+
const exe = b.addExecutable(.{
44+
.name = output_name,
45+
.root_module = b.addModule(output_name, .{
46+
.root_source_file = b.path(path),
47+
.target = target,
48+
.optimize = optimize,
49+
}),
50+
});
51+
exe.linkLibC();
52+
53+
if (exe.root_module.resolved_target.?.result.os.tag == .windows and std.mem.eql(u8, "echo_tcp_server.zig", entry.name)) {
54+
std.log.info("link ws2_32 for {s}", .{entry.name});
55+
exe.linkSystemLibrary("ws2_32");
56+
}
57+
// add to default install
58+
b.installArtifact(exe);
59+
60+
// build test
61+
const test_name = std.fmt.allocPrint(b.allocator, "{s}_test", .{output_name}) catch |err| {
62+
log.err("fmt test name failed, err is {}", .{err});
63+
std.process.exit(1);
64+
};
65+
const unit_tests = b.addTest(.{
66+
.root_module = b.addModule(test_name, .{
67+
.root_source_file = b.path(path),
68+
.target = target,
69+
.optimize = optimize,
70+
}),
71+
});
72+
73+
// add to default install
74+
b.getInstallStep().dependOn(&b.addRunArtifact(unit_tests).step);
75+
} else if (entry.kind == .directory) {
76+
77+
// build child process
78+
var child = ChildProcess.init(&args, b.allocator);
79+
80+
// build cwd
81+
const cwd = std.fs.path.join(b.allocator, &[_][]const u8{
82+
full_path,
83+
entry.name,
84+
}) catch |err| {
85+
log.err("fmt path for examples failed, err is {}", .{err});
86+
std.process.exit(1);
87+
};
88+
89+
// open entry dir
90+
const entry_dir = std.fs.openDirAbsolute(cwd, .{}) catch unreachable;
91+
entry_dir.access("build.zig", .{}) catch {
92+
log.err("not found build.zig in path {s}", .{cwd});
93+
std.process.exit(1);
94+
};
95+
96+
// set child cwd
97+
// this api maybe changed in the future
98+
child.cwd = cwd;
99+
100+
// spawn and wait child process
101+
_ = child.spawnAndWait() catch unreachable;
102+
}
103+
} else {
104+
// Stop endless loop
105+
break;
106+
}
107+
} else |err| {
108+
log.err("iterate examples_path failed, err is {}", .{err});
109+
std.process.exit(1);
110+
}
111+
}

0 commit comments

Comments
 (0)