龍芯平臺構建Go語言環境指南
http://www.loongson.cn/news/company/456.html
一、初識Go語言
Go語言是Google公司於2009年正式推出的一款開源的程式語言,是由Robert Griesemer、Ken Thompson和Rob Pike等世界頂尖計算科學家精心打造的系統程式語言。Go語言最顯著的特點是編碼簡潔迅速、支援高效併發和自動記憶體管理等。此外,Go語言還面向網路伺服器、儲存系統和資料庫等領域的程式設計進行了優化設計,並且簡化了應用系統的安裝和部署。因此,Go語言受到了廣大程式設計師的青睞,越來越多地開始應用於谷歌和百度等知名中外企業的產品中。
Go語言形象標識
對於這樣一個在雲端計算和大資料時代最具發展前景的程式語言,龍芯平臺能不能很好地支援呢?今天我們就從Go的原始碼開始,逐步構建龍芯平臺上的Go語言環境。儘管筆者的實驗機器為安裝了龍芯開源社群版作業系統Loongnix的龍芯3B迷你電腦,本文的方法適用於所有64位作業系統的MIPS處理器平臺。
一、下載Go語言的原始碼
為了吸引更多的社群開發力量,Google開源了Go語言的原始碼,並託管於世界著名的github網站中。我們可以通過執行以下命令獲取Go語言的全套原始碼:
$ cd ~ $ git clone https://github.com/golang/go.git |
上述命令要求您的電腦中安裝了git版本控制工具。如果您的電腦中沒有預裝git,可以通過如下命令快速安裝:
$ sudo yum install git |
二、從原始碼構建Go語言環境
由於當前最新發布的Go語言的穩定版本為Go 1.6,並且官方從該版本開始正式支援MIPS架構的處理器,故筆者以Go 1.6為例展示Go語言環境在龍芯平臺上的構建方法。為了最大限度減少Go語言對其它程式設計工具的依賴,從Go 1.5開始,Go語言的編譯器、彙編器和連結器等底層工具鏈全部使用Go語言來實現。故自Go 1.5開始,從原始碼安裝Go語言環境時需要使用現成的Go語言編譯器來編譯Go的原始碼,上述過程稱為Go語言的自舉編譯。因此,從原始碼安裝Go 1.6時要求系統中存在Go 1.4及其以上的Go語言環境。
由於官方從Go 1.6才開始正式支援MIPS架構,因而無法找到現成的可用於在龍芯上進行自舉編譯的低版本Go編譯器。好在Go語言提供了友好的交叉編譯功能,我們可以藉助X86的機器編譯一個MIPS平臺的Go編譯器,用作在龍芯上從原始碼構建Go 1.6的自舉編譯器。因此,在龍芯平臺上從原始碼構建Go 1.6的環境必須分成兩個階段進行:
1) 在X86平臺上交叉編譯出面向MIPS平臺的Go語言自舉編譯工具鏈;
2) 在龍芯平臺上利用1)中的Go自舉編譯器構建Go 1.6開發環境。
下面筆者逐步向大家展示Go 1.6環境在龍芯平臺上的構建過程。等大家走完整個過程就會發現,在龍芯上從原始碼安裝Go語言環境非常簡單。
第一階段:在
隨便找一臺裝有64位Linux作業系統的X86電腦,逐步執行以下命令。
1. 下載Go 1.4(或者更高版本)的二進位制發行版作為交叉編譯的自舉編譯工具鏈
筆者選擇Go 1.4的發行版作為在X86上編譯Go 1.6原始碼的自舉編譯器。由於官網 https://golang.org 在國內無法正常訪問,可以通過其映象站點 http://golangtc.com/download進行下載。筆者下載的檔案為go1.4.2.linux-amd64.tar.gz,大小約59 M。下載後可以解壓到任意目錄,例如可以通過如下命令將其解壓到/opt資料夾下並重命名為go1.4.2:
$ tar xvzf go1.4.2.linux-amd64.tar.gz -C /opt $ mv /opt/go /opt/go1.4.2 |
2. 配置交叉編譯的自舉編譯工具鏈
$ export GOROOT_BOOTSTRAP=/opt/go1.4.2 |
3. 下載Go 1.6的原始碼
$ cd ~/workspace/golang/ $ git clone https://github.com/golang/go.git |
4. 切換到Go 1.6的發行版
$ cd go $ git checkout release-branch.go1.6 |
5. 交叉編譯
這一步通過執行指令碼bootstrp.bash完成。該指令碼執行前,需要通過環境變數GOOS和GOARCH分別指明交叉編譯的目標作業系統和處理器架構。
$ cd ~/workspace/golang/go/src $ GOOS=linux GOARCH=mips64le ./bootstrap.bash |
接下來就是等待交叉編譯結束了。由於交叉編譯無需執行Go語言官方自帶的測試集,一般10分鐘內即可完成編譯。不出意外的話,整個過程應該非常順利。如果您看到以下提示,則表明交叉編譯成功。
---- Bootstrap toolchain for linux/mips64le installed in /home/fool/workspace/golang/go-linux-mips64le-bootstrap. Building tbz. -rw-rw-r-- 1 fool fool 46736199 6月 3 09:08 /home/fool/workspace/golang/go-linux-mips64le-bootstrap.tbz |
交叉編譯所生成的面向MIPS平臺的Go語言自舉編譯工具鏈位於壓縮包/home/fool/workspace/golang/go-linux-mips64le-bootstrap.tbz中。將該壓縮包拷貝到龍芯電腦中備用。
第二階段:在龍芯平臺上從原始碼構建Go 1.6開發環境。
1. 解壓交叉編譯生成的面向MIPS平臺的自舉編譯工具鏈
$ tar xvjf go-linux-mips64le-bootstrap.tbz -C ~/workspace |
2. 簡單檢驗自舉編譯工具鏈是否可用
$ cd ~/workspace/go-linux-mips64le-bootstrap/bin $ export GOROOT=/home/loongson/workspace/go-linux-mips64le-bootstrap $ ./go version |
如果觀察到以下輸出,則基本可以說明交叉編譯沒有問題。
go version go1.6.2 linux/mips64le |
3. 下載Go 1.6的原始碼並切換到Go 1.6的發行版。
$ cd ~/workspace $ git clone https://github.com/golang/go.git $ cd go $ git checkout release-branch.go1.6 |
4. 編譯配置
在當前目錄建立名為env.sh的shell指令碼,輸入以下語句後儲存退出。
#!/bin/bash export GOROOT_BOOTSTRAP=/home/loongson/workspace/go-linux-mips64le-bootstrap export GOROOT=/home/loongson/workspace/go |
其中,GOROOT_BOOTSTRAP用於指向自舉編譯工具鏈的根目錄,GOROOT指向Go 1.6原始碼的根目錄。
執行env.sh,以完成編譯配置。
$ source env.sh |
5. 首次編譯
$ cd src $ ./all.bash |
上述指令碼執行時,首先會利用自舉編譯工具鏈完成對Go 1.6原始碼的編譯,生成龍芯上的Go 1.6環境。隨後利用官方的測試集對生成的本地Go 1.6進行測試。測試的過程相對漫長,需要耐心等待。約20分鐘後,測試期間中突然列印如下錯誤資訊:
ok cmd/compile/internal/test 0.038s ok cmd/cover 18.360s ok cmd/doc 0.393s ok cmd/fix 0.192s panic: test timed out after 3m0s goroutine 489 [running]: panic(0x120552480, 0xc4203087f0) /home/loongson/workspace/go/src/runtime/panic.go:500 +0x4c4 testing.startAlarm.func1() /home/loongson/workspace/go/src/testing/testing.go:918 +0x168 created by time.goFunc /home/loongson/workspace/go/src/time/sleep.go:132 +0x5c … FAIL cmd/go 208.996s ok cmd/gofmt 0.270s ok cmd/internal/goobj 0.064s ok cmd/internal/obj 0.032s ok cmd/internal/obj/x86 0.067s ok cmd/internal/pprof/profile 0.048s ok cmd/link 0.077s ok cmd/nm 9.304s |
測試專案cmd/go沒有通過測試。這是為什麼呢?筆者起初懷疑編譯生成的Go 1.6可能有問題,反覆檢查了編譯引數的設定,但錯誤依舊。後來,考慮到官方既然已經宣佈Go 1.6直接支援MIPS,編譯出錯的概率應極小,更何況前面那麼多的測試專案都能正確執行。於是將思路從對編譯引數的檢查轉向對測試引數的排查。顯然,錯誤由測試超時導致,而預設的超時閾值僅為3分鐘。對於龍芯和ARM等低主頻的處理器,cmd/go測試項的執行時間可能會超過3分鐘。因此,在龍芯平臺上有可能需要適當增大測試超時的閾值。後來,經過一系列分析和排查,終於找到了環境變數GO_TEST_TIMEOUT_SCALE,用於對測試超時的閾值進行倍增。例如,若設定GO_TEST_TIMEOUT_SCALE = 2,則測試超時的閾值擴大為原來的兩倍,即由3分鐘增大到6分鐘。
6. 重新編譯
根據具體平臺的需要在env.sh中增加對環境變數GO_TEST_TIMEOUT_SCALE的設定,例如以下為適用於龍芯平臺的env.sh。
#!/bin/bash export GOROOT_BOOTSTRAP=/home/loongson/workspace/go-linux-mips64le-bootstrap export GOROOT=/home/loongson/workspace/go # Added for Loongson export GO_TEST_TIMEOUT_SCALE=2 |
上述修改完成後,重新執行env.sh和all.bash這兩個指令碼。
$ cd ~/workspace/go $ source env.sh $ cd src $ ./all.bash |
待指令碼執行結束後,如果觀察到如下輸出資訊,則說明龍芯平臺上Go 1.6的編譯和測試順利完成。整個過程約半小時。
ALL TESTS PASSED --- Installed Go for linux/mips64le in /home/loongson/workspace/go Installed commands in /home/loongson/workspace/go/bin *** You need to add /home/loongson/workspace/go/bin to your PATH. |
7. 安裝編譯生成的Go 1.6。
在~/.bashrc的末尾新增如下語句
export GOROOT=/home/loongson/workspace/go export PATH=$PATH: $GOROOT/bin |
然後執行
$ source ~/.bashrc |
三、龍芯上Go語言對全世界的問候
激動人心的時刻終於到來了!我們先執行一下Go命令,列印一下版本資訊吧:
$ go version go version go1.6.2 linux/mips64le |
接下來,我們來測試一下Go的“Hello World”!開啟任何一款文字編輯器,您可以使用Linux經典的vim,也可以使用更適合大眾的gedit,編寫hello.go檔案,僅需幾行程式碼:
package main import "fmt" func main() { fmt.Printf("Hello World!\n") } |
首先編譯原始碼hello.go。Go和C/C++語言一樣,屬於靜態編譯型語言。Go的源程式必須經過編譯後才能執行。
$ go build hello.go |
上述命令會生成名為hello的可執行檔案。執行hello
$ ./hello Hello World! |
親自感受了Go語言在龍芯上的第一個HelloWorld,真是太令人興奮了!
上述編譯和執行的過程也可以使用go run命令一次性完成,例如
$ go run hello.go Hello World! |
四、繼續把玩 Go!Go!Go!
看到這裡,有讀者不禁會問:除了執行簡單的HelloWorld,龍芯平臺上的Go還能幹什麼?Go語言具有方便移植的特性。所有利用Go語言編寫的應用程式,經過相應平臺的Go語言編譯器編譯後,都能夠在該平臺上執行。所以Go語言環境在龍芯平臺上的成功構建意味著龍芯擁有了Go的全套軟體生態。之前在X86或ARM等平臺上搭建的基於Go語言的應用系統,現在都能夠以較低的代價迅速遷移到龍芯平臺上來。
眼下基於Go的開源專案非常多,筆者沒有時間一一搭建。筆者生性好玩,故專門挑選了幾個較為有意思專案進行試驗。感興趣的朋友可以嘗試更多的專案。需要特別注意的是,在測試開源專案時,還需要額外 設定GOPATH環境變數。這是因為許多開源專案引用了Go語言的第三方庫,需要從GOPATH環境變數指向的路徑中載入第三方庫或者將所引用的第三方庫下載到該路徑中。例如,筆者的設定如下:
$ export GOPATH=/home/loongson/workspace/3rdpkg |
為了便於日後Go語言程式的開發,建議將上述環境變數也加入到~/.bashrc檔案中。
1. 碰撞反彈遊戲(https://github.com/kurehajime/pong-command)
遊戲時,輸入任意一個字串(如go1.6.2),該字串會沿直線運動,遇到上下邊界或左右圍欄則鏡面反彈。左側圍欄由電腦自動控制,右側圍欄由玩家操作。遊戲的目標是控制右側圍欄在垂直方向的位置,使得字串不斷被碰撞反彈。
龍芯平臺上的碰撞反彈遊戲
1. 漢語拼音轉換工具(https://github.com/mozillazg/go-pinyin)
將任意漢字轉換成對應的漢語拼音。例如,輸入“龍芯俱樂部”的執行情況如下:
龍芯平臺上的漢語拼音轉換工具
1. 翻譯助手Utran(https://github.com/zengsai/utran)
可以將英文翻譯成漢語。例如,輸入“This is go1.6.2 running on Loongson.”的執行情況如下:
龍芯平臺上的翻譯助手Utran
1.排序演算法視覺化(https://github.com/SimonWaldherr/GolangSortingVisualization)
可將常見的冒泡、選擇、插入和快排等排序演算法的排序過程視覺化。
一、遇到問題怎麼辦?
以上是筆者在龍芯平臺上從原始碼構建Go語言環境的記錄。讀者按照這些操作步驟也應該能快速構建好Go語言開發環境。如果遇到問題自己不能解決,龍芯社群提供了官方的Bug服務網站(http://bugs.loongnix.org/login_page.php),您可以把遇到的問題提交上去,龍芯團隊的人會及時為您解決。
龍芯官方的Bug提交平臺