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

[インデックス 18866] ファイルの概要

このコミットは、Go言語のコマンドラインツール cmd/go における go build -x コマンドの出力に関するバグ修正です。具体的には、go build -x が表示する go pack コマンドラインが不正であった問題を修正しています。

コミット

commit 22aa54965e1cc7f0a2b194588c1bd8c7c627182d
Author: Jan Ziak <0xe2.0x9a.0x9b@gmail.com>
Date:   Fri Mar 14 16:44:54 2014 +0100

    cmd/go: fix invalid go pack command line in the output of go build -x
    
    Fixes #7262
    
    LGTM=iant
    R=golang-codereviews, iant
    CC=golang-codereviews
    https://golang.org/cl/76110043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/22aa54965e1cc7f0a2b194588c1bd8c7c627182d

元コミット内容

cmd/go: fix invalid go pack command line in the output of go build -x

Fixes #7262

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/76110043

変更の背景

このコミットは、Goのビルドプロセスにおける内部コマンド go pack の呼び出しに関する表示上の問題を修正することを目的としています。go build -x コマンドは、ビルド中に実行されるすべてのコマンドを詳細に表示するデバッグオプションです。しかし、このオプションを使用した場合に表示される go pack コマンドの引数が、実際に実行されるコマンドと異なっていました。

具体的には、既存のアーカイブファイルにオブジェクトファイルを「追加 (append)」する際に go pack コマンドに渡される引数が rqP と表示されていましたが、これは正しくありませんでした。正しい引数は r であり、qP は不要でした。この不一致は、ユーザーが go build -x の出力を解析したり、ビルドプロセスを理解しようとしたりする際に混乱を招く可能性がありました。

この問題は、GoのIssueトラッカーで #7262 として報告されていました。このコミットは、その報告された問題を解決するためのものです。

前提知識の解説

go build コマンド

go build は、Goのソースコードをコンパイルして実行可能ファイルやパッケージアーカイブを生成するための主要なコマンドです。

go build -x オプション

-x オプションは、go build が内部的に実行するすべてのコマンド(コンパイラ、アセンブラ、リンカ、アーカイブツールなど)を標準エラー出力に表示します。これは、ビルドプロセスの詳細をデバッグしたり、理解したりするのに非常に役立ちます。

go pack コマンド

go pack は、Goツールチェーンの一部として使用されるアーカイブツールです。これは、Unix系のシステムにおける ar コマンドに似た機能を提供し、オブジェクトファイル(.o ファイル)をまとめてライブラリアーカイブ(.a ファイル)を作成したり、既存のアーカイブにファイルを追加したりするために使用されます。

go pack の一般的な使用法は以下の通りです。

  • go pack r <archive_file> <object_files>: 指定されたオブジェクトファイルをアーカイブファイルに追加します。アーカイブファイルが存在しない場合は新しく作成されます。
  • go pack rq <archive_file> <object_files>: r と同様ですが、既存のメンバーを置き換えます。
  • go pack rqP <archive_file> <object_files>: rq と同様ですが、P オプションは、アーカイブ内のメンバー名にパス名を含めることを意味します。

このコミットの文脈では、既存のアーカイブにオブジェクトファイルを追加する際に go pack が使用されます。

Goのビルドプロセス

Goのビルドプロセスは、複数のステップから構成されます。

  1. コンパイル: Goのソースファイル(.go)がコンパイラによってオブジェクトファイル(.o)にコンパイルされます。
  2. アーカイブ: コンパイルされたオブジェクトファイルは、go pack などのツールによってライブラリアーカイブ(.a)にまとめられます。これは、パッケージの依存関係を解決し、リンクを効率化するために行われます。
  3. リンク: 最終的に、すべてのライブラリアーカイブと必要なランタイムライブラリがリンカによって結合され、実行可能ファイルが生成されます。

go build -x は、これらの各ステップで実際に実行されるコマンドを表示することで、ビルドプロセスの透明性を提供します。

技術的詳細

この修正は、src/cmd/go/build.go ファイル内の pack メソッドにあります。このメソッドは、go build コマンドが内部的に go pack ツールを呼び出す際のロジックをカプセル化しています。

