重新编译生成go工具

67 阅读2分钟

查看编译安装过程

./make.bash中, 通过编译 cmd/dist 工具后执行后续的编译命令, 我们先查看 cmd/dist/main.go 文件


// 对应命令调用的函数信息
var commands = map[string]func(){
    "banner":    cmdbanner,
    "bootstrap": cmdbootstrap,
    "clean":     cmdclean,
    "env":       cmdenv,
    "install":   cmdinstall,
    "list":      cmdlist,
    "test":      cmdtest,
    "version":   cmdversion,
}

// main takes care of OS-specific startup and dispatches to xmain.
func main() {
    ...
    // 初始化全局状态信息, 比如GOROOT等信息
    xinit()
    // 执行具体操作的命令函数
    xmain()
}

func xmain() {
    ...
    // 根据命令判断调用的具体函数
    if f, ok := commands[cmd]; ok {
        f()
    } else {
        xprintf("unknown command %s\n", cmd)
        usage()
    }
}

根据make.bash末尾执行的命令dist bootstrap -a, 我们查看cmdbootstrap执行的操作, 这个操作会使用 src/cmd 将 src/bin 下的 go 和 gofmt, src/pkg/tool下的工具重新安装

func cmdbootstrap() {
    // 如果设置了 GOBUILDTIMELOGFILE 就会将各个阶段执行的时间输出到具体的文件中,方便查看各个阶段执行的具体时间
    timelog("start", "dist bootstrap")
    defer timelog("end", "dist bootstrap")
    ...
    
    // 全部重建,删除src下的可执行文件. 删除pkg下的安装包,
    if rebuildall {
       clean()
    }
    
    // 构建目录,删除构建缓存
    setup()

    timelog("build", "toolchain1")
    
    // 检查编译时时候需要gcc
    checkCC()
    // 检查 GOROOT_BOOTSTRAP 是否符合最低编译需求, 通过 GOROOT_BOOTSTRAP 把 bootstrapDirs 中指定的文件夹从src复制到
    // goroot/pkg/bootstrap/src下, 然后运行命令安装到 goroot/pkg/bootstrap/pkg, 安装完成后复制到 GOTOOLDIR 文件夹下
    // /opt/bitnami/bootstrap/bin/go install -tags=math_big_pure_go compiler_bootstrap purego bootstrap/cmd/...
    bootstrapBuildTools()
    ...
    
    // 编译安装 runtime, time/tzdata, cmd/go
    // cmd/go 安装后被重命名为go_bootstrap
    install("runtime")     // dependency not visible in sources; also sets up textflag.h
    install("time/tzdata") // no dependency in sources; creates generated file
    install("cmd/go")
    
    ...
    
    timelog("build", "toolchain2")
    ...
    // 使用 go_bootstrap安装 "cmd/asm", "cmd/cgo", "cmd/compile", "cmd/link", "cmd/preprofile"
    goInstall(toolenv(), goBootstrap, append([]string{"-pgo=off"}, toolchain...)...)

    ...
    
    timelog("build", "toolchain3")
    ...
    // 安装tool工具
    goInstall(toolenv(), goBootstrap, append([]string{"-a"}, toolchain...)...)
    
    // 安装go 和 gofmt,并检查重新编译后的工具能否正常使用
    goInstall(nil, goBootstrap, "std")
    goInstall(toolenv(), goBootstrap, "cmd")
    checkNotStale(toolenv(), goBootstrap, toolchain...)
    checkNotStale(nil, goBootstrap, "std")
    checkNotStale(toolenv(), goBootstrap, "cmd")
    checkNotStale(nil, gorootBinGo, "std")
    checkNotStale(toolenv(), gorootBinGo, "cmd")
}