Plan 9とGo言語のブログ

主にPlan 9やGo言語の日々気づいたことを書きます。

Plan 9の9k(64bit)カーネルでGoを最初からビルドする

はじめに

  • この記事は趣味の記録みたいなものです
  • 他OSでPlan 9用にクロスコンパイルする方が圧倒的に早いので普通はそれがおすすめです

ブートストラップ可能な下限バージョン

GoはもともとCで実装されていましたが、Go 1.5以降はセルフホストされています。公式ドキュメントのInstalling Go from sourceにビルド可能なバージョンが書かれていますが、現時点までのバージョンをまとめると

バージョン どこまでビルド可能か
C 〜 Go 1.4
Go 1.4 Go 1.5 〜 1.19
Go 1.17 Go 1.20 〜 1.21
Go 1.20 Go 1.22 〜 1.23

これ以降は、ターゲットのマイナーバージョンが

  • 偶数の場合: N-2
  • 奇数の場合: N-3

という制約になります。例えばGo 1.25をビルドしたい場合、マイナーバージョンが奇数なので下限はGo 1.22です。

Plan 9(64bit)の場合

基本的には上記の通りなのですが、Plan 9でビルドする場合は上記の通りにはいかないケースがいくつかあります。なのでインストールした直後のPlan 9で2025年夏時点の最新バージョンに到達する手順をまとめます。

Go 1.4.3

まずはCコンパイラで1.4.3をビルドします。素のPlan 9では証明書の検証がうまくいかないので、別の方法でダウンロードしておいてください。

curl -LO https://go.dev/dl/go1.4.3.src.tar.gz

あとはPlan 9go1.4 をビルドします。

gunzip -c go1.4.3.src.tar.gz | tar x
mv go go1.4
cd go1.4/src
./make.rc

Go 1.9.7

次に、公式にはGo 1.4があれば1.17までビルドできるとなっていますが、Plan 9(64bit)の場合はGo 1.17やGo 1.11まで上げると runtime: garbage collector found invalid heap pointer というエラーで失敗します。なので、一旦Go 1.9を経由する必要があります。これはGo 1.4.3を使ってビルドします。

curl -LO https://go.dev/dl/go1.9.7.src.tar.gz

ビルドの手順はGo 1.4と同じなので省略。

Go 1.11.13

Go 1.9.7を使ってGo 1.11をビルドします。これは飛ばしてGo 1.17まで上げても動くかもしれないけれど試していません。

curl -LO https://go.dev/dl/go1.11.13.src.tar.gz

GOROOT_BOOTSTRAP 環境変数で指示する必要があります。

gunzip -c go1.11.13.src.tar.gz | tar x
mv go go1.11
cd go1.11/src
GOROOT_BOOTSTRAP=$home/go1.9 ./make.rc -v

ここで make.rc-v オプションを与えていますが、これはビルドの状況を詳しく出力するためのオプションです。Go 1.10前後で make.rc の出力が

Building Go cmd/dist using /usr/glenda/go1.9. (go1.9.7 plan9/amd64)
Building Go toolchain1 using /usr/glenda/go1.9.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.

のようにシンプルなスタイルに変わりましたが、Plan 9でのビルドはネットワーク次第で遅くなるので細かい進捗が出力される方が嬉しいのです。とはいえ無くても困ったりはしません。

Go 1.17.13

Go 1.11を使ってビルドします。

curl -LO https://go.dev/dl/go1.17.13.src.tar.gz

ビルド方法は1.11と同じなので省略。

Go 1.21.13

Go 1.17を使ってビルドします。次の1.22をビルドするために必要な最小バージョンは1.20だけど、新しい方がなにかと良いだろうと思って、Go 1.17でビルド可能な中での最も新しいバージョンを選択しました。

curl -LO https://go.dev/dl/go1.21.13.src.tar.gz

ビルド方法は1.11と同じなので省略。

Go 1.22.12

Go 1.21を使ってビルドします。

curl -LO https://go.dev/dl/go1.22.12.src.tar.gz

ビルド方法は1.11と同じなので省略。

Go 1.24.5

この記事を書いている時点で最新バージョンは1.24.5なのでGo 1.22を使ってビルドしたいのですが、このバージョンは64bit Plan 9環境では問題があるらしく、以下のエラーで失敗します。

Building Go toolchain3 using go_bootstrap and Go toolchain2.
M structure uses sizeclass 1792/0x700 bytes; incompatible with mutex flag mask 0x3ff
fatal error: runtime.m memory alignment too small for spinbit mutex
runtime: panic before malloc heap initialized

runtime stack:
runtime.throw({0xc675e7?, 0x0?})
        runtime/panic.go:1101 +0x49 fp=0x7fffffffee78 sp=0x7fffffffee48 pc=0x273529
runtime.lockVerifyMSize()
        runtime/lock_spinbit.go:97 +0xc5 fp=0x7fffffffeea0 sp=0x7fffffffee78 pc=0x2175c5
runtime.schedinit()
        runtime/proc.go:818 +0x34 fp=0x7fffffffef00 sp=0x7fffffffeea0 pc=0x244c74
runtime.rt0_go()
        runtime/asm_amd64.s:349 +0x128 fp=0x7fffffffef08 sp=0x7fffffffef00 pc=0x278a28
go: error obtaining buildID for go tool compile: exit status: 'compile 17771: 2'
go tool dist: FAILED: /usr/glenda/go/pkg/tool/plan9_amd64/go_bootstrap install -v -a cmd/asm cmd/cgo cmd/compile cmd/link cmd/preprofile: exit status: 'go_bootstrap 17767: 1'

この問題はruntime: panic before malloc heap initialized on plan9/amd64で報告されていて、新しいバージョンでは解決しているようなので1.25相当まで上げましょう。

Go 1.25rc2相当

上記の通り1.24がビルドできないので、GitHubから最新のソースコードを拾ってきてこれで代用します。もう少し経てば正式版が出ると思うので、それを使ってもいいかもしれません。

unzip go-master.zip
mv go-master go
cd go/src

ここで VERSION ファイルを作るのですが、ソースをzipでダウンロードした場合は .git がなくて VERSION の作成が上手く動きません。なので手で以下のような内容のファイルを作成します。

go1.25rc2
time 2025-07-29T12:08:00Z

これであとは make.rc するだけです。

GOROOT_BOOTSTRAP=$home/go1.22 ./make.rc -v