Go
Solaris
golang

Golang って Solaris でビルドできるのか調べてみた(気にすんなよ。くよくよすんなよ)

More than 3 years have passed since last update.

Golang って Solaris ではどうなのか調べてみたの続きになります。

ブートストラップに利用する Go 1.4.2 を Solaris 11.3 でビルドし、Go 1.5.3 を手に入れることがゴールになります。

(Solaris x86 環境が対象です)


作業ディレクトリ

$HOME/go ディレクトリを作業などもろもろ利用するディレクトリとします。

$ mkdir $HOME/go

$ cd $HOME/go


ビルドの準備

必要なパッケージをインストール。

# pkg install developer/versioning/git developer/gnu-binutils \

developer/build/gnu-make developer/gcc-48


ソースコードの入手

Go 1.4.3 と Go 1.5.2 を下記から入手し、$HOME/go ディレクトリに配置。

https://golang.org/dl/

$ wget https://storage.googleapis.com/golang/go1.4.3.src.tar.gz

$ wget https://storage.googleapis.com/golang/go1.5.2.src.tar.gz


まずは Go 1.4.3 のビルド

アーカイブを展開し、go1.4.3 という名前に変更。

$ gtar xvzf go1.4.3.src.tar.gz

$ mv go go1.4.3
$ cd go1.4.3/src
$ PATH=/usr/gnu/bin:$PATH
$ export PATH

make.bash を実行

$ ./make.bash

# Building C bootstrap tool.
cmd/dist

# Building compilers and Go bootstrap tool for host, solaris/amd64.
lib9
libbio
liblink
:
testing/iotest
testing/quick
text/scanner

---
Installed Go for solaris/amd64 in /export/home/kazus/go/go1.4.3
Installed commands in /export/home/kazus/go/go1.4.3/bin

以上で、Go 1.4.3 のビルドは完了。

$ $HOME/go/go1.4.3/bin/go version

go version go1.4.3 solaris/amd64

このディレクトリをそのまま利用します。


Go 1.5.2 のビルド

Go 1.5 のビルドには、Go 1.4.3 が必要になるので、展開した Go 1.4.3 のディレクトリを $GOROOT_BOOTSTRAP に設定します。

$ GOROOT_BOOTSTRAP=$HOME/go/go1.4.3; export GOROOT_BOOTSTRAP

アーカイブを展開し、go1.5.2 という名前に変更。

$ gtar xvzf go1.5.2.src.tar.gz

$ mv go go1.5.2

go1.5.2/src に移動して make.bash を実行

$ cd go1.5.2/src

$ ./make.bash

##### Building Go bootstrap tool.
cmd/dist

##### Building Go toolchain using /export/home/kazus/go/go1.4.3.
bootstrap/internal/obj
bootstrap/asm/internal/flags
:
:
---
Installed Go for solaris/amd64 in /export/home/kazus/go/go1.5.2
Installed commands in /export/home/kazus/go/go1.5.2/bin

以上で、Go 1.5.2 のビルドは完了。

$ $HOME/go/go1.5.2/bin/go version

go version go1.5.2 solaris/amd64


GOPATH と GOROOT

ひとまず、出来上がった go1.5.2 の go コマンドに PATH を通しておきます。

これで、何も考えずに go コマンドを実行できるようになりました。

$ PATH=$HOME/go/go1.5.2/bin:$PATH; export PATH

続いて、ビルドした go コマンドが持っている環境変数を確認してみます。

$ go env

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="solaris"
GOOS="solaris"
GOPATH=""
GORACE=""
GOROOT="/export/home/kazus/go/go1.5.2"
GOTOOLDIR="/export/home/kazus/go/go1.5.2/pkg/tool/solaris_amd64"
GO15VENDOREXPERIMENT=""
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"

$GOROOT が埋め込まれているをことを確認できるので、$GOPATH のみを設定します。

$GOPATH に指定されたディレクトリはワーキングディレクトリとして利用され、$GOPATH/src にパッケージ、pkg にビルドされたライブラリ、bin に実行可能バイナリなどが格納されます。

このあたりは、特にココ!という場所は無いようなのでお好きなようにって感じでしょうか。

自身で作成したパッケージなどの構成にも関わるので、じっくり調べてみるのも良いかと思います。

$ GOPATH=$HOME/go; export GOPATH

もう一度、go env を実行してみると、GOPATH に先ほど設定した $GOPATH の値が入っていることがわかります。

