[インデックス 11451] ファイルの概要
このコミットは、Go言語プロジェクト内のC言語で書かれたツール(cov
, nm
, prof
, pprof
)のビルドおよびインストールプロセスを再構築するものです。具体的には、新しいMakefileの導入、ツールの名称変更、インストールパスの変更、そしてシステムワイドなインストールスクリプトの更新が含まれます。
コミット
commit 4a9138751abd2dbd2c2dbe86697fdd08718535c7
Author: Rob Pike <r@golang.org>
Date: Sun Jan 29 10:14:36 2012 -0800
cmd/go: c tools not used during compilation
cov, nm, pprof, prof
R=rsc, r, rsc
CC=golang-dev
https://golang.org/cl/5576067
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4a9138751abd2dbd2c2dbe86697fdd08718535c7
元コミット内容
このコミットの元のメッセージは以下の通りです。
cmd/go: c tools not used during compilation
cov, nm, pprof, prof
これは、cov
, nm
, pprof
, prof
といったC言語で書かれたツールが、Goのコンパイルプロセス中に直接使用されないことを示唆しています。この変更は、これらのツールのビルドと配布方法を整理し、Goのビルドシステム全体から独立させることを目的としていると考えられます。
変更の背景
このコミットの背景には、Goプロジェクトにおけるツールの管理と配布の標準化があります。以前は、C言語で書かれたツール(cov
, nm
, prof
など)は、Make.ccmd
という汎用的なMakefileを使用してビルドされ、6cov
、6nm
、6prof
のようなプレフィックス付きの名前でインストールされていました。また、インストール先も $GOBIN
ディレクトリ直下でした。
このコミットは、以下の問題点や改善点を解決しようとしています。
- ビルドプロセスの明確化: C言語で書かれたツールに特化した新しいMakefile (
Make.ctool
) を導入することで、ビルドプロセスをより明確にし、Go言語で書かれたツールとは異なるビルド要件を適切に管理します。 - ツールの命名規則の統一:
6cov
のようなプレフィックスは、Goのバージョンやアーキテクチャを示すものでしたが、Goツールチェインが成熟するにつれて、より汎用的な名前 (cov
,nm
,prof
) が望ましくなりました。これにより、ツールの利用者が混乱することなく、直感的にツールを識別できるようになります。 - インストールパスの整理: Goのツールは通常
$GOROOT/bin
または$GOBIN
にインストールされますが、このコミットではC言語ツールを$GOROOT/bin/go-tool/
という専用のサブディレクトリに配置することで、Goツールチェインの他の部分との分離を明確にし、管理を容易にします。これは、これらのツールがGoコンパイラやリンカとは異なる補助的な役割を持つことを示唆しています。 - システムワイドなインストールの改善:
sudo.bash
スクリプトの更新は、これらのツールをシステム全体にインストールする際のパスと名前の整合性を確保し、古いバイナリの残存を防ぐためのものです。
これらの変更は、Goプロジェクトが成長し、ツールチェインが複雑化する中で、よりクリーンで保守しやすい構造を目指す一環として行われました。
前提知識の解説
このコミットを理解するためには、以下の概念について知っておく必要があります。
- Go言語のビルドシステム: Goプロジェクトは、独自のビルドシステムを使用しており、Makefileがその一部を構成しています。
Make.inc
、Make.ccmd
、そしてこのコミットで導入されるMake.ctool
など、様々なMakefileがGoのソースコードやツールをビルドするために利用されます。 - Makefile:
make
コマンドによって実行されるビルド自動化ツールです。依存関係に基づいてファイルをコンパイル、リンク、インストールする手順を定義します。 $GOROOT
と$GOBIN
:$GOROOT
: Goのインストールディレクトリのルートパスを示す環境変数です。Goの標準ライブラリ、ツール、ドキュメントなどが含まれます。$GOBIN
: Goの実行可能バイナリがインストールされるディレクトリを示す環境変数です。通常は$GOROOT/bin
またはユーザーの$HOME/go/bin
に設定されます。
cov
(Go Coverage Tool): Goのコードカバレッジを測定するためのツールです。テストがコードのどの部分を実行したかを分析し、カバレッジレポートを生成します。nm
(Go Symbol Table Tool): Unix系のnm
コマンドに似たツールで、Goのオブジェクトファイルや実行可能ファイル内のシンボル(関数名、変数名など)をリスト表示します。デバッグやバイナリの解析に役立ちます。prof
/pprof
(Go Profiling Tools): Goアプリケーションのパフォーマンスプロファイリングを行うためのツール群です。CPU使用率、メモリ割り当て、ゴルーチンブロックなどを分析し、パフォーマンスのボトルネックを特定するのに役立ちます。pprof
は、プロファイリングデータを視覚化するためのツールとして広く知られています。HOST_CC
,HOST_LD
,HOST_O
: Goのビルドシステム内で使用される変数で、ホストシステム(Goのビルドが実行される環境)のCコンパイラ、リンカ、オブジェクトファイルの拡張子をそれぞれ指します。これにより、クロスコンパイル環境でも適切にCコードをビルドできます。bison
: Yacc互換のパーサジェネレータです。文法定義ファイルからC言語のソースコードを生成し、構文解析器を作成します。y.tab.h
やy.tab.c
といったファイルが生成されるのは、bison
が使用されていることを示します。gdb
: GNU Debuggerの略で、プログラムの実行を制御し、内部状態を検査するためのデバッグツールです。
技術的詳細
このコミットの技術的詳細は、主にGoのビルドシステムにおけるC言語ツールの取り扱いに関するものです。
-
src/Make.ctool
の導入:- この新しいMakefileは、C言語で書かれたGoツールをビルドするための標準的なルールを定義しています。
TARG
変数に.exe
拡張子を付加することで、Windows環境での実行可能ファイル名を自動的に処理します。$(HOST_LD)
を使用して、$(OFILES)
(オブジェクトファイル) と$(LIB)
(ライブラリ) をリンクし、最終的な実行可能ファイル$(TARG)
を生成します。-L"$(GOROOT)"/lib
は、Goのライブラリディレクトリをリンカの検索パスに追加します。-lmach
,-lbio
,-l9
,-lm
は、特定のシステムライブラリへのリンクを示唆しています。$(OFILES)
が$(HFILES)
に依存することを定義しており、ヘッダーファイルの変更がオブジェクトファイルの再コンパイルをトリガーするようにしています。clean
およびnuke
ターゲットは、ビルド生成物やインストールされたバイナリを削除するための標準的なクリーンアップメカニズムを提供します。特にnuke
は、インストールされたツールを$GOROOT/bin/go-tool/
から削除します。install
ターゲットは、ビルドされたツールを$GOROOT/bin/go-tool/
ディレクトリにコピーします。mkdir -p
を使用して、必要に応じてディレクトリを作成します。y.tab.h
およびy.tab.c
のルールは、bison
を使用してパーサ関連のファイルを生成するプロセスを定義しています。これは、cov
やprof
のようなツールが構文解析を必要とする場合に利用されます。%.$(HOST_O): %.c
ルールは、Cソースファイルをオブジェクトファイルにコンパイルする方法を定義しています。$(PWD)/$*.c
を使用することで、gdb
のようなデバッガがスタックトレースで完全なパスを表示できるようにしています。
-
ツールの名称変更とMakefileの更新:
src/cmd/cov/Makefile
,src/cmd/nm/Makefile
,src/cmd/prof/Makefile
の各ファイルで、TARG
変数の値が6cov
からcov
、6nm
からnm
、6prof
からprof
へと変更されています。これにより、生成されるバイナリの名前が簡潔になります。- これらのMakefileは、
include ../../Make.ccmd
からinclude ../../Make.ctool
へと変更され、新しいCツール専用のビルドシステムを利用するようになりました。 NOINSTALL=1
の削除は、これらのツールがデフォルトでインストールされるようになったことを意味します。- インストールパスが
$(GOBIN)/$(TARG)
から$(GOBIN)/go-tool/$(TARG)
へと変更され、専用のサブディレクトリに配置されるようになりました。 src/cmd/prof/gopprof
がsrc/cmd/prof/pprof
にリネームされました。これは、pprof
ツール自体がGo言語で書かれたスクリプトまたはバイナリであり、その名前を簡潔にするための変更です。
-
src/cmd/go/tool.go
の変更:sort.StringSlice(names).Sort()
がsort.Strings(names)
に変更されています。これは、Go 1.8で導入されたsort.Strings
関数(sort.StringSlice
のヘルパー関数)を使用する、より現代的で簡潔なGoのイディオムへの更新です。機能的な変更はありませんが、コードの可読性と保守性が向上します。
-
src/sudo.bash
の変更:- このスクリプトは、
cov
とprof
ツールをシステムワイドにインストールするためのものです。 - 古い
6$i
形式のバイナリを削除し、新しい$i
形式のバイナリをインストールするように変更されています。 - インストールパスは
/usr/local/bin/6$i
から/usr/local/bin/go$i
へと変更されています。これは、Goツールであることを明示し、他のシステムツールとの名前の衝突を避けるための命名規則の変更です。 chgrp procmod
とchmod g+s
は、特定のグループ (procmod
) に所有権を与え、setgidビットを設定することで、これらのツールが特定の権限で実行されるようにするためのものです。これは、プロファイリングやカバレッジ測定のような操作が、システムリソースへのアクセスを必要とする場合があるためです。
- このスクリプトは、
これらの変更は、Goのビルドシステムが進化し、よりモジュール化され、特定の種類のツール(C言語で書かれたもの)の管理が改善されたことを示しています。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更は、主に以下のファイルに集中しています。
-
src/Make.ctool
(新規ファイル):- C言語で書かれたGoツールをビルドするための新しいMakefileの定義。
- Windows環境での
.exe
拡張子の自動付与。 HOST_LD
とHOST_CC
を使用したコンパイル・リンク規則。$GOROOT/bin/go-tool
へのインストールルール。bison
を使用したパーサファイルの生成ルール。
-
src/cmd/cov/Makefile
:TARG=6cov
からTARG=cov
への変更。include ../../Make.ccmd
からinclude ../../Make.ctool
への変更。- インストールパスを
$(GOBIN)/$(TARG)
から$(GOBIN)/go-tool/$(TARG)
へ変更。
-
src/cmd/nm/Makefile
:TARG=6nm
からTARG=nm
への変更。include ../../Make.ccmd
からinclude ../../Make.ctool
への変更。
-
src/cmd/prof/Makefile
:TARG=6prof
からTARG=prof
への変更。include ../../Make.ccmd
からinclude ../../Make.ctool
への変更。- インストールパスを
$(GOBIN)/$(TARG)
から$(GOBIN)/go-tool/$(TARG)
へ変更。 install-pprof
ターゲットのソースとインストールパスの変更。
-
src/cmd/prof/{gopprof => pprof}
(ファイル名変更):gopprof
スクリプトがpprof
にリネームされました。
-
src/sudo.bash
:cov
とprof
のシステムワイドインストールロジックの更新。- 古い
6$i
バイナリの削除と、新しいgo$i
バイナリのインストール。 - インストールパスが
/usr/local/bin/6$i
から/usr/local/bin/go$i
へ変更。
-
src/cmd/go/tool.go
:sort.StringSlice(names).Sort()
からsort.Strings(names)
への変更。
コアとなるコードの解説
src/Make.ctool
(抜粋)
# Tools always go into $GOROOT/bin/go-tool
ifeq (windows,$(findstring windows, $(shell uname | tr A-Z a-z | sed 's/mingw/windows/')))\n+TARG:=$(TARG).exe
endif
$(TARG): $(OFILES) $(LIB)
$(HOST_LD) -o $(TARG) -L"$(GOROOT)"/lib $(OFILES) $(LIB) -lmach -lbio -l9 -lm $(HOST_LDFLAGS)
# ... (clean, nuke, y.tab.h/c rules) ...
ifneq ($(NOINSTALL),1)
install: $(QUOTED_GOROOT)/bin/go-tool/$(TARG)
endif
$(QUOTED_GOROOT)/bin/go-tool/$(TARG): $(TARG)
mkdir -p "$(GOROOT)/bin/go-tool" && cp $(TARG) "$(GOROOT)/bin/go-tool/$(TARG)"
%.$(HOST_O): %.c
$(HOST_CC) $(HOST_CFLAGS) -c "$(PWD)/$*.c"
この新しいMakefileは、C言語で書かれたGoツールをビルドするための中心的な役割を担います。特に注目すべきは、$GOROOT/bin/go-tool
という専用のインストールディレクトリが導入された点です。これにより、Goの標準ツールとC言語で書かれた補助ツールが明確に分離されます。Windows環境での .exe
拡張子の自動付与は、クロスプラットフォーム対応の一環です。
src/cmd/cov/Makefile
(抜粋)
-TARG=6cov
+TARG=cov
OFILES=\
main.$O\
tree.$O\
# ...
NOINSTALL=1
-include ../../Make.ccmd
+include ../../Make.ctool
# ... (install-darwin, install-default rules) ...
install-default: $(TARG)
- cp $(TARG) "$(GOBIN)"/$(TARG)
+ cp $(TARG) "$(GOBIN)"/go-tool/$(TARG)
cov
ツールのMakefileの変更は、他のCツール(nm
, prof
)にも共通するパターンを示しています。
TARG
の変更:6cov
からcov
へと名前が簡潔になりました。include
の変更: 汎用的なMake.ccmd
から、Cツール専用のMake.ctool
へとビルドシステムが切り替わりました。これにより、Cツールに特化したビルドルールが適用されます。- インストールパスの変更:
$(GOBIN)
直下ではなく、$(GOBIN)/go-tool/
サブディレクトリにインストールされるようになりました。これは、Goツールチェイン内のツールの役割と配置をより明確にするための整理です。
src/sudo.bash
(抜粋)
for i in prof cov
do
# Remove old binaries if present
sudo rm -f /usr/local/bin/6$i
# Install new binaries
sudo cp "$GOROOT"/src/cmd/$i/$i /usr/local/bin/go$i
sudo chgrp procmod /usr/local/bin/go$i
sudo chmod g+s /usr/local/bin/go$i
done
このシェルスクリプトは、cov
と prof
をシステムワイドにインストールする際のロジックを更新しています。
sudo rm -f /usr/local/bin/6$i
: 以前の命名規則 (6cov
,6prof
) でインストールされていた古いバイナリを削除します。sudo cp "$GOROOT"/src/cmd/$i/$i /usr/local/bin/go$i
: 新しい命名規則 (cov
,prof
) でビルドされたバイナリを、/usr/local/bin/go$i
というパスでシステムにコピーします。これにより、例えばgocov
やgoprof
のようなコマンド名でこれらのツールが利用できるようになります。sudo chgrp procmod /usr/local/bin/go$i
とsudo chmod g+s /usr/local/bin/go$i
: これらのコマンドは、インストールされたバイナリのグループ所有者をprocmod
に変更し、setgidビットを設定します。setgidビットが設定された実行可能ファイルは、そのファイルが属するグループの権限で実行されます。これは、プロファイリングやカバレッジ測定ツールが、システムプロセス情報へのアクセスなど、特定の特権を必要とする場合に用いられるセキュリティ設定です。
src/cmd/go/tool.go
(抜粋)
func listTools() {
// ...
// Old: sort.StringSlice(names).Sort()
sort.Strings(names) // New
for _, name := range names {
// ...
}
}
この変更は、Goの標準ライブラリの sort
パッケージの利用方法を更新したものです。sort.StringSlice(names).Sort()
は、[]string
型を sort.Interface
インターフェースに適合させるための古いイディオムでした。sort.Strings(names)
は、Go 1.8で導入された sort
パッケージのヘルパー関数であり、[]string
を直接ソートできるため、より簡潔で読みやすいコードになります。これは機能的な変更ではなく、コードの現代化とベストプラクティスへの準拠を示しています。
関連リンク
- Go言語公式ウェブサイト: https://golang.org/
- Goのソースコードリポジトリ (GitHub): https://github.com/golang/go
- GoのIssue Tracker (Gerrit): https://go.dev/issue (このコミットのChange-Id:
5576067
に関連するGerritの変更セットは、古いGerritインスタンスのものである可能性があり、直接アクセスできない場合があります。)
参考にした情報源リンク
- Go言語のMakefileに関するドキュメントや議論 (Goのソースコード内のコメントや関連するコミット履歴)
- Goの
sort
パッケージのドキュメント: https://pkg.go.dev/sort - Unix
nm
コマンドのmanページ bison
のドキュメントgdb
のドキュメント