一、初识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的环境必须分成两个阶段进行:
- 在X86平台上交叉编译出面向MIPS平台的Go语言自举编译工具链;
- 在龙芯平台上利用1)中的Go自举编译器构建Go 1.6开发环境。
下面笔者逐步向大家展示Go 1.6环境在龙芯平台上的构建过程。等大家走完整个过程就会发现,在龙芯上从源代码安装Go语言环境非常简单。
第一阶段:在X86平台上交叉编译出面向MIPS平台的Go语言自举编译工具链。
随便找一台装有64位Linux操作系统的X86电脑,逐步执行以下命令。
- 下载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
- 配置交叉编译的自举编译工具链
$ export GOROOT_BOOTSTRAP=/opt/go1.4.2
- 下载Go 1.6的源代码
$ cd ~/workspace/golang/
$ git clone https://github.com/golang/go.git
- 切换到Go 1.6的发行版
$ cd go
$ git checkout release-branch.go1.6
- 交叉编译 这一步通过执行脚本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开发环境。
- 解压交叉编译生成的面向MIPS平台的自举编译工具链
$ tar xvjf go-linux-mips64le-bootstrap.tbz -C ~/workspace
- 简单检验自举编译工具链是否可用
$ 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
- 下载Go 1.6的源代码并切换到Go 1.6的发行版。
$ cd ~/workspace
$ git clone https://github.com/golang/go.git
$ cd go
$ git checkout release-branch.go1.6
- 编译配置 在当前目录创建名为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
- 首次编译
$ 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分钟。
- 重新编译 根据具体平台的需要在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.
- 安装编译生成的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文件中。
碰撞反弹游戏 (https://github.com/kurehajime/pong-command)
游戏时,输入任意一个字符串(如go1.6.2),该字符串会沿直线运动,遇到上下边界或左右围栏则镜面反弹。左侧围栏由电脑自动控制,右侧围栏由玩家操作。游戏的目标是控制右侧围栏在垂直方向的位置,使得字符串不断被碰撞反弹。
龙芯平台上的碰撞反弹游戏
汉语拼音转换工具 (https://github.com/mozillazg/go-pinyin)
将任意汉字转换成对应的汉语拼音。例如,输入“龙芯俱乐部”的执行情况如下:
龙芯平台上的汉语拼音转换工具
翻译助手Utran (https://github.com/zengsai/utran)
可以将英文翻译成汉语。例如,输入“This is go1.6.2 running on Loongson.”的执行情况如下:
龙芯平台上的翻译助手Utran
排序算法可视化 (https://github.com/SimonWaldherr/GolangSortingVisualization)
可将常见的冒泡、选择、插入和快排等排序算法的排序过程可视化。
排序过程可视化
六、遇到问题怎么办?
以上是笔者在龙芯平台上从源代码构建Go语言环境的记录。读者按照这些操作步骤也应该能快速构建好Go语言开发环境。如果遇到问题自己不能解决,龙芯社区提供了官方的Bug服务网站(http://bugs.loongnix.org/login_page.php) ,您可以把遇到的问题提交上去,龙芯团队的人会及时为您解决。
文章来源于龙芯开源社区
龙芯技术社区
有疑问加站长微信联系(非本文作者)