Logo address

Golang

2022/01/27

Installation to Plan9

2022/01/27

Binary Installation

Plan9 用の Go のコードが
http://9legacy.org/download.html
にある。これは 9front でもそのまま動くはずである。

僕の場合には環境変数

GOLANG=$home/src/golang
を設定し、ここに Go の配布版をおくことにしている。

仮に Go 1.16.13 on plan9/amd64 をインストールするとすれば、ダウンロードしたファイルを $GOLANG にコピーして展開するとディレクトリ

$GOLANG/go-plan9-amd64-bootstrap
が生成される。説明を簡単にするために、これを $GOLANG/bootstrap とする。

9legacy.org の配布ファイルは Linux でクロスコンパイルした痕跡が残っている。すなわち

$GOLANG/bootstrap/bin
に実行ファイル gogofmt が含まれているが、これは Linux のものである。Plan9 用のものは
$GOLANG/bootstrap/bin/plan9_amd64
に含まれている。このままでは問題が発生するので
cp $GOLANG/bootstrap/bin/plan9_amd64/* $GOLANG/bootstrap/bin
を実行しておく必要がある。

このあと $GOLANG/bootstrap を "$GOLANG/go" と名前を変更し、環境変数 $GOROOT

GOROOT=$GOLANG/go
として
path=($path $GOROOT/bin)
とすれば完了。

ソースからコンパイル

準備

Go のコンパイラは、コンパイルの後に生成されたコードのテストを行う。IPv6 のテストも行うので IPv6 を可能にしておく必要がある。この件に関する解説は
http://p9.local/admin/server.html
に書いておいた。
さらに、このときに loop back アドレスを利用する。従って
ip/ipconfig -P loopback /dev/null 127.0.0.1
ip/ipconfig -P loopback /dev/null ::1
を実行して loop back アドレスを作っておく必要がある。

なお、現在の loop back アドレスの設定状態は

cat /net/ipifc/1/status
で判る。

ソースのダウンロードとコンパイル

Plan9 用の Go が既に動いていれば、それを使ってソースからコンパイルできる。ソースコードは直接 Go の公式ページ[1]からダウンロードする。例えばそれを go1.17.3.tar.gz とせよ。このファイルは展開するとディレクトリ go が生成されるように作られている。ところが$GOLANG/go が既に存在するので、古い方は $GOLANG/bootstrap とでも名前を変えておく必要がある。すなわち次のように行う:

cd $GOLANG
mv go bootstrap
tar -xf go1.17.6.src.tar	# produces go
GOROOT_BOOTSTRAP=$GOLANG/bootstrap
cd go/src
all.rc
次のようなメッセージが表示されるはずである:
Building Go cmd/dist using /usr/arisawa/src/golang/bootstrap
Building Go toolchain1 using /usr/arisawa/src/golang/bootstrap.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for plan9/amd64.

##### Testing packages.
ok  	archive/tar	0.090s
ok  	archive/zip	0.295s
...

メッセージの詳細を示しておく: 詳細

「詳細」を見れば判るが、1箇所(go test proxy)でテストに失敗している。原因は(今の所)不明。

問題点

all.rc は内部で make.rc
Golang のアップデートにおける "Testing packages" は結構時間がかかる。
ここに書いた方法でやると、その間 Go を使えないことになる。Go を使ってサービスを行っている場合には、このことは問題なる。

Go のクロスコンパイラ

Go はクロスコンパイラを持っている。しかも
をサポートしている[1]。

ページ[1]では現在ではバイナリコードを含む配布をサポートしているのは、Windows、MacOS、FreeBSD および Linux のみである。しかし優秀なクロスコンパイラがあるので、上記 OS のいずれかを持っていれば、Plan9(9front を含む)でも最新の Go の版を直ちに使える。

僕の環境では Linux に(少し古い)Go のバイナリ版が既にインストールされていた。この Go のクロスコンパイラを利用して Go の最新版(Go1.17.6)を Plan9 にインストールする手順を解説する。(文献[3]を参考にした)

  1. Go の公式サイト[1]から go1.17.6.src.tar.gz を手に入れる
  2. これをどこかに置く。説明を簡単にするために、これを $GOLANG とする。僕の場合は $GOLANG$HOME/src/golang にしている。(注意: 公式サイトの推奨インストール先は /usr/local/go である)
  3. これを展開する。するとディレクトリ $GOLANG/go が作られる。(従って既に $GOLANG/go があれば名称を変更しておく必要がある)
ここでは Plan9 の CPU が amd64 と想定する。
cd $GOLANG/go/src
GOOS=plan9 GOARCH=amd64 make.bash
すると、次のメッセージを出して終了する:
GOOS=plan9 GOARCH=amd64 make.bash
Building Go cmd/dist using /home/arisawa/src/golang/go. (go1.17.6 linux/amd64)
Building Go toolchain1 using /home/arisawa/src/golang/go.
GOOS=plan9 GOARCH=amd64 make.bash
Building Go cmd/dist using /home/arisawa/src/golang/go. (go1.17.6 linux/amd64)
Building Go toolchain1 using /home/arisawa/src/golang/go.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for host, linux/amd64.
Building packages and commands for target, plan9/amd64.
---
Installed Go for plan9/amd64 in /home/arisawa/src/golang/go1.17.6
Installed commands in /home/arisawa/src/golang/go1.17.6/bin

$GOROOT$GOLANG/go としよう。新たに生成されたコードは

に見出される。
Go のクロスコンパイラは Plan9/amd64 のコードの他に、クロスコンパイラの実行環境であるLinux/amd64 のコードも生成している。特に次の点に注意する:
従って、Linux 側で
GOROOT=$GOLANG/go
PATH=$PATH:$GOROOT/bin
に設定されていれば、Linux の Go もアップデートされたことになる。

注意: Go の実行コードの置き場所は1箇所にまとめた方が混乱が少ない。Linux の配布版は /usr/bin にコードを作るが、そこに古いコードが残っている可能性があるので注意。(僕は削除した)

なお、生成された gogofmt は strip されていないので膨れている。Linux の場合 strip すれば 2/3 ほどに小さくなる。(Plan9 のコードは(Plan9 側で strip しても)殆ど小さくならない)

最後に、ディレクトリ $GOLANG/go 以下を Plan9 側に移す。生成されたコードのテストは Plan9 側で行う必要がある。

あとは Plan9 の環境変数

GOROOT=$home/src/golang/go
path=($path $GOROOT/bin)
をどこかで設定しておしまい。

Plan9 と Golang

Go の主な開発チームは Plan9 の開発者たちである。中心になっていた Rob Pike は 2002 年に Bell-labs から Google に移籍している[6]。この頃は Bell-lab がいろいろ問題を抱えていた。親会社の経営不振を受けて、短期的な利益を追求する経営陣の圧力が Hendrik Schön の事件を誘発している。また短期的な利益を生み出さないシステムソフトウェアの開発者たちには辛らかったに違いない。この頃(2000)の Rob の心情が文献[7]に綴られている。Rob は Plan9 をフリーソースにすべく経営陣と交渉を重ね、交渉に成功した後に、仲間たちと一緒に Google に移籍した。そうして生まれたのが Go である。

僕が Go を試したのは Go の初版がリリースされた年(2012)である[2]。従って今から 10 年も前になる。この頃に書いた僕の記事が[8]と[9]にある。しかしそれ以降は Go を使っていない。なぜか? Go が生成したコードが C で生成したコードに比べて数十倍から百倍も大きなサイズになるからである。この問題に関して Plan9 のメーリングリストに不満が寄せられていた。Rob は、アセンブラから C に変わったときも同じように言われたのだ... と返事をしていた。コードサイズの問題はハードウェア性能の進歩が解決するだろうと Rob は見通していたに違いない。

多様なシステムで共通の言語が利用できることは良いことである。しかし肝心の本家と分家の公式リリースには Go が含まれていない。コードサイズの問題も大きいが、(今の所)基本的に困っていないからではないかと思われる。Plan9 には優秀なスクリプト言語 rc が存在し、C でパーツを作り、rc で組み立てるのが Plan9er の基本的なプログラミングスタイルである1。従って C で書くプログラムは大きくはならない。単機能であり、他の OS のようにオプションの山にはならないのである。


注1. 9front の rc-httpd はそうした極端な例であろう。この傾向は分家の方が強い

参考文献

[1] Downloads
https://go.dev/dl/

[2] Release History
https://go.dev/doc/devel/release

[3] Download and install
https://go.dev/doc/install

[4] Installing Go from source
https://go.dev/doc/install/source

[5] Installation - 9legacy
http://9legacy.org/download.html

[6] Rob Pike
http://herpolhode.com/rob/

[7] Systems Software Research is Irrelevant
http://herpolhode.com/rob/utah2000.pdf (2000)

[8] 初めての Go lang
http://ar.nyx.link/blog/golang/ (2012)

[9] Speed comparison: CPython, PyPy, Lua, LuaJIT, C, Go
http://ar.nyx.link/blog/speed/ (2012)

実行環境

2020/01/27

Go が利用する環境変数は

go env
で見ることができる。個々の処理に関してそれらの全てが必要な訳ではない。必ず必要な環境変数は GOROOT である。

GOROOT

Go のソースコード xxx.go を(お試しに)実行するには
go run xxx.go arg1 arg2 ...	# (1)
が手軽である。arg1 arg2 ...xxx.go に与える引数であるが、必要がないなら書かない。また arg1 に Go のソースコードを与えた場合には別の意味になる。

(1)による実行コードは /tmp に生成され、実行後に自動的に消去される。消去されたくないなら

go build xxx.go			# (2)
とする。実行コード xxx は(2)を実行したディレクトリに生成される。従って
xxx arg1 arg2 ...		# (3)
で実行される。

実行コードをコマンドとして活用したい場合には、実行コードの置き場所を決めておく必要があろう。この問題は GOPATH で扱われる。

GOPATH

Go の配布版の置き場所は $GOROOT である。他方、ユーザーが作成した、あるいは非公式の Go のソースプロクラムの置き場所は $GOROOT と区別したほうが良い。$GOPATH/src はそれらの(推奨される)置き場所である。

go env GOPATH

GOPATH の値は
go env GOPATH
で得られる。環境変数 GOPATH が設定されている場合には、この結果は環境変数 GOPATH に一致している。設定されていない場合には、$HOME/go となっている。従って
GOPATH=`{go env GOPATH}
としてよい。以下では環境変数 $GOPATH が設定されているとして説明する。

go install

$GOPATH/bin は、Go ユーザーによってコンパイルされた実行コードの、推奨される置き場所である。

go install xxx.go
によって $GOPATH/binxxx が生成されているはずである。これは
go build xxx.go
で生成される xxx である。

$GOPATH/bin に置かれている実行コードがコマンドとして利用できるようにするには、新しい path

path=($path $GOPATH/bin)
として設定しておく必要がある。

GOPATH についての、詳しい解説は

go help gopath
を見よ。