[インデックス 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 (一般的な情報源として)