源碼安裝GO

安裝Go語言,建議通過源碼安裝。通過源碼安裝Go,一般只需要安裝一個GCC編譯器就可以了。(Windows下是安裝MinGW)。該文分析通過源碼安裝Go語言的過程。

一、分析安裝腳本

《探究Go中各個目錄的功能》一文中提到了幾個腳本,以及它們的作用。現在來分析這些腳本都做了些什麼。(以linux下爲例,Windows對應的腳本類似)

1、all.bash

1set -e
2if [ ! -f make.bash ]; then
3    echo 'all.bash must be run from $GOROOT/src' 1>&2
4    exit 1
5fi
6OLDPATH="$PATH"
7. ./make.bash --no-banner
8bash run.bash --no-rebuild
9PATH="$OLDPATH"
10$GOTOOLDIR/dist banner  # print build info

說明:

1)set -e 當腳本中某個命令返回非零退出狀態時,腳本退出
2)if語句 是要求all.bash必須在make.bash所在的目錄運行(也就是$GOROOT/src)
3)OLDPATH=”$PATH” 保存當前PATH
4)執行make.bash並傳遞–no-banner參數
5)執行run.bash並傳遞–no-rebuild參數
6)執行dist工具並傳遞 banner參數,打印build信息

2、make.bash

在make.bash中,有一些環境變量,執行make.bash過程中會用到。

①GOROOT_FINAL:最終被設置的Go root,在編譯過程中,默認是Go tree的位置。

②GOHOSTARCH:爲主機工具(編譯器和二進制文件)指定體系結構。這種類型的二進制文件在當前系統必須是可執行的,因此設置這個環境變量的目前唯一常見原因是在AMD64機器上設置GOHOSTARCH=386。(也就是說,在ADM64上可以運行386的可執行文件)

③GO_GCFLAGS:當構建包和命令時可以通過該環境變量附帶上5g/6g/8g的參數

④GO_LDFLAGS:當構建包和命令時可以通過該環境變量附帶上5l/6l/8l的參數

⑤CGO_ENABLED:在構建過程中控制cgo的使用。當設置爲1,在構建時,會包含所有cgo相關的文件,如帶有”cgo”編譯指令的.c和.go文件。當設置爲0,則忽略它們(即禁用CGO)

在文件開頭是一些檢查:比如是否在Windows下運行了make.bash,ld的版本等。

make.bash中接下來主要的工作(也就是開始構建):

1)構建 C 引導工具 —— cmd/dist

這裏首先會export GOROOT環境變量,它的值就是go源碼所在路徑,可見,源碼安裝之前並不要求一定要設置GOROOT。

這裏學習一個shell腳本知識

GOROOT_FINAL=”${GOROOT_FINAL:-$GOROOT}”
這叫做參數替換,形式如下:
${parameter-default},${parameter:-default}
意思是:如果 parameter 沒被 set,那麼就使用 default。這兩種形式大部分時候是相同的。區別是:當parameter被設置了且爲空,則第一種不能輸出默認值,而第二種可以。

所以,GOROOT_FINAL=”${GOROOT_FINAL:-$GOROOT}”的意思就是,如果GOROOT_FINAL沒設置,則GOROOT_FINAL=$GOROOT

通過gcc編譯cmd/dist

2)構建 編譯器和Go引導工具

首先通過執行dist設置需要的環境變量
eval $(./cmd/dist/dist env -p)

接着構建Go引導工具:go_bootstrap,以及編譯器等

3)構建 包和命令工具

這是通過go_bootstrap做的

3、run.bash

該腳本是一個測試腳本,運行標準庫中的測試用例。默認情況下會重新構建go包和工具。由於make.bash會做構建的工作,all.bash中執行run.bash時,傳遞了–no-rebuild

二、源碼安裝說明

源碼安裝Go語言,一般只需要執行./all.bash就可以了。(Windows上執行all.bat)

根據上面的分析,這樣會運行測試腳本。如果想更快的安裝Go,可以直接運行make.bash(Windows上是make.bat)

整個安裝過程大概如下:

# Building C bootstrap tool.
cmd/dist

# Building compilers and Go bootstrap tool for host, linux/amd64.
lib9
libbio
libmach
misc/pprof
……
pkg/text/template/parse
pkg/text/template
pkg/go/doc
pkg/go/build
cmd/go

# Building packages and commands for linux/amd64.
runtime
errors
sync/atomic
sync
io
……
testing
testing/iotest
testing/quick

# Testing packages.
ok cmd/api 0.031s
? cmd/cgo [no test files]
ok cmd/fix 3.558s
ok cmd/go 0.022s
……
? unsafe [no test files]

real 3m6.056s
user 2m29.517s
sys 0m25.134s
# GOMAXPROCS=2 runtime -cpu=1,2,4
ok runtime 6.605s

# sync -cpu=10
ok sync 0.428s

# Testing race detector.
ok flag 1.044s

# ../misc/cgo/stdio

# ../misc/cgo/life

# ../misc/cgo/test
scatter = 0×430490
hello from C
PASS
ok _/home/polaris/go/misc/cgo/test 1.137s

# ../misc/cgo/testso

# ../doc/progs

real 0m19.110s
user 0m15.341s
sys 0m2.904s

# ../doc/articles/wiki
run.bash: 行 92: make: 未找到命令
PASS

# ../doc/codewalk

# ../misc/dashboard/builder ../misc/goplay