kazus@solaris:~/go$ go env

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="solaris"
GOOS="solaris"
GOPATH="/export/home/kazus/go"
GORACE=""
GOROOT="/export/home/kazus/go/go1.5.2"
GOTOOLDIR="/export/home/kazus/go/go1.5.2/pkg/tool/solaris_amd64"
GO15VENDOREXPERIMENT=""
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"


Hello, World!

How to Write Go Code などを参考に Hello,World! を実行してみます。

ソースはコピペで。

package main

import "fmt"

func main() {
fmt.Printf("Hello, world.\n")
}

go run で実行できます。

(一時的にワーキングディレクトリに実行可能ファイルを作成し、実行後は消去します。)

$ go run hello.go

hello, world

実行可能なバイナリを作成するには、go build を利用します。

$ go build hello.go

$ ls -al
total 2312
drwxr-xr-x 2 kazus staff 4 Jan 11 16:24 .
drwxr-xr-x 14 kazus staff 23 Jan 11 16:21 ..
-rwxr-xr-x 1 kazus staff 2349856 Jan 11 16:24 hello
-rw-r--r-- 1 kazus staff 77 Jan 11 16:22 hello.go

$ ./hello
hello, world

go build 時に -x オプションをつけることで、何が行われているか詳細を知ることができます。

$ go build -x hello.go

WORK=/tmp/go-build595923179
mkdir -p $WORK/command-line-arguments/_obj/
mkdir -p $WORK/command-line-arguments/_obj/exe/
cd /export/home/kazus/go/test
/export/home/kazus/go/go1.5.2/pkg/tool/solaris_amd64/compile -o $WORK/command-line-arguments.a -trimpath $WORK -p main -complete -buildid f68da26c4308377ead5ac41ebd2a70f05db675c6 -D _/export/home/kazus/go/test -I $WORK -pack ./hello.go
cd .
/export/home/kazus/go/go1.5.2/pkg/tool/solaris_amd64/link -o $WORK/command-line-arguments/_obj/exe/a.out -L $WORK -extld=gcc -buildmode=exe -buildid=f68da26c4308377ead5ac41ebd2a70f05db675c6 $WORK/command-line-arguments.a
cp $WORK/command-line-arguments/_obj/exe/a.out hello


まとめ

以上で Go 1.5 の環境を手に入れることができました。

あとは、もう好きにやっちゃってください。

下記は、お時間あればどうぞ。


ポータビリティ問題?

platform 依存の low-level interactions を利用した実装が多く見られるので、ポータビリティが損なわれているんじゃないか問題を Solaris 観点で。

確かに、Terminal 系のプログラムで ioctl 使っているものに遭遇して乗り越えられないもの多数


何かインストールしてみよう

この記事を参考に ccat, pt, peco にチャレンジしてみた

* あるとちょっと便利なコマンドラインツール3つ


pt - The Platinum Searcher:

https://github.com/monochromegane/the_platinum_searcher

Go言語で作られたパターン検索ツール。

pt が依存している Terminal パッケージ が、Solaris に対応していないためインストールできず。

が、FreeBSD や Darwin (OS X) では CGO (Go から C の関数を呼び出すことができる)という仕組みを使ったものも提供されていたため、見よう見まねでごにょごにょしたら Solaris でも動くものが出来上がったので Pull Request してみた。

1.5 のリリースノートに書かれていた The Solaris port now has full support for cgo を覚えていたので、そこからたどってみた。

というわけで、今日から Solaris でも pt 使えます。

$ go get github.com/monochromegane/the_platinum_searcher/...

$ $GOPATH/bin/pt --help


ccat - ccat is the colorizing cat:

https://github.com/jingweno/ccat

syntax highlighting をサポートした cat コマンド

やってみる。

$ go get -u github.com/jingweno/ccat

# github.com/jingweno/ccat
jingweno/ccat/ccat.go:22: undefined: isatty.IsTerminal

ccat パッケージに含まれ、かつ depend している go-isatty パッケージが Solaris をサポートしていないため、undefined: isatty.IsTerminal でエラーとなる。

本家では Solaris をサポートしたパッケージを配布しているので、ccat.go を下記のように書き換える、もう一度、go get -u github.com/jingweno/ccat すればインストールできる。

diff --git a/ccat.go b/ccat.go

