[インデックス 13232] ファイルの概要
このコミットは、Go言語のビルドツール cmd/go に -ccflags オプションを追加するものです。これにより、GoのツールチェインがC言語のソースコードをコンパイルする際に使用するCコンパイラ(5c, 6c, 8cなど)に対して、追加の引数を渡すことが可能になります。これは、Goコンパイラ(5g, 6g, 8gなど)に引数を渡すための既存の -gcflags オプションと同様の機能を提供します。
コミット
commit 5b2cd445fbc586e6a1c12420436a5523cd9f8d78
Author: Dave Cheney <dave@cheney.net>
Date: Thu May 31 09:10:03 2012 +1000
cmd/go: add -ccflags
Add -ccflags to pass arguments to {5,6,8}c
similar to -gcflags for {5,6,8}g.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6260047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5b2cd445fbc586e6a1c12420436a5523cd9f8d78
元コミット内容
cmd/go: add -ccflags
Add -ccflags to pass arguments to {5,6,8}c
similar to -gcflags for {5,6,8}g.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6260047
変更の背景
Go言語は、C言語のコードをGoプログラムに組み込むための cgo というメカニズムを提供しています。cgo を使用すると、Goのソースコード内にC言語のコードを記述し、Goの関数からCの関数を呼び出したり、その逆を行ったりすることができます。
Goのビルドプロセスでは、Goのソースコードは 5g, 6g, 8g といったGoコンパイラによってコンパイルされ、Cのソースコードは 5c, 6c, 8c といったCコンパイラによってコンパイルされます。これらのコンパイラは、Goのツールチェインの一部として提供されるPlan 9系のコンパイラです。
従来、Goコンパイラに対しては -gcflags オプションを使って追加の引数(例えば最適化レベルの調整やデバッグ情報の追加など)を渡すことが可能でした。しかし、Cコンパイラに対して同様の引数を渡す直接的な手段が go build コマンドにはありませんでした。
このコミットの背景には、cgo を利用する際に、Cコンパイラの挙動を細かく制御したいというニーズがありました。例えば、特定のCライブラリをリンクする際に必要なコンパイラフラグや、Cコードの最適化設定などをビルド時に指定したい場合です。-ccflags の導入により、Goのビルドシステムを通じてCコンパイラに直接引数を渡せるようになり、cgo を利用したプロジェクトのビルドの柔軟性が向上しました。
前提知識の解説
Goのビルドプロセスとツールチェイン
Go言語のビルドプロセスは、go build コマンドによって管理されます。このコマンドは、ソースコードの依存関係を解決し、コンパイル、アセンブル、リンクといった一連の処理を実行して実行可能ファイルを生成します。
Goのツールチェインは、Goコンパイラ(gc)、アセンブラ(as)、リンカ(ld)など、ビルドに必要な様々なツールを含んでいます。これらのツールは、ターゲットアーキテクチャ(例: amd64, arm, 386)に応じて、それぞれ 6g, 5g, 8g のように命名されています。
5g: ARMアーキテクチャ向けのGoコンパイラ6g: x86-64 (AMD64) アーキテクチャ向けのGoコンパイラ8g: x86 (386) アーキテクチャ向けのGoコンパイラ
同様に、C言語のコンパイルにはPlan 9系のCコンパイラが使用されます。
5c: ARMアーキテクチャ向けのCコンパイラ6c: x86-64 (AMD64) アーキテクチャ向けのCコンパイラ8c: x86 (386) アーキテクチャ向けのCコンパイラ
cgo
cgo は、GoプログラムからC言語のコードを呼び出すためのGoの機能です。Goのソースファイル内に import "C" と記述し、その後にC言語のコードをコメント形式で記述することで、GoとCの相互運用が可能になります。cgo を使用すると、Goの標準ライブラリでは提供されていない低レベルなシステムコールや、既存のCライブラリを利用することができます。
cgo を含むGoプログラムをビルドする際、GoのビルドツールはまずC言語のコードをCコンパイラ(5c, 6c, 8cなど)でコンパイルし、その結果生成されたオブジェクトファイルをGoのオブジェクトファイルとリンクします。
コンパイラフラグ
コンパイラフラグ(またはコンパイラオプション)は、コンパイラの挙動を制御するためにコンパイラに渡されるコマンドライン引数です。これらは、コンパイル時の最適化レベル、デバッグ情報の生成、警告の表示方法、インクルードパスの指定、マクロの定義など、多岐にわたる設定を調整するために使用されます。
Goのビルドコマンドでは、これまでも以下の主要なフラグが提供されていました。
-gcflags: Goコンパイラ(5g,6g,8gなど)に渡す引数を指定します。例えば、-gcflags="-N -l"は最適化とインライン化を無効にし、デバッグを容易にします。-ldflags: リンカに渡す引数を指定します。例えば、-ldflags="-s -w"はシンボルテーブルとデバッグ情報を削除し、バイナリサイズを削減します。
このコミットで追加される -ccflags は、これらのフラグと同様に、Cコンパイラに引数を渡すためのものです。
技術的詳細
このコミットの技術的な変更は、主に src/cmd/go/build.go ファイルに集中しています。このファイルは、go コマンドのビルドロジックを定義しています。
変更のポイントは以下の通りです。
-
-ccflagsオプションの追加:go buildコマンドのヘルプメッセージに-ccflagsオプションの説明が追加されました。これにより、ユーザーがこの新しいオプションの存在と目的を認識できるようになります。@@ -60,6 +60,8 @@ The build flags are shared by the build, install, run, and test commands: -x \t\tprint the commands. +\t-ccflags 'arg list' +\t\targuments to pass on each 5c, 6c, or 8c compiler invocation -compiler name \t\tname of compiler to use, as in runtime.Compiler (gccgo or gc) -gccgoflags 'arg list' -
buildCcflags変数の導入:buildCcflagsという新しいスライス型の変数がvar宣言に追加されました。この変数は、-ccflagsオプションで指定された引数を格納するために使用されます。[]string型であることから、複数の引数をスペース区切りで受け取ることが想定されます。@@ -99,6 +101,7 @@ var buildX bool // -x flag var buildO = cmdBuild.Flag.String("o", "", "output file") var buildWork bool // -work flag var buildGcflags []string // -gcflags flag +var buildCcflags []string // -ccflags flag var buildLdflags []string // -ldflags flag var buildGccgoflags []string // -gccgoflags flag -
コマンドラインフラグの登録:
addBuildFlags関数内で、buildCcflags変数をcmd.Flag.Varを使ってコマンドラインフラグとして登録しています。(*stringsFlag)(&buildCcflags)は、stringsFlag型(GoのflagパッケージのValueインターフェースを実装しているカスタム型)にbuildCcflagsをキャストすることで、スペース区切りの文字列をスライスとしてパースできるようにしています。@@ -146,6 +149,7 @@ func addBuildFlags(cmd *Command) { cmd.Flag.BoolVar(&buildX, "x", false, "") cmd.Flag.BoolVar(&buildWork, "work", false, "") cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "") +\tcmd.Flag.Var((*stringsFlag)(&buildCcflags), "ccflags", "") cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "") cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "") cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "") -
Cコンパイラ呼び出しへの引数追加:
gcToolchain型のccメソッドが変更されました。このメソッドは、GoのツールチェインがC言語のソースファイルをコンパイルする際にCコンパイラ(5c,6c,8cなど)を呼び出すロジックを含んでいます。変更前は、Cコンパイラに渡す引数がハードコードされていました。
return b.run(p.Dir, p.ImportPath, tool(archChar+"c"), "-FVw", "-I", objdir, "-I", inc, "-o", ofile, "-DGOOS_"+goos, "-DGOARCH_"+goarch, cfile)変更後は、
buildCcflagsの内容がstringListヘルパー関数を通じて既存の引数リストに結合され、Cコンパイラに渡されるようになりました。stringListは、複数の引数スライスや個別の文字列を結合して単一の[]stringを生成するユーティリティ関数であると推測されます。@@ -1277,9 +1281,8 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action,\n func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {\n \tinc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))\n \tcfile = mkAbs(p.Dir, cfile)\n-\treturn b.run(p.Dir, p.ImportPath, tool(archChar+"c"), "-FVw",\n-\t\t"-I", objdir, "-I", inc, "-o", ofile,\n-\t\t"-DGOOS_"+goos, "-DGOARCH_"+goarch, cfile)\n+\targs := stringList(tool(archChar+"c"), "-FVw", "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-DGOOS_"+goos, "-DGOARCH_"+goarch, cfile)\n+\treturn b.run(p.Dir, p.ImportPath, args)\n }\この変更により、ユーザーが
-ccflagsで指定した任意の引数が、Cコンパイラの呼び出し時に動的に追加されるようになります。
コアとなるコードの変更箇所
src/cmd/go/build.go ファイルにおける変更箇所は以下の通りです。
-
行 60-61:
-ccflagsの説明が追加されました。--- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -60,6 +60,8 @@ The build flags are shared by the build, install, run, and test commands: -x \t\tprint the commands. +\t-ccflags 'arg list' +\t\targuments to pass on each 5c, 6c, or 8c compiler invocation -compiler name \t\tname of compiler to use, as in runtime.Compiler (gccgo or gc) -gccgoflags 'arg list' -
行 99-101:
buildCcflags変数が宣言されました。@@ -99,6 +101,7 @@ var buildX bool // -x flag var buildO = cmdBuild.Flag.String("o", "", "output file") var buildWork bool // -work flag var buildGcflags []string // -gcflags flag +var buildCcflags []string // -ccflags flag var buildLdflags []string // -ldflags flag var buildGccgoflags []string // -gccgoflags flag -
行 146-149:
addBuildFlags関数内でbuildCcflagsがコマンドラインフラグとして登録されました。@@ -146,6 +149,7 @@ func addBuildFlags(cmd *Command) { cmd.Flag.BoolVar(&buildX, "x", false, "") cmd.Flag.BoolVar(&buildWork, "work", false, "") cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "") +\tcmd.Flag.Var((*stringsFlag)(&buildCcflags), "ccflags", "") cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "") cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "") cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "") -
行 1277-1281:
gcToolchain.ccメソッド内でCコンパイラへの引数リストにbuildCcflagsが追加されました。@@ -1277,9 +1281,8 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action,\n func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {\n \tinc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))\n \tcfile = mkAbs(p.Dir, cfile)\n-\treturn b.run(p.Dir, p.ImportPath, tool(archChar+"c"), "-FVw",\n-\t\t"-I", objdir, "-I", inc, "-o", ofile,\n-\t\t"-DGOOS_"+goos, "-DGOARCH_"+goarch, cfile)\n+\targs := stringList(tool(archChar+"c"), "-FVw", "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-DGOOS_"+goos, "-DGOARCH_"+goarch, cfile)\n+\treturn b.run(p.Dir, p.ImportPath, args)\n }\
コアとなるコードの解説
-
-ccflags 'arg list'の追加: これはユーザー向けのドキュメント変更であり、go buildコマンドのヘルプメッセージに新しいオプションが追加されたことを示します。これにより、ユーザーはgo build -hを実行した際に-ccflagsの存在と用途を知ることができます。 -
var buildCcflags []stringの宣言:buildCcflagsは、go buildコマンドが実行される際に、-ccflagsオプションで指定されたすべての引数を文字列のスライスとして保持するためのグローバル変数です。この変数が存在することで、プログラムの他の部分から-ccflagsの値にアクセスできるようになります。 -
cmd.Flag.Var((*stringsFlag)(&buildCcflags), "ccflags", ""): この行は、Goの標準flagパッケージを使用して、buildCcflags変数をコマンドラインフラグ-ccflagsに関連付けています。stringsFlagは、おそらくflag.Valueインターフェースを実装したカスタム型で、コマンドラインから渡された文字列(例:"-ccflags='-Wall -O2'")をパースして、buildCcflagsスライスに個々の引数(例:["-Wall", "-O2"])として格納する役割を担っています。これにより、ユーザーは複数のCコンパイラフラグを単一の-ccflagsオプションで指定できるようになります。 -
args := stringList(tool(archChar+"c"), ..., buildCcflags, ...)およびreturn b.run(p.Dir, p.ImportPath, args): この部分が、実際にCコンパイラに-ccflagsで指定された引数を渡す核心的な変更です。gcToolchain.ccメソッドは、C言語のソースファイルをコンパイルするためにCコンパイラ(tool(archChar+"c")、例えば5c,6c,8c)を呼び出します。 変更前は、Cコンパイラに渡す引数が固定されていましたが、変更後はstringList関数を使って、既存の必須引数(-FVw,-I,-o,-DGOOS_,-DGOARCH_など)に加えて、buildCcflagsの内容が動的に追加されるようになりました。b.runメソッドは、指定されたディレクトリで、指定されたインポートパスのコンテキストで、指定されたコマンド(Cコンパイラ)と引数(args)を実行します。これにより、ユーザーが-ccflagsで指定した任意のコンパイラオプションが、Cコンパイラの実際の呼び出しに反映されるようになります。
関連リンク
- Go Change-Id:
I2222222222222222222222222222222222222222(コミットメッセージのhttps://golang.org/cl/6260047に対応するGoのコードレビューシステム (Gerrit) のチェンジリストID) - Go Issue Tracker: このコミットが解決した、または関連するGoのIssueがある場合、ここに記載されます。コミットメッセージには直接的なIssue番号の記載はありませんが、通常は関連するIssueが存在します。
参考にした情報源リンク
- Goの公式ドキュメント:
go buildコマンドのオプションに関する公式ドキュメント。 - cgoに関するGoの公式ドキュメント:
cgoの使い方とGoとCの相互運用に関する詳細。 - Plan 9 from Bell Labs: Goのツールチェインが使用するPlan 9系のコンパイラに関する背景情報。
- Goのソースコードリポジトリ:
src/cmd/go/build.goファイルの現在のバージョンや、関連するコミット履歴を確認するためのリポジトリ。 - Goのコードレビューシステム (Gerrit): コミットメッセージに記載されているチェンジリスト
https://golang.org/cl/6260047は、この変更が提案され、レビューされた場所です。- Go Code Review
- このリンクから、コミットに至るまでの議論や、レビュー担当者からのコメントなどを確認できます。
- Dave Cheneyのブログや記事: コミットの作者であるDave CheneyはGoコミュニティで著名な開発者であり、彼のブログや記事がこの変更の背景や意図についてさらに詳しい情報を提供している可能性があります。
- Dave Cheney's Blog (一般的な情報源として)
- Goのコンパイラフラグに関する議論: Goのメーリングリストやフォーラムでの
-gcflags,-ldflagsなどに関する議論。- golang-nuts Google Group (一般的な情報源として)
- golang-dev Google Group (一般的な情報源として)