LoginSignup
5

More than 5 years have passed since last update.

Organization

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

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 ディレクトリに配置。

$ 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

これが、超絶便利そうだったのでインストールしてみたかったが Solaris をサポートしていない termbox への依存が激しくくじけました。
かわりに Python で実装された percol 置いときますね。

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

$ 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.

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
5