[インデックス 10875] ファイルの概要
このコミットは、Go言語のランタイムパッケージにおける自動生成ファイルの管理方法を改善することを目的としています。具体的には、以前の試み(CL 5493063)が失敗に終わったことを踏まえ、Makefile
の代わりにシェルスクリプト(autogen.sh
)を使用して、OSやアーキテクチャに依存するランタイムの定義ファイルやアセンブリヘッダーファイルを生成するように変更しています。これにより、ビルドプロセスの堅牢性と保守性が向上しています。
コミット
commit 55889409f8d44fab8f7715ec2d66286b857e25e7
Author: Russ Cox <rsc@golang.org>
Date: Mon Dec 19 15:51:13 2011 -0500
runtime: separate out auto-generated files, take 2
This is like the ill-fated CL 5493063 except that
I have written a shell script (autogen.sh) instead of
thinking I could possibly write a correct Makefile.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5496075
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/55889409f8d44fab8f7715ec2d66286b857e25e7
元コミット内容
runtime: separate out auto-generated files, take 2
このコミットは、自動生成ファイルを分離する2回目の試みです。以前の失敗したCL 5493063とは異なり、今回は正確なMakefileを書くことが不可能だと考え、代わりにシェルスクリプト(autogen.sh)を作成しました。
変更の背景
Go言語のランタイムは、様々なOS(GOOS
)とアーキテクチャ(GOARCH
)の組み合わせに対応するために、多くのプラットフォーム固有のコードを含んでいます。これらのコードの一部は、ビルド時に自動生成されるファイルに依存しています。以前は、これらの自動生成ファイルの管理がMakefile
によって行われていましたが、Makefile
の複雑さやプラットフォーム間の差異への対応の難しさから、ビルドプロセスの堅牢性に課題がありました。
コミットメッセージにある「ill-fated CL 5493063」は、おそらく以前の自動生成ファイル分離の試みがうまくいかなかったことを示唆しています。Makefile
は強力なツールですが、特にクロスプラットフォーム対応や複雑な依存関係の管理においては、その記述が非常に難しく、エラーが発生しやすいという問題があります。
このコミットの背景には、このようなMakefile
の限界を認識し、よりシンプルで堅牢なシェルスクリプト(autogen.sh
)に自動生成処理を移行することで、ビルドプロセスの信頼性を向上させたいという意図があります。シェルスクリプトは、Makefile
に比べて記述が直接的であり、特定のタスクの自動化に適しています。
前提知識の解説
Go言語のビルドプロセスとクロスコンパイル
Go言語は、その強力なクロスコンパイル機能で知られています。これは、あるOS/アーキテクチャ上で、別のOS/アーキテクチャ向けのバイナリを生成できる能力を指します。この機能は、GOOS
(ターゲットOS)とGOARCH
(ターゲットアーキテクチャ)という環境変数によって制御されます。
Goのビルドシステムは、これらの環境変数に基づいて、適切なソースファイルを選択し、コンパイルします。例えば、runtime
パッケージには、sys_linux_amd64.s
やdefs_windows.go
のように、特定のOSやアーキテクチャに特化したファイルが存在します。
Makefile
とシェルスクリプト
Makefile
:make
ユーティリティが使用するビルド自動化ツールです。依存関係を定義し、それらの依存関係が変更された場合にのみ特定のコマンドを実行することで、効率的なビルドを可能にします。しかし、複雑なロジックや条件分岐、特にクロスプラットフォーム対応が必要な場合には、記述が複雑になりがちです。- シェルスクリプト:
bash
などのシェルで実行されるスクリプトです。一連のコマンドを順次実行する形式で、特定のタスクの自動化に非常に適しています。Makefile
のような依存関係の自動解決機能はありませんが、そのシンプルさから、特定のビルドステップやファイル生成処理の自動化によく用いられます。
Goランタイムパッケージ
Goのruntime
パッケージは、Goプログラムの実行を支える低レベルの機能を提供します。これには、ガベージコレクション、スケジューラ、メモリ管理、システムコールインターフェースなどが含まれます。runtime
パッケージのコードは、Go言語だけでなく、C言語やアセンブリ言語で書かれた部分も多く、OSやアーキテクチャに深く依存しています。
自動生成ファイル
ソフトウェア開発において、特定の情報(バージョン情報、OS/アーキテクチャ固有の定数、構造体のオフセットなど)は、手動で記述するのではなく、スクリプトによって自動的に生成されることがあります。これにより、手作業によるエラーを防ぎ、常に最新かつ正確な情報がコードに反映されるようになります。Goのランタイムでは、ビルド時にこれらの情報がC言語のヘッダーファイルやGo言語のソースファイルとして生成され、他のソースファイルから利用されます。
技術的詳細
このコミットの主要な変更点は、Goランタイムの自動生成ファイルの生成ロジックをMakefile
からautogen.sh
という新しいシェルスクリプトに移行したことです。
autogen.sh
の導入
src/pkg/runtime/autogen.sh
が新規に作成されました。このスクリプトは、GOOS
とGOARCH
の組み合わせごとに、以下のファイルを生成します。
zgoarch_*.go
: 各アーキテクチャ(386
,amd64
,arm
)に対応するGoの定数ファイル。theGoarch
という定数にアーキテクチャ名が設定されます。zgoos_*.go
: 各OS(darwin
,freebsd
,linux
,netbsd
,openbsd
,plan9
,windows
)に対応するGoの定数ファイル。theGoos
という定数にOS名が設定されます。zruntime_defs_*.go
:mkgodefs.sh
スクリプトを使用して、C言語の構造体定義をGo言語の構造体定義に変換したファイル。これにより、Goのコードからランタイムの内部構造にアクセスできるようになります。ファイル名はzruntime_defs_GOOS_GOARCH.go
の形式になります。zasm_*.h
:mkasmh.sh
スクリプトを使用して、アセンブリコードからランタイムの構造体オフセットなどの情報を抽出したCヘッダーファイル。アセンブリコードがGoランタイムの内部構造にアクセスする際に利用されます。ファイル名はzasm_GOOS_GOARCH.h
の形式になります。zversion.go
:mkversion
ツールを使用して、Goのバージョン情報をGoの定数として定義したファイル。
これらの生成されたファイルは、ファイル名の先頭にz
が付けられています。これは、Goのビルドシステムにおいて、自動生成されたファイルであることを示す慣例的なプレフィックスです。また、これらのファイルには「AUTO-GENERATED by autogen.sh; DO NOT EDIT
」というコメントが追加され、手動での編集を避けるように促しています。
Makefile
の変更
src/pkg/runtime/Makefile
からは、自動生成ファイルに関する複雑なルールが削除されました。代わりに、autogen.sh
がこれらのファイルを生成する責任を負います。
GOFILES
リストから、runtime_defs.go
,version.go
,version_*.go
といった自動生成されるファイルが削除され、代わりにzgoarch_$(GOARCH).go
,zgoos_$(GOOS).go
,zruntime_defs_$(GOOS)_$(GOARCH).go
,zversion.go
といった新しい自動生成ファイルが追加されました。CLEANFILES
からも、古い自動生成ファイルが削除され、新しい自動生成ファイル(z*
で始まるファイル)がclean-local
ターゲットで削除されるようになりました。asm_$(GOARCH).h
などのヘッダーファイルの生成ルールも削除され、autogen.sh
がzasm_GOOS_GOARCH.h
を生成するように変更されました。src/make.bash
では、pkg
のビルドの前にautogen.sh
を実行するステップが追加されました。これにより、ランタイムパッケージのビルドに必要な自動生成ファイルが事前に準備されるようになります。
アセンブリファイルの変更
src/pkg/runtime/asm_*.s
ファイル(例: asm_386.s
, asm_amd64.s
, asm_arm.s
)では、インクルードするヘッダーファイルがasm_$(GOARCH).h
からzasm_GOOS_GOARCH.h
に変更されました。これは、autogen.sh
によって生成される新しいヘッダーファイルを参照するためです。
goc2c.c
とmkversion.c
の変更
これらのC言語のソースファイルには、生成されるファイルの先頭に「// AUTO-GENERATED by autogen.sh; DO NOT EDIT
」というコメントを追加するためのprintf
文が追加されました。
defs_*.go
ファイルの変更
src/pkg/runtime/defs*_*.go
ファイルには、// +build ignore
というビルドタグが追加されました。これは、これらのファイルが直接Goのビルドプロセスに含まれるのではなく、cgo -cdefs
のようなツールによって処理されることを示しています。
コアとなるコードの変更箇所
src/pkg/runtime/autogen.sh
: 新規追加されたシェルスクリプト。自動生成ファイルの生成ロジックをカプセル化。src/pkg/runtime/Makefile
: 自動生成ファイルに関する複雑なルールが削除され、新しい自動生成ファイルが参照されるように変更。src/make.bash
:autogen.sh
の実行ステップが追加され、ビルドプロセスに組み込まれた。src/pkg/runtime/asm_*.s
: インクルードするヘッダーファイルがasm_$(GOARCH).h
からzasm_GOOS_GOARCH.h
に変更。src/pkg/runtime/goc2c.c
,src/pkg/runtime/mkversion.c
: 自動生成コメントの追加。
コアとなるコードの解説
autogen.sh
このスクリプトは、Goランタイムのビルドプロセスにおいて、OSやアーキテクチャに依存する様々なファイルを自動的に生成する中心的な役割を担います。
#!/bin/sh
# Copyright 2011 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# This script generates the various derived files involved in
# building package runtime.
#
# autogen.sh rebuilds everything
# autogen.sh -clean deletes the generated files
# ... (GOARCHES, GOOSES, GOOSARCHES, HELPERS の定義) ...
rm -f $HELPERS z* # 既存のヘルパーと自動生成ファイルを削除
if [ "$1" = "-clean" ]; then
exit 0
fi
set -e # エラーが発生したらスクリプトを終了
if [ "$GOROOT" = "" ]; then
echo "$0"': $GOROOT must be set' >&2
exit 2
fi
# Use goc2c to translate .goc files into arch-specific .c files.
quietgcc -o goc2c -I "$GOROOT/include" goc2c.c "$GOROOT/lib/lib9.a"
for file in *.goc
do
for arch in $GOARCHES
do
base=$(echo $file | sed 's/\.goc$//')
GOARCH=$arch ./goc2c $file >z.tmp
mv -f z.tmp z${base}_$arch.c
done
done
# Version constants.
quietgcc -o mkversion -I "$GOROOT/include" mkversion.c "$GOROOT/lib/lib9.a"
GOROOT="$GOROOT_FINAL" ./mkversion >z.tmp
mv z.tmp zversion.go
for arch in $GOARCHES
do
(
echo '// AUTO-GENERATED by autogen.sh; DO NOT EDIT'
echo
echo 'package runtime'
echo
echo 'const theGoarch = "'$arch'"'
) >zgoarch_$arch.go
done
for os in $GOOSES
do
(
echo '// AUTO-GENERATED by autogen.sh; DO NOT EDIT'
echo
echo 'package runtime'
echo
echo 'const theGoos = "'$os'"'
) >zgoos_$os.go
done
# Definitions of runtime structs, translated from C to Go.
for osarch in $GOOSARCHES
do
./mkgodefs.sh $osarch proc.c iface.c hashmap.c chan.c >z.tmp
mv -f z.tmp zruntime_defs_$osarch.go
done
# Struct field offsets, for use by assembly files.
for osarch in $GOOSARCHES
do
./mkasmh.sh $osarch proc.c defs.h >z.tmp
mv -f z.tmp zasm_$osarch.h
done
rm -f $HELPERS
このスクリプトは、goc2c
、mkversion
、mkgodefs.sh
、mkasmh.sh
といったヘルパースクリプトやツールを呼び出し、それぞれのOS/アーキテクチャの組み合わせに対して必要なファイルを生成します。これにより、ビルドシステムはこれらの自動生成ファイルを直接利用できるようになり、Makefile
の複雑な依存関係管理から解放されます。
Makefile
の変更の意図
src/pkg/runtime/Makefile
から自動生成に関するルールを削除し、src/make.bash
でautogen.sh
を呼び出すように変更したことで、ビルドプロセスの責任分担が明確になりました。Makefile
はコンパイルとリンクのルールに集中し、ファイルの生成はautogen.sh
に任せることで、それぞれのツールの得意分野を活かしています。これにより、ビルドシステムの全体的な理解と保守が容易になります。
アセンブリファイルのヘッダー変更
アセンブリファイルがzasm_GOOS_GOARCH.h
をインクルードするように変更されたのは、autogen.sh
によって生成される新しいヘッダーファイルが、OSとアーキテクチャに特化した構造体オフセットなどの情報を提供するためです。これにより、アセンブリコードは常に正確なランタイムの内部構造にアクセスできるようになります。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/doc/
- Goのビルドコマンド: https://go.dev/cmd/go/
参考にした情報源リンク
- GitHub上のコミットページ: https://github.com/golang/go/commit/55889409f8d44fab8f7715ec2d66286b857e25e7
- Go言語のソースコード(
src/pkg/runtime
ディレクトリ) - Go言語のビルドシステムに関する一般的な知識