問題は、既存のアーカイブファイルにオブジェクトファイルを追加する際に、appending というフラグが true に設定されるロジックにありました。この appendingtrue の場合、go pack に渡すコマンド引数として cmd = "rqP" が設定されていました。しかし、実際に必要なのは r オプションのみでした。q (quiet) や P (pathnames) は、この文脈では不要であり、go build -x の出力に誤った情報として表示されていました。

修正は、appendingtrue の場合に cmd 変数を "r" に変更するだけです。これにより、go pack コマンドラインが正しく pack r <archive_file> <object_files> の形式で表示されるようになります。

stringList 関数は、与えられた文字列スライスを結合してコマンドライン文字列を生成するために使用されます。修正前は、pack, cmd, b.work, absAfile, absOfiles の順で引数が渡されていましたが、修正後は b.work (作業ディレクトリ) が削除され、pack, cmd, absAfile, absOfiles の順で引数が渡されるようになりました。これは、go pack コマンド自体が作業ディレクトリを引数として必要としないため、go build -x の出力から不要な情報を削除し、より正確なコマンドラインを表示するための変更です。

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

--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1625,10 +1625,10 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
 	appending := false
 	if _, err := os.Stat(absAfile); err == nil {
 		appending = true
-		cmd = "rqP"
+		cmd = "r"
 	}
 
-	cmdline := stringList("pack", cmd, b.work, absAfile, absOfiles)
+	cmdline := stringList("pack", cmd, absAfile, absOfiles)
 
 	if appending {
 		if buildN || buildX {

コアとなるコードの解説

変更前

	appending := false
	if _, err := os.Stat(absAfile); err == nil {
		appending = true
		cmd = "rqP" // 既存のアーカイブファイルが存在する場合、"rqP" を設定
	}

	cmdline := stringList("pack", cmd, b.work, absAfile, absOfiles) // b.work もコマンドラインに含める
  • os.Stat(absAfile): 指定されたパス absAfile (アーカイブファイルの絶対パス) のファイル情報を取得しようとします。
  • err == nil: ファイルが存在する場合、エラーは nil となり、appendingtrue に設定されます。
  • cmd = "rqP": appendingtrue の場合、go pack に渡すコマンド引数として "rqP" が設定されます。これは、既存のアーカイブにファイルを追加する際に使用されるオプションです。しかし、この q (quiet) と P (pathnames) は、go build -x の出力において不要な情報でした。
  • stringList("pack", cmd, b.work, absAfile, absOfiles): go pack コマンドラインを構築します。このとき、b.work (ビルドの作業ディレクトリ) も引数として含まれていました。

変更後

	appending := false
	if _, err := os.Stat(absAfile); err == nil {
		appending = true
		cmd = "r" // 既存のアーカイブファイルが存在する場合、"r" に修正
	}

	cmdline := stringList("pack", cmd, absAfile, absOfiles) // b.work を削除
  • cmd = "r": appendingtrue の場合、go pack に渡すコマンド引数が "r" に修正されました。r オプションは、既存のアーカイブにメンバーを追加または置き換えるための標準的なオプションであり、qP はこの文脈では冗長でした。これにより、go build -x の出力がより正確になります。
  • stringList("pack", cmd, absAfile, absOfiles): go pack コマンドラインの構築から b.work が削除されました。go pack コマンド自体は作業ディレクトリを引数として必要としないため、この変更は go build -x の出力をより簡潔で正確なものにします。

この修正により、go build -x の出力は、実際に go pack が実行される際のコマンドラインを正確に反映するようになり、デバッグやビルドプロセスの理解が容易になります。

関連リンク

  • Go issue #7262: cmd/go: fix invalid go pack command line in the output of go build -x (このコミットが修正した問題の報告)
    • 直接的なリンクは見つかりませんでしたが、コミットメッセージに記載されています。
  • Go CL 76110043: cmd/go: fix invalid go pack command line in the output of go build -x (このコミットの変更リスト)

参考にした情報源リンク

  • Goの公式ドキュメント(go buildgo tool pack などに関する情報)
  • ar コマンドのmanページ(go pack の動作を理解するための参考)
  • Goのソースコード(src/cmd/go/build.go
  • GoのIssueトラッカー(過去のIssueの検索)
  • Goのコードレビューシステム(Gerrit)