Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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を使用してビルドされ、6cov6nm6prof のようなプレフィックス付きの名前でインストールされていました。また、インストール先も $GOBIN ディレクトリ直下でした。

このコミットは、以下の問題点や改善点を解決しようとしています。

  1. ビルドプロセスの明確化: C言語で書かれたツールに特化した新しいMakefile (Make.ctool) を導入することで、ビルドプロセスをより明確にし、Go言語で書かれたツールとは異なるビルド要件を適切に管理します。
  2. ツールの命名規則の統一: 6cov のようなプレフィックスは、Goのバージョンやアーキテクチャを示すものでしたが、Goツールチェインが成熟するにつれて、より汎用的な名前 (cov, nm, prof) が望ましくなりました。これにより、ツールの利用者が混乱することなく、直感的にツールを識別できるようになります。
  3. インストールパスの整理: Goのツールは通常 $GOROOT/bin または $GOBIN にインストールされますが、このコミットではC言語ツールを $GOROOT/bin/go-tool/ という専用のサブディレクトリに配置することで、Goツールチェインの他の部分との分離を明確にし、管理を容易にします。これは、これらのツールがGoコンパイラやリンカとは異なる補助的な役割を持つことを示唆しています。
  4. システムワイドなインストールの改善: sudo.bash スクリプトの更新は、これらのツールをシステム全体にインストールする際のパスと名前の整合性を確保し、古いバイナリの残存を防ぐためのものです。

これらの変更は、Goプロジェクトが成長し、ツールチェインが複雑化する中で、よりクリーンで保守しやすい構造を目指す一環として行われました。

前提知識の解説

このコミットを理解するためには、以下の概念について知っておく必要があります。

  • Go言語のビルドシステム: Goプロジェクトは、独自のビルドシステムを使用しており、Makefileがその一部を構成しています。Make.incMake.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.hy.tab.c といったファイルが生成されるのは、bison が使用されていることを示します。
  • gdb: GNU Debuggerの略で、プログラムの実行を制御し、内部状態を検査するためのデバッグツールです。

技術的詳細

このコミットの技術的詳細は、主にGoのビルドシステムにおけるC言語ツールの取り扱いに関するものです。

  1. 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 を使用してパーサ関連のファイルを生成するプロセスを定義しています。これは、covprof のようなツールが構文解析を必要とする場合に利用されます。
    • %.$(HOST_O): %.c ルールは、Cソースファイルをオブジェクトファイルにコンパイルする方法を定義しています。$(PWD)/$*.c を使用することで、gdb のようなデバッガがスタックトレースで完全なパスを表示できるようにしています。
  2. ツールの名称変更とMakefileの更新:

    • src/cmd/cov/Makefile, src/cmd/nm/Makefile, src/cmd/prof/Makefile の各ファイルで、TARG 変数の値が 6cov から cov6nm から nm6prof から prof へと変更されています。これにより、生成されるバイナリの名前が簡潔になります。
    • これらのMakefileは、include ../../Make.ccmd から include ../../Make.ctool へと変更され、新しいCツール専用のビルドシステムを利用するようになりました。
    • NOINSTALL=1 の削除は、これらのツールがデフォルトでインストールされるようになったことを意味します。
    • インストールパスが $(GOBIN)/$(TARG) から $(GOBIN)/go-tool/$(TARG) へと変更され、専用のサブディレクトリに配置されるようになりました。
    • src/cmd/prof/gopprofsrc/cmd/prof/pprof にリネームされました。これは、pprof ツール自体がGo言語で書かれたスクリプトまたはバイナリであり、その名前を簡潔にするための変更です。
  3. src/cmd/go/tool.go の変更:

    • sort.StringSlice(names).Sort()sort.Strings(names) に変更されています。これは、Go 1.8で導入された sort.Strings 関数(sort.StringSlice のヘルパー関数)を使用する、より現代的で簡潔なGoのイディオムへの更新です。機能的な変更はありませんが、コードの可読性と保守性が向上します。
  4. src/sudo.bash の変更:

    • このスクリプトは、covprof ツールをシステムワイドにインストールするためのものです。
    • 古い 6$i 形式のバイナリを削除し、新しい $i 形式のバイナリをインストールするように変更されています。
    • インストールパスは /usr/local/bin/6$i から /usr/local/bin/go$i へと変更されています。これは、Goツールであることを明示し、他のシステムツールとの名前の衝突を避けるための命名規則の変更です。
    • chgrp procmodchmod g+s は、特定のグループ (procmod) に所有権を与え、setgidビットを設定することで、これらのツールが特定の権限で実行されるようにするためのものです。これは、プロファイリングやカバレッジ測定のような操作が、システムリソースへのアクセスを必要とする場合があるためです。

これらの変更は、Goのビルドシステムが進化し、よりモジュール化され、特定の種類のツール(C言語で書かれたもの)の管理が改善されたことを示しています。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更は、主に以下のファイルに集中しています。

  1. src/Make.ctool (新規ファイル):

    • C言語で書かれたGoツールをビルドするための新しいMakefileの定義。
    • Windows環境での .exe 拡張子の自動付与。
    • HOST_LDHOST_CC を使用したコンパイル・リンク規則。
    • $GOROOT/bin/go-tool へのインストールルール。
    • bison を使用したパーサファイルの生成ルール。
  2. src/cmd/cov/Makefile:

    • TARG=6cov から TARG=cov への変更。
    • include ../../Make.ccmd から include ../../Make.ctool への変更。
    • インストールパスを $(GOBIN)/$(TARG) から $(GOBIN)/go-tool/$(TARG) へ変更。
  3. src/cmd/nm/Makefile:

    • TARG=6nm から TARG=nm への変更。
    • include ../../Make.ccmd から include ../../Make.ctool への変更。
  4. src/cmd/prof/Makefile:

    • TARG=6prof から TARG=prof への変更。
    • include ../../Make.ccmd から include ../../Make.ctool への変更。
    • インストールパスを $(GOBIN)/$(TARG) から $(GOBIN)/go-tool/$(TARG) へ変更。
    • install-pprof ターゲットのソースとインストールパスの変更。
  5. src/cmd/prof/{gopprof => pprof} (ファイル名変更):

    • gopprof スクリプトが pprof にリネームされました。
  6. src/sudo.bash:

    • covprof のシステムワイドインストールロジックの更新。
    • 古い 6$i バイナリの削除と、新しい go$i バイナリのインストール。
    • インストールパスが /usr/local/bin/6$i から /usr/local/bin/go$i へ変更。
  7. 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)にも共通するパターンを示しています。

  1. TARG の変更: 6cov から cov へと名前が簡潔になりました。
  2. include の変更: 汎用的な Make.ccmd から、Cツール専用の Make.ctool へとビルドシステムが切り替わりました。これにより、Cツールに特化したビルドルールが適用されます。
  3. インストールパスの変更: $(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

このシェルスクリプトは、covprof をシステムワイドにインストールする際のロジックを更新しています。

  • 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 というパスでシステムにコピーします。これにより、例えば gocovgoprof のようなコマンド名でこれらのツールが利用できるようになります。
  • sudo chgrp procmod /usr/local/bin/go$isudo 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 のドキュメント