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

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

このコミットは、Go言語のビルドツールである cmd/go における gccgo ツールチェーンのフラグ処理に関する改善と、ユーザーが誤ったツールチェーンオプションを渡した場合の警告機能の追加を目的としています。具体的には、gccgo コマンドラインの末尾に gccgoflags を渡すように変更し、gcgccgo の間で誤ったフラグ(例: gccgo 使用時に -gcflags を使用)が指定された場合にユーザーに警告を表示するようになりました。

コミット

commit 326ccebec8986de534c8608ff6f8fe7bd0070b10
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Wed Dec 19 01:48:09 2012 +0800

    cmd/go: pass gccgoflags at the end of gccgo command line, warn if user passes the wrong toolchain options
    
    R=iant
    CC=golang-dev
    https://golang.org/cl/6940082

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

https://github.com/golang/go/commit/326ccebec8986de534c8608ff6f8fe7bd0070b10

元コミット内容

cmd/go: pass gccgoflags at the end of gccgo command line, warn if user passes the wrong toolchain options

R=iant
CC=golang-dev
https://golang.org/cl/6940082

変更の背景

Go言語のビルドシステムでは、複数のコンパイラツールチェーンをサポートしています。主要なものはGoチームが開発している gc (Go Compiler) と、GCCをベースにした gccgo です。これらのツールチェーンは、それぞれ異なるコマンドラインフラグを受け入れます。

以前の go build コマンドでは、gccgo ツールチェーンを使用する際に、コンパイラやリンカに渡すためのカスタムフラグを buildGccgoflags 変数を通じて処理していました。しかし、これらのフラグが gccgo コマンドラインの途中に挿入されることがあり、特定のシナリオで問題を引き起こす可能性がありました。特に、リンカフラグ (-Wl,...) のような特定のオプションは、コマンドラインの末尾に配置されることがGCCベースのツールでは一般的であり、そうでない場合に予期せぬ挙動やエラーが発生することがあります。

また、ユーザーが go build コマンドを使用する際に、現在選択されているツールチェーン(gc または gccgo)に対して不適切なフラグ(例: gccgo を使用しているのに -gcflags を指定する、または gc を使用しているのに -gccgoflags を指定する)を渡してしまうという問題がありました。これは混乱を招き、意図しないビルド結果につながる可能性がありました。

このコミットは、これらの問題を解決するために、gccgo のフラグ処理を改善し、ユーザーへの警告を強化することを目的としています。

前提知識の解説

  • go build コマンド: Go言語のソースコードをコンパイルして実行可能ファイルを生成するための主要なコマンドです。Goモジュール内のパッケージをビルドし、依存関係を解決します。
  • Goツールチェーン: Go言語のプログラムをビルドするために必要な一連のツール(コンパイラ、リンカ、アセンブラなど)の総称です。
  • gc (Go Compiler): Go言語の公式コンパイラであり、Goチームによって開発されています。Go言語のソースコードを直接機械語にコンパイルします。
  • gccgo: GCC (GNU Compiler Collection) をバックエンドとして使用するGo言語のコンパイラです。gc とは異なる実装であり、GCCの最適化やクロスコンパイル機能を利用できる場合があります。
  • コンパイラフラグ (-gcflags, -gccgoflags): コンパイラの挙動を制御するためのオプションです。
    • -gcflags: gc コンパイラに渡されるフラグを指定します。
    • -gccgoflags: gccgo コンパイラに渡されるフラグを指定します。
  • リンカフラグ (-ldflags): リンカの挙動を制御するためのオプションです。通常、生成される実行ファイルの特性(例: 埋め込み情報、ライブラリのリンク方法)に影響を与えます。
    • -Wl,...: GCC系のツールでリンカにオプションを渡すための一般的な方法です。

技術的詳細

このコミットは、src/cmd/go/build.go ファイル内の runBuild 関数と gccgcToolchain.ld 関数に焦点を当てています。

  1. フラグの誤用に対する警告: runBuild 関数内に新しい「sanity check」セクションが追加されました。これは、ユーザーが go build コマンドに渡したフラグが、現在使用されているツールチェーンに対して適切であるかを検証します。

    • gccgo ツールチェーンが選択されている場合 (buildContext.Compiler == "gccgo"):
      • もし buildGcflags (gcコンパイラ用のフラグ) が指定されていたら、「go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags」という警告が表示されます。
      • もし buildLdflags (gcリンカ用のフラグ) が指定されていたら、「go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags」という警告が表示されます。
    • gc ツールチェーンが選択されている場合 (buildContext.Compiler == "gc"):
      • もし buildGccgoflags (gccgoコンパイラ用のフラグ) が指定されていたら、「go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags」という警告が表示されます。 これらの警告は、ユーザーが正しいフラグを使用するように促し、ビルドの失敗や予期せぬ挙動を防ぐのに役立ちます。
  2. gccgo コマンドラインでの gccgoflags の配置変更: gccgcToolchain.ld 関数は、gccgo ツールチェーンを使用して最終的な実行ファイルをリンクする際のコマンドラインを構築します。以前は buildGccgoflagsgccgo コマンドラインの途中に配置されていました。 変更後、buildGccgoflagsgccgo コマンドラインの末尾に移動されました。これは、GCCベースのリンカがリンカ固有のオプション(特に -Wl,... のようなもの)をコマンドラインの最後に期待する一般的な慣習に合わせたものです。これにより、gccgo を使用したビルドの堅牢性が向上し、特定のリンカフラグが正しく解釈されるようになります。

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

