安裝Go語言,建議透過原始碼安裝。透過原始碼安裝Go,一般只需要安裝一個GCC編譯器就可以了。(Windows下是安裝MinGW)。該文分析透過原始碼安裝Go語言的過程。
一、分析安裝指令碼
在《探究Go中各個目錄的功能》一文中提到了幾個指令碼,以及它們的作用。現在來分析這些指令碼都做了些什麼。(以linux下為例,Windows對應的指令碼類似)
1、all.bash
2 |
if [ ! -f make . bash ]; then
|
3 |
echo 'all.bash must be run from $GOROOT/src' 1>&2
|
7 |
. ./ make . bash --no-banner
|
8 |
bash run. bash --no-rebuild
|
10 |
$GOTOOLDIR/dist banner
|
說明:
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指令碼(關鍵部分)
1 |
echo '# Building C bootstrap tool.'
|
4 |
export GOROOT= "$(cd .. && pwd)"
|
6 |
GOROOT_FINAL= "${GOROOT_FINAL:-$GOROOT}"
|
7 |
DEFGOROOT= '-DGOROOT_FINAL="' "$GOROOT_FINAL "'" '
|
25 |
gcc $mflag -O2 -Wall -Werror -ggdb -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
|
29 |
eval $(./cmd/dist/dist env -p)
|
33 |
if [ "$1" = "--dist-tool" ]; then
|
36 |
if [ "$2" != "" ]; then
|
39 |
mv cmd/dist/dist "$GOTOOLDIR" /dist
|
45 |
echo "# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."
|
49 |
if [ "$1" = "--no-clean" ]; then
|
53 |
./cmd/dist/dist bootstrap $buildall - v
|
55 |
mv cmd/dist/dist "$GOTOOLDIR" /dist
|
56 |
"$GOTOOLDIR" /go_bootstrap clean -i std
|
63 |
if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then
|
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
|
71 |
echo "# Building packages and commands for $GOOS/$GOARCH."
|
72 |
"$GOTOOLDIR" /go_bootstrap install -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" - v std
|
75 |
rm -f "$GOTOOLDIR" /go_bootstrap
|
80 |
if [ "$1" != "--no-banner" ]; then
|
81 |
"$GOTOOLDIR" /dist banner
|
注:有些是根據指令碼中的英文翻譯的,如不明白,請看指令碼的註釋;如有不對,請指正!謝謝!