龙芯Go!Go!Go!——龙芯平台上构建Go语言环境指南


一、初识Go语言
        Go语言是Google公司于2009年正式推出的一款开源的编程语言,是由Robert Griesemer、Ken Thompson和Rob Pike等世界顶尖计算科学家精心打造的系统编程语言。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语言环境非常简单。
第一阶段:在X86平台上交叉编译出面向MIPS平台的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),该字符串会沿直线运动,遇到上下边界或左右围栏则镜面反弹。左侧围栏由电脑自动控制,右侧围栏由玩家操作。游戏的目标是控制右侧围栏在垂直方向的位置,使得字符串不断被碰撞反弹。
龙芯平台上的碰撞反弹游戏.png

龙芯平台上的碰撞反弹游戏
  1. 汉语拼音转换工具(https://github.com/mozillazg/go-pinyin)
      将任意汉字转换成对应的汉语拼音。例如,输入“龙芯俱乐部”的执行情况如下:
龙芯平台上的汉语拼音转换工具.png

      龙芯平台上的汉语拼音转换工具
  1. 翻译助手Utran(https://github.com/zengsai/utran)
      可以将英文翻译成汉语。例如,输入“This is go1.6.2 running on Loongson.”的执行情况如下:
龙芯平台上的翻译助手Utran.png

      龙芯平台上的翻译助手Utran
  1.排序算法可视化(https://github.com/SimonWaldherr/GolangSortingVisualization)
      可将常见的冒泡、选择、插入和快排等排序算法的排序过程可视化。
排序过程可视化.png

一、遇到问题怎么办?
        以上是笔者在龙芯平台上从源代码构建Go语言环境的记录。读者按照这些操作步骤也应该能快速构建好Go语言开发环境。如果遇到问题自己不能解决,龙芯社区提供了官方的Bug服务网站(http://bugs.loongnix.org/login_page.php),您可以把遇到的问题提交上去,龙芯团队的人会及时为您解决。
龙芯官方的Bug提交平台
 

0 个评论

要回复文章请先登录注册