菜单

开发工作流

相关源文件

本文档描述了 Go 编程语言的构建、测试和发布过程。它侧重于 Go 本身的开发方式,而不是如何使用 Go 开发软件。本文档解释了支持 Go 开发周期的工具以及对 Go 存储库进行更改所涉及的步骤。

构建系统概述

Go 使用一个以 dist 工具为中心定制的构建系统,该工具负责引导过程、编译和测试。该工具通过采用多阶段方法来处理使用 Go 构建 Go 的复杂性,从而解决了引导难题。

来源: src/cmd/dist/build.go25-606 src/cmd/dist/build.go490-606

环境设置

构建系统依赖几个环境变量来控制其行为。这些变量在 dist 工具中的 xinit() 函数中进行初始化。

环境变量目的
GOROOTGo 存储库的根目录
GOOS目标操作系统
GOARCH目标架构
GOARM, GOARM64, GO386 等特定于体系结构的选项
GOHOSTOS, GOHOSTARCH主机操作系统和体系结构
GOEXPERIMENT要启用的实验性功能
GOFIPS140FIPS 140 模式配置

来源: src/cmd/dist/build.go109-278 src/cmd/dist/build.go490-606

启动过程

Go 的引导过程是一个多阶段编译过程,解决了使用 Go 编译 Go 的鸡生蛋还是蛋生鸡的问题。该过程分为几个阶段:

在引导过程中

  1. setup() 函数准备目录结构
  2. 主机 Go 编译器(之前已安装)构建一个引导编译器
  3. 引导编译器构建最小编译器(go_bootstrap
  4. go_bootstrap 构建实际的 Go 工具链
  5. 然后,工具链用于再次构建自身以进行验证和优化

来源: src/cmd/dist/build.go525-606 src/cmd/dist/build.go677-1063

包安装

Go 的构建系统采用基于包的编译方法,由 install()runInstall() 等函数管理。这些函数负责编译单个包、解析依赖项并将生成的工件放置在适当的位置。

包安装的关键步骤

  1. 检查包是否已构建或是最新的
  2. 识别用于编译的源文件
  3. 生成任何必要的文件(例如 zdefaultcc.go)
  4. 解析和构建依赖项
  5. 使用适当的编译器编译 Go 文件
  6. 如果存在,则编译汇编文件
  7. 链接或归档生成的对象文件

来源: src/cmd/dist/build.go677-1063 src/cmd/dist/buildgo.go31-64

测试框架

Go 项目使用一个全面的测试框架,由 dist test 命令管理。测试由 tester 结构协调,该结构处理许多不同类型的测试。

测试类型包括

  1. 标准包测试(go test std cmd
  2. 竞态检测器测试(-race 标志)
  3. 内存沙箱器测试(-msan 标志)
  4. 地址沙箱器测试(-asan 标志)
  5. 特定平台的测试
  6. 构建模式测试(不同的编译模式)
  7. 外部链接测试
  8. 纯 Go 实现测试
  9. FIPS 合规性测试

来源: src/cmd/dist/test.go27-275 src/cmd/dist/test.go543-994 src/cmd/dist/testjson.go17-27

测试执行

Go 中的测试是高度并行化的,并进行了仔细的依赖管理。work 结构表示一个测试作业,而 tester 结构协调执行。

测试执行的关键方面

  1. 可以使用 -run 正则表达式过滤测试
  2. 测试可以在启用或不启用竞态检测器的情况下运行
  3. 测试可以被构建但不能运行(-compile-only
  4. 测试可以在出错时继续运行(-k 标志)
  5. 测试可以生成 JSON 输出(-json 标志)

来源: src/cmd/dist/test.go83-94 src/cmd/dist/test.go112-275 src/cmd/dist/testjson.go17-27

架构和平台支持

Go 支持广泛的架构和操作系统,并为不同平台提供专门的处理。

平台支持的差异通过以下方式处理:

  1. 不同的工具链策略(例如,交叉编译)
  2. 特定平台的构建标签
  3. 条件链接策略(内部链接 vs. 外部链接)
  4. 对 cgo 启用平台的特殊处理

来源: src/internal/platform/supported.go19-34 src/internal/platform/zosarch.go10-57 src/cmd/dist/build.go70-106

构建模式

Go 支持多种构建模式,这些模式会影响代码的编译和链接方式。buildModeInit() 函数在 build 包中配置这些模式。

构建模式描述
archive常规包归档 (.a 文件)
c-archiveC 兼容的归档,可以链接到 C 程序中
c-sharedC 兼容的共享库 (.so, .dll, .dylib)
默认默认可执行文件(在某些平台上可能是 PIE)
exe强制非 PIE 可执行文件
pie位置无关的可执行文件
shared用于动态链接的 Go 共享库
plugin可加载插件 (go plugin)

来源: src/cmd/go/internal/work/init.go188-342 src/cmd/link/internal/ld/config.go13-114

版本控制和发布流程

Go 使用语义化版本控制,并采用独特的版本标识方案。版本信息来自多个来源:

  1. Go 根目录中的 VERSION 文件
  2. 来自存储库的 Git 信息
  3. 存储在 src/internal/goversion/goversion.go 中的内部版本号

findgoversion() 中构造版本字符串,格式如下:

  • go1.21.0 (用于发布版本)
  • devel go1.21-abc123 (用于开发版本)

来源: src/cmd/dist/build.go362-445

更改 Go

在对 Go 仓库进行更改时,开发者遵循以下工作流程:

  1. 设置环境(GOROOT 等)
  2. 进行代码更改
  3. 使用 ./make.bash./make.bat 构建 Go
  4. 使用 go testdist test 运行相关测试
  5. 验证跨平台兼容性
  6. 提交更改以供审查

来源:src/cmd/dist/test.go956-994 src/cmd/dist/build.go109-154

交叉编译支持

Go 构建系统支持通过环境变量和编译器配置进行交叉编译。

  1. 设置 GOOS 和 GOARCH 以定位目标平台
  2. 根据需要使用特定于体系结构的变量,如 GOARM、GO386 等。
  3. 交叉编译时,cgo 的处理方式有所不同。

交叉编译在构建系统中拥有特殊的处理方式,包括不同的链接策略和编译器标志。compilerEnv() 函数通过将不同的编译器设置映射到不同的目标平台来管理这种复杂性。

来源:src/cmd/dist/build.go280-319 src/cmd/dist/build.go609-656

总结

Go 的开发工作流程结合了自定义构建系统和全面的测试,以确保在众多平台上发布高质量的软件。dist 工具协调这一过程,处理引导的挑战、依赖管理和特定于平台的各种需求。理解这个工作流程对于任何为 Go 本身做出贡献的人来说都是至关重要的。