src/cmd/go/build.go ファイルの以下の部分が変更されました。

--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -191,6 +191,21 @@ func runBuild(cmd *Command, args []string) {
 		*buildO += exeSuffix
 	}
 
+	// sanity check some often mis-used options
+	switch buildContext.Compiler {
+	case "gccgo":
+		if len(buildGcflags) != 0 {
+			fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
+		}
+		if len(buildLdflags) != 0 {
+			fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
+		}
+	case "gc":
+		if len(buildGccgoflags) != 0 {
+			fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
+		}
+	}
+
 	if *buildO != "" {
 		if len(pkgs) > 1 {
 			fatalf("go build: cannot use -o with multiple packages")
@@ -1451,7 +1466,7 @@ func (tools gccgcToolchain) ld(b *builder, p *Package, out string, allactions []
 	if usesCgo && goos == "linux" {
 		ldflags = append(ldflags, "-Wl,-E")
 	}
-	return b.run(".", p.ImportPath, "gccgo", "-o", out, buildGccgoflags, ofiles, "-Wl,-(\", ldflags, "-Wl,-)")
+	return b.run(".", p.ImportPath, "gccgo", "-o", out, ofiles, "-Wl,-(\", ldflags, "-Wl,-)", buildGccgoflags)
 }
 
 func (gccgcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {

コアとなるコードの解説

runBuild 関数内の変更

 	// sanity check some often mis-used options
 	switch buildContext.Compiler {
 	case "gccgo":
 		if len(buildGcflags) != 0 {
 			fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
 		}
 		if len(buildLdflags) != 0 {
 			fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
 		}
 	case "gc":
 		if len(buildGccgoflags) != 0 {
 			fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
 		}
 	}

このコードブロックは、go build コマンドが実行される際に、ユーザーが指定したコンパイラフラグが現在のビルドコンテキスト(使用されているツールチェーン)と一致しているかをチェックします。

  • buildContext.Compiler は、現在使用されているGoコンパイラ(gc または gccgo)を示します。
  • gccgo が使用されているにもかかわらず、gc 用のフラグ (buildGcflagsbuildLdflags) が指定されている場合、適切な gccgoflags を使用するよう警告します。
  • 同様に、gc が使用されているにもかかわらず、gccgo 用のフラグ (buildGccgoflags) が指定されている場合、適切な gcflagsldflags を使用するよう警告します。 これにより、ユーザーの誤解を減らし、ビルドエラーを未然に防ぐことができます。

gccgcToolchain.ld 関数内の変更

-	return b.run(".", p.ImportPath, "gccgo", "-o", out, buildGccgoflags, ofiles, "-Wl,-(\", ldflags, "-Wl,-)")
+	return b.run(".", p.ImportPath, "gccgo", "-o", out, ofiles, "-Wl,-(\", ldflags, "-Wl,-)", buildGccgoflags)

この行は、gccgo リンカコマンドを構築する部分です。変更の核心は buildGccgoflags の位置です。

  • 変更前は buildGccgoflagsofiles (オブジェクトファイル) の前に配置されていました。
  • 変更後は buildGccgoflags がコマンドラインの末尾に移動されました。 これは、GCCベースのツール(gccgo も含む)が、リンカに渡されるカスタムフラグや特殊なオプションをコマンドラインの最後に配置することを期待する一般的なパターンに準拠するためです。これにより、リンカがこれらのフラグを正しく解釈し、ビルドプロセスがより安定して予測可能になります。特に、-Wl,-(-Wl,-) のようなリンカグループオプションの後にカスタムリンカフラグを配置することは、GCCリンカの動作において重要です。

関連リンク

このコミットに関連するGo Gerritの変更リスト (CL) は https://golang.org/cl/6940082 ですが、現在のツールでは直接その内容を取得できませんでした。

参考にした情報源リンク

  • コミットの差分情報 (git diff)
  • Go言語のビルドシステムとツールチェーンに関する一般的な知識
  • GCCおよびgccgoのコマンドラインオプションに関する一般的な知識