[インデックス 14285] ファイルの概要
このコミットは、Go言語の標準ビルドツールである cmd/go
における gccgo
サポートの改善に関するものです。具体的には、src/cmd/go/build.go
ファイルが変更されており、gccgo
コンパイラとの連携をよりスムーズにするための様々な修正が含まれています。
コミット
commit f284a3ff4d525da4fb1dff6580588cabdbeab423
Author: Ian Lance Taylor <iant@golang.org>
Date: Thu Nov 1 11:13:50 2012 -0700
cmd/go: fixes to gccgo support
* Use -fgo-pkgpath and -gccgopkgpath rather than -fgo-prefix
and -gccgoprefix.
* Define GOPKGPATH when compiling .c or .s files for gccgo.
* Use -fgo-relative-import-path.
* Produce .o files for gccgo, not .[568] files.
* Pass -E when linking if using cgo.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6820064
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/f284a3ff4d525da4fb1dff6580588cabdbeab423
元コミット内容
cmd/go
ツールにおける gccgo
サポートの修正。
-fgo-prefix
および-gccgoprefix
の代わりに-fgo-pkgpath
および-gccgopkgpath
を使用する。gccgo
用に.c
または.s
ファイルをコンパイルする際にGOPKGPATH
を定義する。-fgo-relative-import-path
を使用する。gccgo
用に.[568]
ファイルではなく.o
ファイルを生成する。cgo
を使用している場合、リンク時に-E
を渡す。
変更の背景
このコミットは、Go言語の公式ビルドツールである cmd/go
が、代替コンパイラである gccgo
を使用する際の互換性と機能性を向上させるために行われました。
Go言語には主に2つのコンパイラ実装があります。一つは公式のGoコンパイラ(通称 gc
または cmd/compile
)で、もう一つはGCCのフロントエンドとして実装された gccgo
です。cmd/go
ツールは、デフォルトでは gc
を使用しますが、gccgo
を使用するように設定することも可能です。
このコミット以前は、cmd/go
が gccgo
を利用する際にいくつかの不整合や機能不足がありました。具体的には、以下のような問題が考えられます。
- フラグ名の不一致:
gccgo
が期待するパッケージパス関連のフラグ名と、cmd/go
が生成していたフラグ名が異なっていた可能性があります。これにより、gccgo
がパッケージパスを正しく認識できない問題が発生していました。 - C/アセンブリコードとの連携不足:
gccgo
でビルドする際に、Goのパッケージパス情報がCやアセンブリのソースコードに適切に渡されていなかったため、これらの言語で書かれた部分がGoのパッケージ構造を認識できない可能性がありました。 - オブジェクトファイル形式の不統一:
gc
コンパイラは、ターゲットアーキテクチャに応じて.5
(ARM),.6
(x86-64),.8
(x86) といった独自のオブジェクトファイル拡張子を使用します。しかし、gccgo
は標準的なGCCのツールチェーンの一部であるため、通常は.o
拡張子を使用します。この不一致がビルドシステム内で混乱を招いたり、他のGCCツールとの連携を妨げたりする可能性がありました。 - Cgoと動的リンクの問題:
cgo
を使用してC/C++コードをGoプログラムに組み込む場合、特にLinuxのようなシステムでは、動的リンク時のシンボル解決に特定のリンカフラグが必要となることがあります。このフラグが不足していると、実行時にリンクエラーが発生する可能性がありました。
これらの問題を解決し、cmd/go
と gccgo
の間の連携をより堅牢で標準的なものにすることが、このコミットの主な背景です。
前提知識の解説
Go言語のビルドシステム (cmd/go
)
cmd/go
は、Go言語のソースコードをビルド、テスト、インストール、管理するための公式コマンドラインツールです。Goのワークスペース、モジュール、パッケージの概念を理解し、依存関係の解決、コンパイル、アセンブル、リンクといった一連のビルドプロセスを自動化します。
cmd/go
は内部的に、Goコンパイラ (gc
)、アセンブラ (go tool asm
)、リンカ (go tool link
) などのツールを呼び出して実行します。
gccgo
gccgo
は、Go言語のプログラムをGCC (GNU Compiler Collection) のフロントエンドとしてコンパイルするツールチェーンです。標準のGoコンパイラ (gc
) とは独立して開発されており、GCCの最適化や既存のC/C++ライブラリとの連携といったGCCエコシステムの利点を活用できます。gccgo
はGoの仕様に準拠していますが、内部実装や生成されるバイナリの特性は gc
と異なる場合があります。
Cgo
cgo
は、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのツールです。Goのソースファイル内にCのコードを直接記述し、cgo
がGoとCの間のインターフェースコードを生成します。これにより、既存のCライブラリをGoから利用したり、パフォーマンスが重要な部分をCで記述したりすることが可能になります。
パッケージパス (Package Path)
Go言語において、パッケージパスはパッケージの一意な識別子です。例えば、"fmt"
や "github.com/user/repo/mypackage"
のように、通常はインポートパスとして使用されます。コンパイラやリンカは、このパッケージパス情報を使用して、依存関係を解決したり、生成されるバイナリ内でパッケージを識別したりします。
オブジェクトファイル (.o, .5/.6/.8)
オブジェクトファイルは、コンパイラやアセンブラによって生成される中間ファイルで、ソースコードを機械語に変換したものです。まだ完全に実行可能な形式ではなく、他のオブジェクトファイルやライブラリとリンクされて最終的な実行可能ファイルやライブラリになります。
.o
: これはUnix系システムで一般的なオブジェクトファイルの拡張子で、GCCを含む多くのコンパイラが使用します。.5
,.6
,.8
: これらはGoの標準コンパイラ (gc
) が使用する独自のオブジェクトファイル拡張子です。それぞれ、gc
がサポートする異なるアーキテクチャ(例:.5
はARM、.6
はx86-64、.8
はx86)に対応しています。この独自の命名規則は、Goのビルドシステムが特定のアーキテクチャ向けのオブジェクトファイルを識別するために使われていました。
リンカフラグ (-Wl,-E
)
リンカは、複数のオブジェクトファイルやライブラリを結合して最終的な実行可能ファイルを作成するツールです。リンカには様々なオプション(フラグ)を渡すことができ、その挙動を制御します。
-Wl,option
は、GCCなどのコンパイラドライバがリンカに直接 option
を渡すための一般的な構文です。
-Wl,-E
は、特にLinuxシステムにおいて、動的リンカの挙動に影響を与える重要なフラグです。このフラグは、実行可能ファイルがロードされる際に、環境変数 LD_PRELOAD
で指定されたライブラリや、実行可能ファイル自体に埋め込まれた DT_RPATH
や DT_RUNPATH
エントリで指定されたパスを検索対象に含めるようにリンカに指示します。cgo
を使用してGoプログラムがCライブラリに依存する場合、このフラグがないと、実行時に必要なシンボルが見つからずにエラーとなることがあります。
技術的詳細
このコミットで行われた技術的な変更は、cmd/go
が gccgo
ツールチェーンとより密接に、かつ標準的な方法で連携できるようにするためのものです。
-
フラグ名の統一 (
-fgo-prefix
->-fgo-pkgpath
):- 以前は
gccgo
にパッケージパスを渡す際に-fgo-prefix
というフラグが使われていましたが、これはgccgo
の内部的な命名規則や他のGCCフロントエンドとの整合性を考慮して-fgo-pkgpath
に変更されました。この変更は、gccgo
コンパイラ (gc
メソッド内) とcgo
ツール (cgo
メソッド内) の両方に適用されています。 gccgoPrefix
関数は削除され、より汎用的なgccgoPkgpath
関数が導入されました。gccgoPkgpath
は、コマンドではないパッケージや強制的にライブラリとして扱われるパッケージに対してはp.ImportPath
をそのまま返し、それ以外の場合は空文字列を返します。これにより、パッケージパスの概念がより直接的にgccgo
に伝わるようになります。
- 以前は
-
GOPKGPATH
マクロの定義:gccgo
で.c
または.s
(Cまたはアセンブリ) ファイルをコンパイルする際、プリプロセッサマクロGOPKGPATH
が定義されるようになりました。このマクロの値は、Goのパッケージパスをサニタイズ(非英数字をアンダースコアに変換)したものです。- これは
gccgcToolchain.asm
およびgccgcToolchain.cc
メソッドで行われます。Cやアセンブリのコード内で#ifdef GOPKGPATH
のような形でこのマクロを利用することで、Goのパッケージパスに基づいて条件付きコンパイルを行ったり、デバッグ情報を埋め込んだりすることが可能になります。これにより、GoとC/アセンブリの間の連携が強化されます。
-
相対インポートパスのサポート (
-fgo-relative-import-path
):gccgcToolchain.gc
メソッドにおいて、パッケージにp.localPrefix
が設定されている場合、-fgo-relative-import-path
フラグがgccgo
に渡されるようになりました。これは、Goモジュール内で相対的なインポートパスが使用されるシナリオに対応するためのものです。gccgo
がこれらの相対パスを正しく解決できるようになり、より複雑なプロジェクト構造をサポートします。
-
オブジェクトファイル拡張子の統一 (
.[568]
->.o
):cmd/go
は、gccgo
を使用する場合、C (.c
) およびアセンブリ (.s
) ファイルのコンパイル結果として、Goの標準コンパイラが使用する.5
,.6
,.8
ではなく、標準的な.o
拡張子のオブジェクトファイルを生成するようになりました。- これは
build.go
のobjExt
変数の設定と、cc
およびasm
メソッドの出力ファイル名生成ロジックの変更によって実現されています。この変更により、gccgo
が生成するオブジェクトファイルが他のGCCツールや標準的なビルドシステムと互換性を持つようになり、ビルドプロセスの整合性が向上します。
-
リンカの
-E
フラグの追加:gccgcToolchain.ld
メソッドにおいて、cgo
ファイルが使用されている (usesCgo
が true) かつOSがLinux (goos == "linux"
) の場合、リンカに-Wl,-E
フラグが渡されるようになりました。- このフラグは、特にLinux環境で
cgo
を介して動的にリンクされるCライブラリのシンボル解決を助けます。これにより、cgo
を使用したGoプログラムが、実行時に必要な共有ライブラリを正しく見つけられるようになり、リンクエラーや実行時エラーのリスクが低減されます。
-
gccgoCleanPkgpath
関数の導入:- 新しいヘルパー関数
gccgoCleanPkgpath
が追加されました。この関数は、gccgoPkgpath
から得られたパッケージパスを受け取り、英数字以外の文字をアンダースコア (_
) に置換します。これは、パッケージパスをCプリプロセッサマクロ (-D
) の値として安全に使用できるようにするためです。マクロ名やその値には特定の文字しか使用できないため、このサニタイズ処理は必須です。
- 新しいヘルパー関数
これらの変更は、cmd/go
が gccgo
をバックエンドとして使用する際のビルドの信頼性、互換性、および機能性を大幅に向上させるものです。
コアとなるコードの変更箇所
変更は主に src/cmd/go/build.go
ファイルに集中しています。
-
オブジェクトファイル拡張子の決定ロジックの変更 (L745-760):
--- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -745,8 +745,13 @@ func (b *builder) build(a *action) (err error) { } } + objExt := archChar + if _, ok := buildToolchain.(gccgcToolchain); ok { + objExt = "o" + } + for _, file := range cfiles { - out := file[:len(file)-len(".c")] + "." + archChar + out := file[:len(file)-len(".c")] + "." + objExt if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil { return err } @@ -755,7 +760,7 @@ func (b *builder) build(a *action) (err error) { // Assemble .s files. for _, file := range sfiles { - out := file[:len(file)-len(".s")] + "." + archChar + out := file[:len(file)-len(".s")] + "." + objExt if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil { return err }
gccgcToolchain
を使用する場合、オブジェクトファイルの拡張子をarchChar
(例:5
,6
,8
) から"o"
に変更。 -
gccgcToolchain.gc
(Goコンパイラ) のフラグ変更 (L1355-1364):--- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -1355,8 +1360,11 @@ func (gccgcToolchain) gc(b *builder, p *Package, obj string, importArgs []string out := p.Name + ".o" ofile = obj + out gcargs := []string{"-g"} - if prefix := gccgoPrefix(p); prefix != "" { - gcargs = append(gcargs, "-fgo-prefix="+gccgoPrefix(p)) + if pkgpath := gccgoPkgpath(p); pkgpath != "" { + gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath) + } + if p.localPrefix != "" { + gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix) } args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags) for _, f := range gofiles {
-fgo-prefix
を-fgo-pkgpath
に変更し、p.localPrefix
があれば-fgo-relative-import-path
を追加。 -
gccgcToolchain.asm
(アセンブラ) でのGOPKGPATH
定義 (L1367-1373):--- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -1367,7 +1375,11 @@ func (gccgcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { func (gccgcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { sfile = mkAbs(p.Dir, sfile) return b.run(p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile, "-DGOOS_"+goos, "-DGOARCH_"+goarch, sfile) + defs := []string{"-DGOOS_" + goos, "-DGOARCH_" + goarch} + if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { + defs = append(defs, `-DGOPKGPATH="`+pkgpath+`"`)\n+ } + return b.run(p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile, defs, sfile) }
.s
ファイルコンパイル時にGOPKGPATH
マクロを定義。 -
gccgcToolchain.ld
(リンカ) でのcgo
検出と-E
フラグ追加 (L1392-1433):--- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -1392,6 +1404,7 @@ func (tools gccgcToolchain) ld(b *builder, p *Package, out string, allactions [] sfiles := make(map[*Package][]string) ldflags := []string{} cgoldflags := []string{} + usesCgo := false for _, a := range allactions { if a.p != nil { if !a.p.Standard { @@ -1400,12 +1413,16 @@ func (tools gccgcToolchain) ld(b *builder, p *Package, out string, allactions [] } } cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...) + if len(a.p.CgoFiles) > 0 { + usesCgo = true + } if a.p.usesSwig() { sd := a.p.swigDir(&buildContext) for _, f := range stringList(a.p.SwigFiles, a.p.SwigCXXFiles) { soname := a.p.swigSoname(f) sfiles[a.p] = append(sfiles[a.p], filepath.Join(sd, soname)) } + usesCgo = true } } } @@ -1416,25 +1433,40 @@ func (tools gccgcToolchain) ld(b *builder, p *Package, out string, allactions [] ldflags = append(ldflags, sfiles...) } ldflags = append(ldflags, cgoldflags...) + if usesCgo && goos == "linux" { + ldflags = append(ldflags, "-Wl,-E") + } return b.run(".", p.ImportPath, "gccgo", "-o", out, buildGccgoflags, ofiles, "-Wl,-(", ldflags, "-Wl,)") }
usesCgo
フラグを導入し、cgo
またはswig
が使用され、かつLinuxの場合にリンカに-Wl,-E
を追加。 -
gccgcToolchain.cc
(Cコンパイラ) でのGOPKGPATH
定義 (L1435-1444):--- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -1435,8 +1444,11 @@ func (tools gccgcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { func (gccgcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) cfile = mkAbs(p.Dir, cfile) + defs := []string{"-DGOOS_" + goos, "-DGOARCH_" + goarch} + if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { + defs = append(defs, `-DGOPKGPATH="`+pkgpath+`"`)\n+ } return b.run(p.Dir, p.ImportPath, "gcc", "-Wall", "-g", - "-I", objdir, "-I", inc, "-o", ofile, - "-DGOOS_"+goos, "-DGOARCH_"+goarch, "-c", cfile) + "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) }
.c
ファイルコンパイル時にGOPKGPATH
マクロを定義。 -
gccgoPrefix
の削除とgccgoPkgpath
,gccgoCleanPkgpath
の追加 (L1446-1466):--- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -1446,14 +1455,23 @@ func (gccgcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { return b.run(p.Dir, p.ImportPath, "gcc", "-Wall", "-g", "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) } -func gccgoPrefix(p *Package) string { - switch { - case p.build.IsCommand() && !p.forceLibrary: +func gccgoPkgpath(p *Package) string { + if p.build.IsCommand() && !p.forceLibrary { return "" - case p.fake: - return "fake_" + p.ImportPath } - return "go_" + p.ImportPath + return p.ImportPath +} + +func gccgoCleanPkgpath(p *Package) string { + clean := func(r rune) rune { + switch { + case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', + '0' <= r && r <= '9': + return r + } + return '_' + } + return strings.Map(clean, gccgoPkgpath(p)) } // libgcc returns the filename for libgcc, as determined by invoking gcc with
gccgoPrefix
関数を削除し、gccgoPkgpath
とgccgoCleanPkgpath
を新しく定義。 -
builder.cgo
でのフラグ変更とオブジェクト拡張子設定 (L1563-1570):--- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -1563,8 +1595,8 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,\ if _, ok := buildToolchain.(gccgcToolchain); ok { cgoflags = append(cgoflags, "-gccgo") - if prefix := gccgoPrefix(p); prefix != "" { - cgoflags = append(cgoflags, "-gccgoprefix="+gccgoPrefix(p)) + if pkgpath := gccgoPkgpath(p); pkgpath != "" { + cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath) } objExt = "o" }
-gccgoprefix
を-gccgopkgpath
に変更し、objExt
を"o"
に設定。
コアとなるコードの解説
オブジェクトファイル拡張子の統一
objExt := archChar
if _, ok := buildToolchain.(gccgcToolchain); ok {
objExt = "o"
}
// ...
out := file[:len(file)-len(".c")] + "." + objExt
// ...
out := file[:len(file)-len(".s")] + "." + objExt
この変更は、cmd/go
が gccgo
ツールチェーンを使用しているかどうかを buildToolchain.(gccgcToolchain)
で確認し、もし gccgo
であれば、C (.c
) およびアセンブリ (.s
) ファイルから生成されるオブジェクトファイルの拡張子を標準的な .o
に設定します。Goの標準コンパイラ (gc
) はアーキテクチャ固有の拡張子(例: .5
, .6
, .8
)を使用しますが、gccgo
はGCCの慣習に従うため、この統一は互換性にとって重要です。
gccgcToolchain.gc
(Goコンパイラ) のフラグ変更
if pkgpath := gccgoPkgpath(p); pkgpath != "" {
gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath)
}
if p.localPrefix != "" {
gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix)
}
gccgo
コンパイラを呼び出す際に渡す引数 (gcargs
) が変更されました。
gccgoPkgpath(p)
は、パッケージのインポートパスを返します。これが空でなければ、-fgo-pkgpath=
フラグが追加されます。これは、gccgo
がGoのパッケージパスを正しく認識し、内部的なシンボル名や依存関係の解決に利用できるようにするためです。以前の-fgo-prefix
よりも、その意図が明確になりました。p.localPrefix
は、Goモジュールにおける相対的なインポートパスのプレフィックスを示す可能性があります。これが存在する場合、-fgo-relative-import-path=
フラグが追加され、gccgo
が相対インポートを適切に処理できるようになります。
gccgcToolchain.asm
および gccgcToolchain.cc
での GOPKGPATH
定義
defs := []string{"-DGOOS_" + goos, "-DGOARCH_" + goarch}
if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
defs = append(defs, `-DGOPKGPATH="`+pkgpath+`"`)
}
return b.run(p.Dir, p.ImportPath, "gccgo", /* ... */, defs, sfile) // for .s files
// ...
return b.run(p.Dir, p.ImportPath, "gcc", /* ... */, defs, "-c", cfile) // for .c files
アセンブリ (.s
) およびC (.c
) ファイルをコンパイルする際、gccgoCleanPkgpath(p)
でサニタイズされたGoのパッケージパスが、プリプロセッサマクロ GOPKGPATH
として定義されます。例えば、パッケージパスが "github.com/foo/bar"
であれば、GOPKGPATH
は "github_com_foo_bar"
のような値になります。これにより、Cやアセンブリのソースコード内で #ifdef GOPKGPATH
や GOPKGPATH
の値を利用して、Goのパッケージ情報に基づいた処理を行うことが可能になります。これは、GoとC/アセンブリの間のより深い連携を可能にします。
gccgcToolchain.ld
(リンカ) での cgo
検出と -E
フラグ追加
usesCgo := false
// ...
if len(a.p.CgoFiles) > 0 {
usesCgo = true
}
// ...
if a.p.usesSwig() {
// ...
usesCgo = true
}
// ...
if usesCgo && goos == "linux" {
ldflags = append(ldflags, "-Wl,-E")
}
このセクションでは、ビルド対象のパッケージが cgo
ファイル (a.p.CgoFiles
) を含んでいるか、または swig
を使用しているか (a.p.usesSwig()
) を usesCgo
フラグで追跡します。
もし cgo
または swig
が使用されており、かつオペレーティングシステムがLinuxである場合、リンカに -Wl,-E
フラグが追加されます。このフラグは、Linuxの動的リンカに対して、実行可能ファイルがロードされる際に環境変数 LD_PRELOAD
や DT_RPATH
/DT_RUNPATH
で指定されたパスを検索対象に含めるように指示します。これは、cgo
を使用してGoプログラムがCの共有ライブラリに依存する場合に、実行時のシンボル解決を確実に行うために非常に重要です。
gccgoPkgpath
および gccgoCleanPkgpath
関数の導入
func gccgoPkgpath(p *Package) string {
if p.build.IsCommand() && !p.forceLibrary {
return ""
}
return p.ImportPath
}
func gccgoCleanPkgpath(p *Package) string {
clean := func(r rune) rune {
switch {
case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
'0' <= r && r <= '9':
return r
}
return '_'
}
return strings.Map(clean, gccgoPkgpath(p))
}
gccgoPkgpath
は、与えられたGoパッケージp
のインポートパスを返します。ただし、それがコマンドであり、かつ強制的にライブラリとして扱われていない場合は空文字列を返します。これは、実行可能ファイル自体には特定のパッケージパスが不要であるというgccgo
のセマンティクスに合わせたものです。gccgoCleanPkgpath
は、gccgoPkgpath
から得られた文字列を受け取り、それを「クリーン」にします。具体的には、英数字以外のすべての文字をアンダースコア (_
) に置換します。この関数は、パッケージパスをCプリプロセッサマクロ (-D
フラグで渡される値) の一部として使用する際に必要です。Cプリプロセッサマクロの名前や値には、特定の文字セットしか使用できないため、このサニタイズ処理が不可欠です。
builder.cgo
でのフラグ変更とオブジェクト拡張子設定
if _, ok := buildToolchain.(gccgcToolchain); ok {
cgoflags = append(cgoflags, "-gccgo")
if pkgpath := gccgoPkgpath(p); pkgpath != "" {
cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath)
}
objExt = "o"
}
cgo
ツールを呼び出す際にも、gccgo
ツールチェーンが使用されている場合は、-gccgo
フラグが追加されます。また、gccgoPkgpath
から得られたパッケージパスが空でなければ、-gccgopkgpath=
フラグが追加されます。これは、cgo
が gccgo
と連携してGoとCの間のバインディングを生成する際に、正しいパッケージパス情報を利用できるようにするためです。さらに、cgo
が生成するオブジェクトファイルの拡張子も .o
に設定されます。
これらの変更は、cmd/go
が gccgo
を利用する際のビルドプロセス全体にわたる整合性を高め、より堅牢で標準的なGoプログラムのビルドを可能にしています。
関連リンク
- https://golang.org/cl/6820064 (Gerrit Code Review)
参考にした情報源リンク
- Go言語公式ドキュメント (Go Command, cgo, build modesなど)
- GCCgo ドキュメント (特にコマンドラインオプションに関する情報)
- Linux man pages (ld, gccなど)
- Go言語のソースコード (特に
src/cmd/go
ディレクトリ) - Go言語のビルドシステムについて (一般的なGoのビルドに関する情報)
- GCCgoの概要 (GCCgoに関する公式ドキュメント)
- Cgoのドキュメント (Cgoに関する公式ブログ記事)
- Linuxの動的リンカに関する情報 (ld.so man page)
- GCCのリンカオプションに関する情報 (GCC Link Options)