# ../test/bench/shootout
fasta
reverse-complement
nbody
binary-tree
binary-tree-freelist
fannkuch
fannkuch-parallel
regex-dna
regex-dna-parallel
spectral-norm
k-nucleotide
k-nucleotide-parallel
mandelbrot
meteor-contest
pidigits
threadring
chameneosredux

# ../test/bench/go1
ok _/home/polaris/go/test/bench/go1 4.942s

# ../test

real 1m38.036s
user 1m14.701s
sys 0m16.645s

# Checking API compatibility.
+pkg crypto/x509, const PEMCipher3DES PEMCipher
+pkg crypto/x509, const PEMCipherAES128 PEMCipher
+pkg crypto/x509, const PEMCipherAES192 PEMCipher
+pkg crypto/x509, const PEMCipherAES256 PEMCipher
+pkg crypto/x509, const PEMCipherDES PEMCipher
+pkg crypto/x509, func EncryptPEMBlock(io.Reader, string, []byte, []byte, PEMCipher)
……
+pkg reflect, func SliceOf(Type) Type
+pkg regexp, method (*Regexp) Split(string, int) []string
~pkg text/template/parse, type DotNode bool
~pkg text/template/parse, type Node interface { Copy, String, Type }

ALL TESTS PASSED


Installed Go for linux/amd64 in /home/polaris/go
Installed commands in /home/polaris/go/bin
*** You need to add /home/polaris/go/bin to your PATH.

三、帶中文註釋的腳本

以下是我加上了註釋的make.bash腳本(關鍵部分)

1echo '# Building C bootstrap tool.'
2echo cmd/dist
3# export當前Go源碼所在跟目錄爲GOROOT
4export GOROOT="$(cd .. && pwd)"
5# 如果GOROOT_FINAL沒有設置,則使用$GOROOT的值當做GOROOT_FINAL
6GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
7DEFGOROOT='-DGOROOT_FINAL="'"$GOROOT_FINAL"'"'
8
9# 如果在amd64機子上編譯Go本身爲32位,可以設置 $GOHOSTARCH=386。不建議這麼做
10mflag=""
11case "$GOHOSTARCH" in
12386) mflag=-m32;;
13amd64) mflag=-m64;;
14esac
15
16# gcc編譯:編譯cmd/dist下所有的c文件
17# -m:指定處理器架構,以便進行優化(-m32、-m64)或爲空(一般爲空)
18# -O:優化選項,一般爲:-O2。優化得到的程序比沒優化的要小,執行速度可能也有所提高
19# -Wall:生成所有警告信息
20# -Werror:所有警告信息都變成錯誤
21# -ggdb:爲gdb生成調試信息(-g是生成調試信息)
22# -o:生成指定的輸出文件
23# -I:指定額外的文件搜索路徑
24# -D:相當於C語言中的#define GOROOT_FINAL="$GOROOT_FINAL"
25gcc $mflag -O2 -Wall -Werror -ggdb -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
26
27# 編譯完 dist 工具後,運行dist。目的是設置相關環境變量
28# 比如:$GOTOOLDIR 環境變量就是這裏設置的
29eval $(./cmd/dist/dist env -p)
30echo
31
32# 運行make.bash時傳遞--dist-tool參數可以僅編譯dist工具
33if [ "$1" = "--dist-tool" ]; then
34    # Stop after building dist tool.
35    mkdir -p "$GOTOOLDIR"
36    if [ "$2" != "" ]; then
37        cp cmd/dist/dist "$2"
38    fi
39    mv cmd/dist/dist "$GOTOOLDIR"/dist
40    exit 0
41fi
42
43# 構建 編譯器和Go引導工具
44# $GOHOSTOS/$GOHOSTARCH 是運行dist設置的
45echo "# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."
46# 表示重新構建
47buildall="-a"
48# 傳遞--no-clean 表示不重新構建
49if [ "$1" = "--no-clean" ]; then
50    buildall=""
51fi
52# 構建Go引導工具
53./cmd/dist/dist bootstrap $buildall -v # builds go_bootstrap
54# Delay move of dist tool to now, because bootstrap may clear tool directory.
55mv cmd/dist/dist "$GOTOOLDIR"/dist
56"$GOTOOLDIR"/go_bootstrap clean -i std
57echo
58
59# $GOHOSTARCH 與 $GOARCH的區別:($GOHOSTOS 與 $GOOS的區別一樣)
60#   GOARCH 表示Go寫出來的程序會在什麼架構運行(目標操作系統);
61#   GOHOSTARCH 表示運行make.bash這個腳本的系統架構
62# 一般它們是相等的,只有在需要交叉編譯時纔會不一樣。
63if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then
64    # 即使交叉編譯,本機的Go環境還是必須得有
65    echo "# Building packages and commands for host, $GOHOSTOS/$GOHOSTARCH."
66    GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
67        "$GOTOOLDIR"/go_bootstrap install -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
68    echo
69fi
70
71echo "# Building packages and commands for $GOOS/$GOARCH."
72"$GOTOOLDIR"/go_bootstrap install -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
73echo
74
75rm -f "$GOTOOLDIR"/go_bootstrap
76
77# 是否打印安裝成功的提示信息。一般爲:
78#   Installed Go for $GOOS/$GOARCH in $GOROOT
79#   Installed commands in $GOROOT/bin
80if [ "$1" != "--no-banner" ]; then
81    "$GOTOOLDIR"/dist banner

82fi


注:有些是根據腳本中的英文翻譯的,如不明白,請看腳本的註釋;如有不對,請指正!謝謝!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章