13.6 语言的自举
前期准备
- 从 Go 源代码树中删除所有 C 程序:删除 C 编译器(5c,6c,8c,9c)。
- 将 C 程序将转换为 Go,包括:
- Go 编译器
- 汇编器
- 链接器
cmd/dist
如果这些程序是用 Go 编写的,则在完全从源代码构建时会引入引导问题: 因此需要一个有效的 Go 工具链才能构建 Go 工具链。
自举流程
要构建 x ≥ 5 的 Go 1.x,必须在 $GOROOT_BOOTSTRAP
中已经安装 Go 1.4(或更高版本)。
$GOROOT_BOOTSTRAP
的默认值为 $HOME/go1.4
。
Go 1.4 将尽可能长地继续使用,并作为自举的基础版本。
适当的工具链(编译器,汇编器,链接器)将需要使用 Go 1.4 进行构建,
无论是通过将其功能限制在 Go 1.4 中还是通过使用构建标签来构建。
为了与后续内容进行比较,Go 1.4的旧构建过程为:
- 用
gcc
(或clang
)构建cmd/dist
。 - 使用
dist
,用gcc
(或clang
)构建编译器工具链 - NOP
- 使用
dist
,使用编译器工具链构建cmd/go
(作为go_bootstrap
)。 - 使用
go_bootstrap
构建其余的标准库和命令。
Go 1.x(x ≥ 5)的新构建过程将是:
- 使用 Go 1.4 构建
cmd/dist
。 - 使用
dist
,通过 Go 1.4 构建 Go 1.x 编译器工具链。 - 使用
dist
自身重建 Go 1.x 编译器工具链。 - 使用
dist
,使用 Go 1.x 编译器工具链构建 Go 1.xcmd/go
(作为go_bootstrap
)。 - 使用
go_bootstrap
构建其余的 Go 1.x 标准库和命令。
在自举前后的构建过程包含两个变化:
- 第一个变化是用 Go 1.4 替换了 gcc(或clang)。
- 第二个变化是引入了第 3 步,该步骤用其自身重建了 Go 1.x 编译器工具链。 第 2 步中构建的 6g 是使用 Go 1.4 库和编译器构建的 Go 1.x 编译器。 第 3 步中构建的 6g 与 Go 1.x 编译器相同,但使用 Go 1.x 库和编译器构建。 如果 Go 1.x 更改了调试信息的格式或二进制文件的某些其他详细信息, 则 6g 是 Go 1.4 二进制文件还是 Go 1.x 二进制文件对工具可能很重要。 如果 Go 1.x 在库中引入了任何性能或稳定性方面的改进, 则第 3 步中的编译器将比第2步中的编译器更快或更稳定。 当然,如果 Go 1.x 存在问题,则第 3 步中 6g 的构建也会遇到问题, 因此可以禁用第 3 步进行调试。
all.bash
↳ make.bash
↳ check ld
↳ check dyanmic ld.so
↳ cldear runtime/runtime_defs.go
↳ go build -o cmd/dist/dist ./cmd/dist
↳ dist bootstrap
↳ run.bash --no-rebuild
↳ go tool dist test