原始碼安裝GO

nintyuui發表於2021-09-09

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

一、分析安裝指令碼

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

1、all.bash

1 set -e
2 if [ ! -f make.bash ]; then
3     echo 'all.bash must be run from $GOROOT/src' 1>&2
4     exit 1
5 fi
6 OLDPATH="$PATH"
7 . ./make.bash --no-banner
8 bash run.bash --no-rebuild
9 PATH="$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指令碼(關鍵部分)

1 echo '# Building C bootstrap tool.'
2 echo cmd/dist
3 # export當前Go原始碼所在跟目錄為GOROOT
4 export GOROOT="$(cd .. && pwd)"
5 # 如果GOROOT_FINAL沒有設定,則使用$GOROOT的值當做GOROOT_FINAL
6 GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
7 DEFGOROOT='-DGOROOT_FINAL="'"$GOROOT_FINAL"'"'
8
9 # 如果在amd64機子上編譯Go本身為32位,可以設定 $GOHOSTARCH=386。不建議這麼做
10 mflag=""
11 case "$GOHOSTARCH" in
12 386) mflag=-m32;;
13 amd64) mflag=-m64;;
14 esac
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"
25 gcc $mflag -O2 -Wall -Werror -ggdb -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
26
27 # 編譯完 dist 工具後,執行dist。目的是設定相關環境變數
28 # 比如:$GOTOOLDIR 環境變數就是這裡設定的
29 eval $(./cmd/dist/dist env -p)
30 echo
31
32 # 執行make.bash時傳遞--dist-tool引數可以僅編譯dist工具
33 if [ "$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
41 fi
42
43 # 構建 編譯器和Go引導工具
44 # $GOHOSTOS/$GOHOSTARCH 是執行dist設定的
45 echo "# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."
46 # 表示重新構建
47 buildall="-a"
48 # 傳遞--no-clean 表示不重新構建
49 if [ "$1" = "--no-clean" ]; then
50     buildall=""
51 fi
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.
55 mv cmd/dist/dist "$GOTOOLDIR"/dist
56 "$GOTOOLDIR"/go_bootstrap clean -i std
57 echo
58
59 # $GOHOSTARCH 與 $GOARCH的區別:($GOHOSTOS 與 $GOOS的區別一樣)
60 #   GOARCH 表示Go寫出來的程式會在什麼架構執行(目標作業系統);
61 #   GOHOSTARCH 表示執行make.bash這個指令碼的系統架構
62 # 一般它們是相等的,只有在需要交叉編譯時才會不一樣。
63 if [ "$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
69 fi
70
71 echo "# Building packages and commands for $GOOS/$GOARCH."
72 "$GOTOOLDIR"/go_bootstrap install -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
73 echo
74
75 rm -f "$GOTOOLDIR"/go_bootstrap
76
77 # 是否列印安裝成功的提示資訊。一般為:
78 #   Installed Go for $GOOS/$GOARCH in $GOROOT
79 #   Installed commands in $GOROOT/bin
80 if [ "$1" != "--no-banner" ]; then
81     "$GOTOOLDIR"/dist banner


82 fi




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


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3209/viewspace-2817762/,如需轉載,請註明出處,否則將追究法律責任。

相關文章