index eae8a8e..b4a67b7 100644
--- a/ccat.go
+++ b/ccat.go
@@ -7,7 +7,7 @@ import (
"os"
"syscall"

- "github.com/jingweno/ccat/Godeps/_workspace/src/github.com/mattn/go-isatty"
+ "github.com/mattn/go-isatty"
)

type CCatPrinter interface {

もう一回

$ go get -fix -v -u github.com/jingweno/ccat

github.com/jingweno/ccat (download)
github.com/mattn/go-isatty (download)
Fetching https://golang.org/x/sys/unix?go-get=1
Parsing meta tags from https://golang.org/x/sys/unix?go-get=1 (status code 200)
get "golang.org/x/sys/unix": found meta tag main.metaImport{Prefix:"golang.org/x/sys", VCS:"git", RepoRoot:"https://go.googlesource.com/sys"} at https://golang.org/x/sys/unix?go-get=1
get "golang.org/x/sys/unix": verifying non-authoritative meta tag
Fetching https://golang.org/x/sys?go-get=1
Parsing meta tags from https://golang.org/x/sys?go-get=1 (status code 200)
golang.org/x/sys (download)
github.com/jingweno/ccat

ccat コマンドが $GOPATH/bin に作成されている。

$ ls $GOPATH/bin/ccat

/export/home/kazus/go/bin/ccat*


peco - Simplistic interactive filtering tool

https://github.com/peco/peco

これが、超絶便利そうだったのでインストールしてみたかったが Solaris をサポートしていない termbox への依存が激しくくじけました。

かわりに Python で実装された percol 置いときますね。


boom - HTTP(S) load generator, ApacheBench (ab) replacement, written in Go:

https://github.com/rakyll/boom

$ go get github.com/rakyll/boom

下記のエラーが出力されるので、pb/pb.go に patch を適用します。

# github.com/rakyll/pb

../src/github.com/rakyll/pb/pb.go:168: undefined: terminalWidth

パッチ:

$ git diff

diff --git a/pb_nix.go b/pb_nix.go
index 1f606aa..45bcfb0 100644
--- a/pb_nix.go
+++ b/pb_nix.go
@@ -1,4 +1,4 @@
-// +build linux darwin freebsd
+// +build linux darwin freebsd solaris

package pb

もう、一回。

今度は undefined: syscall.SYS_IOCTL が出ました。

ちょっとこれを CGO 対応させるスキルがありません。

$ go get github.com/rakyll/boom

# github.com/rakyll/pb
./pb_nix.go:26: undefined: syscall.SYS_IOCTL

正しい手法ではないですが、go1.5.2 のソースを修正します。

書き換えたら go 1.5.2 のビルド手順と同じ make.bash を実行してください。

diff -cNr go/src/syscall/zsysnum_solaris_amd64.go go1.5.2/src/syscall/zsysnum_solaris_amd64.go

*** go/src/syscall/zsysnum_solaris_amd64.go Thu Dec 3 09:53:02 2015
--- go1.5.2/src/syscall/zsysnum_solaris_amd64.go Mon Jan 11 23:14:32 2016
***************
*** 8,13 ****
--- 8,14 ----

// TODO(aram): remove these before Go 1.3.
const (
+ SYS_IOCTL = 54
SYS_EXECVE = 59
SYS_FCNTL = 62
)

修正を加えたビルドが完了したら、また go get を実行します。

$ go get github.com/rakyll/boom

これで、$GOROOT/bin に boom バイナリが作成されているはず。

動作しました。

$ $GOPATH/bin/boom -n 10000 -c 100 -m POST http://192.168.100.15:8080

10000 / 10000 Booooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo! 100.00 %

Summary:
Total: 5.1659 secs.
Slowest: 1.2772 secs.
Fastest: 0.0025 secs.
Average: 0.0428 secs.
Requests/sec: 1935.7703
Total Data Received: 12670000 bytes.
Response Size per Request: 1267 bytes.

Status code distribution:
[404] 10000 responses

Response time histogram:
0.003 [1] |
0.130 [9902] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
0.257 [18] |
0.385 [2] |
0.512 [0] |
0.640 [0] |
0.767 [0] |
0.895 [0] |
1.022 [0] |
1.150 [26] |
1.277 [51] |

Latency distribution:
10% in 0.0170 secs.
25% in 0.0232 secs.
50% in 0.0310 secs.
75% in 0.0425 secs.
90% in 0.0543 secs.
95% in 0.0650 secs.
99% in 0.1263 secs.


参考