runsisi's

technical notes

从源代码构建 go

2019-03-21 runsisi#golang

有多种方法从源代码构建 go,其中的关键是准备自举所需的工具链。

gcc 构建 go1.4 并实现自举

go1.4 是最后一个使用 C 语言实现 go 工具链的版本。

~$ pwd
/home/runsisi/build
~$ wget https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz
--2019-03-21 13:59:54--  https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz
...
~$ mkdir go1.4
~$ tar xvzf go1.4-bootstrap-20171003.tar.gz -C go1.4/ --strip-components 1
go/.gitattributes
go/.gitignore
go/.hgignore
go/.hgtags
go/AUTHORS
go/CONTRIBUTORS
go/LICENSE
go/PATENTS
go/README
go/VERSION
go/api/
...
~$ cd go1.4/src/
~$ ./make.bash
# Building C bootstrap tool.
cmd/dist

# Building compilers and Go bootstrap tool for host, linux/amd64.
...
Installed Go for linux/amd64 in /home/runsisi/build/go1.4
Installed commands in /home/runsisi/build/go1.4/bin
~$ cd ../..
~$ pwd
/home/runsisi/build
~$ export GOROOT_BOOTSTRAP=$PWD/go1.4
~$ env | grep GOROOT_BOOTSTRAP
GOROOT_BOOTSTRAP=/home/runsisi/build/go1.4
~$ git clone https://github.com/golang/go.git go-src
Cloning into 'go-src'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
...
~$ cd go-src/src/
~$ ./make.bash
Building Go cmd/dist using /home/runsisi/build/go1.4.
Building Go toolchain1 using /home/runsisi/build/go1.4.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for linux/amd64.
---
Installed Go for linux/amd64 in /home/runsisi/build/go-src
Installed commands in /home/runsisi/build/go-src/bin
~$ cd ../..
~$ pwd
/home/runsisi/build
~$ export GOROOT=$PWD/go-src
~$ env | grep GOROOT
GOROOT_BOOTSTRAP=/home/runsisi/build/go1.4
GOROOT=/home/runsisi/build/go-src
~$ export PATH=$GOROOT/bin:$PATH
~$ env | grep PATH
PATH=/home/runsisi/build/go-src/bin:/home/runsisi/bin:/home/runsisi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
~$ go version
go version devel +0fe1986 Thu Mar 21 01:35:21 2019 +0000 linux/amd64
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/runsisi/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/runsisi/go"
GOPROXY=""
GORACE=""
GOROOT="/home/runsisi/build/go-src"
GOTMPDIR=""
GOTOOLDIR="/home/runsisi/build/go-src/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build558142010=/tmp/go-build -gno-record-gcc-switches"

使用官方构建的 go 实现自举

~$ pwd
/home/runsisi/build
~$ wget https://dl.google.com/go/go1.12.1.linux-amd64.tar.gz
--2019-03-21 15:34:19--  https://dl.google.com/go/go1.12.1.linux-amd64.tar.gz
...
~$ mkdir go1.12.1
~$ tar xvzf go1.12.1.linux-amd64.tar.gz -C go1.12.1/ --strip-components 1
go/AUTHORS
go/CONTRIBUTING.md
go/CONTRIBUTORS
go/LICENSE
go/PATENTS
go/README.md
go/VERSION
go/api/
...
~$ export GOROOT_BOOTSTRAP=$PWD/go1.12.1
~$ env | grep GOROOT_BOOTSTRAP
GOROOT_BOOTSTRAP=/home/runsisi/build/go1.12.1
~$ git clone https://github.com/golang/go.git go-src
Cloning into 'go-src'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
...
~$ cd go-src/src/
~$ ./make.bash
Building Go cmd/dist using /home/runsisi/build/go1.12.1.
Building Go toolchain1 using /home/runsisi/build/go1.12.1.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for linux/amd64.
---
Installed Go for linux/amd64 in /home/runsisi/build/go-src
Installed commands in /home/runsisi/build/go-src/bin
~$ cd ../..
~$ pwd
/home/runsisi/build
~$ export GOROOT=$PWD/go-src
~$ env | grep GOROOT
GOROOT_BOOTSTRAP=/home/runsisi/build/go1.12.1
GOROOT=/home/runsisi/build/go-src
~$ export PATH=$GOROOT/bin:$PATH
~$ env | grep PATH
PATH=/home/runsisi/build/go-src/bin:/home/runsisi/bin:/home/runsisi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
~$ go version
go version devel +0fe1986 Thu Mar 21 01:35:21 2019 +0000 linux/amd64
~$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/runsisi/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/runsisi/go"
GOPROXY=""
GORACE=""
GOROOT="/home/runsisi/build/go-src"
GOTMPDIR=""
GOTOOLDIR="/home/runsisi/build/go-src/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build768513990=/tmp/go-build -gno-record-gcc-switches"

使用发行版自带的 go 实现自举

~$ pwd
/home/runsisi/build
~$ sudo apt install golang-go
Reading package lists... Done
Building dependency tree
Reading state information... Done
...
The following NEW packages will be installed:
  golang-1.6-go golang-1.6-race-detector-runtime golang-1.6-src golang-go golang-race-detector-runtime golang-src
...
~$ go env GOROOT
/usr/lib/go-1.6
~$ export GOROOT_BOOTSTRAP=/usr/lib/go-1.6
~$ git clone https://github.com/golang/go.git go-src
Cloning into 'go-src'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
...
~$ cd go-src/src/
~$ ./make.bash
Building Go cmd/dist using /usr/lib/go-1.6.
Building Go toolchain1 using /usr/lib/go-1.6.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for linux/amd64.
---
Installed Go for linux/amd64 in /home/runsisi/build/go-src
Installed commands in /home/runsisi/build/go-src/bin
~$ cd ../..
~$ pwd
/home/runsisi/build
~$ export GOROOT=$PWD/go-src
~$ env | grep GOROOT
GOROOT_BOOTSTRAP=/usr/lib/go-1.6
GOROOT=/home/runsisi/build/go-src
~$ export PATH=$GOROOT/bin:$PATH
~$ env | grep PATH
PATH=/home/runsisi/build/go-src/bin:/home/runsisi/bin:/home/runsisi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
~$ go version
go version devel +0fe1986 Thu Mar 21 01:35:21 2019 +0000 linux/amd64
~$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/runsisi/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/runsisi/go"
GOPROXY=""
GORACE=""
GOROOT="/home/runsisi/build/go-src"
GOTMPDIR=""
GOTOOLDIR="/home/runsisi/build/go-src/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build576587668=/tmp/go-build -gno-record-gcc-switches"

注意事项

  1. 如果没有在环境变量中定义 GOPATH,那么 GOPATH 默认为 $HOME/go (src/go/build/build.go/defaultGOPATH);
  2. 如果没有在环境变量中定义 GOROOT,那么 GOROOT 默认为构建时源代码所在的路径 (src/runtime/extern.go/GOROOT),如果需要修改这个默认值,可以在构建时设置 GOROOT_FINAL 环境变量;
  3. 不管构建时 GOROOT_FINAL 是否设置,如果构建后保持目录结构不变go env GOROOT 得到的是源代码所在路径 (src/cmd/go/internal/cfg/cfg.go/findGOROOT),因此从官方下载的构建版本无需显式设置 GOROOT

参考资料

Installing Go from source

https://golang.org/doc/install/source

You don’t need to set GOROOT, really

https://dave.cheney.net/2013/06/14/you-dont-need-to-set-goroot-really