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

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

このコミットは、Go言語のツールチェインにおいて、cgo (C言語との相互運用を可能にするツール) がgccgo (GCCベースのGoコンパイラ) と連携する際の機能強化とバグ修正を目的としています。具体的には、gccgoでコンパイルされたGo関数をC言語からエクスポートして呼び出す機能の追加と、go testコマンドがpackage mainのテストをgccgoで実行する際の問題を解決しています。

コミット

commit 3211b2cca98936e94dc2e819dbe474337ecdd24e
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date:   Thu Mar 15 23:50:25 2012 +0100

    cmd/cgo: add support for function export for gccgo.
    
    A "gccgoprefix" flag is added and used by the go tool,
    to mirror the -fgo-prefix flag for gccgo, whose value
    is required to know how to access functions from C.
    
    Trying to export Go methods or unexported Go functions
    will not work.
    
    Also fix go test on "main" packages.
    
    Updates #2313.
    Fixes #3262.
    
    R=mpimenov, rsc, iant
    CC=golang-dev
    https://golang.org/cl/5797046

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

https://github.com/golang/go/commit/3211b2cca98936e94dc2e819dbe474337ecdd24e

元コミット内容

cmd/cgo: gccgo向けにGo関数のエクスポートをサポートする機能を追加。

go toolによって使用される"gccgoprefix"フラグが追加され、gccgo-fgo-prefixフラグをミラーリングします。この値は、C言語からGo関数にアクセスする方法を知るために必要です。

GoのメソッドやエクスポートされていないGo関数をエクスポートしようとしても機能しません。

また、"main"パッケージに対するgo testの修正も行います。

Issue #2313 を更新。 Issue #3262 を修正。

変更の背景

このコミットは、Go言語のツールチェインにおけるcgogccgoの連携を改善するという、より大きな目標の一部です。

  1. cgogccgoの互換性向上 (Issue #2313): 従来のGoコンパイラ(gc)とcgoの組み合わせでは、Go関数をC言語から呼び出す(エクスポートする)機能が提供されていました。しかし、gccgoは異なるコンパイルモデルとシンボル命名規則を持つため、この機能が直接利用できませんでした。Issue #2313は、cgogccgo環境でも同様の機能を提供できるようにするための包括的な課題でした。このコミットは、その課題に対する具体的な解決策の一つとして、gccgoにおけるGo関数のエクスポート機能を追加しています。これにより、gccgoを使用する開発者も、C言語とのより深い相互運用性を享受できるようになります。

  2. go testgccgopackage main問題の解決 (Issue #3262): go testコマンドは、テスト対象のパッケージがpackage mainである場合に、特定の挙動を示します。gccgopackage mainのテストをコンパイル・実行する際に、内部的なリンケージやシンボル解決の問題が発生していました。Issue #3262は、この特定のシナリオにおけるgo testの不具合を報告しており、このコミットはその問題を修正することで、gccgo環境でのテストの信頼性を向上させています。

これらの変更は、Go言語のツールチェインが多様なコンパイラ環境(特にgccgo)においても一貫した機能と安定性を提供できるようにするための重要なステップです。

前提知識の解説

このコミットを理解するためには、以下の概念が重要です。

  • Go言語のcgo:

    • cgoは、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGoツールです。GoとCの間の橋渡しをします。
    • Goのソースファイル内にimport "C"という行を記述し、その後にCのコードを直接埋め込むことで、Cの関数をGoから呼び出したり、Goの関数をCから呼び出せるようにエクスポートしたりできます。
    • cgoは、GoとCの間の型変換やメモリ管理の調整を行います。
  • gcgccgo:

    • gc: Go言語の公式コンパイラであり、通常go buildコマンドで使用されるデフォルトのコンパイラです。Goのソースコードを直接機械語にコンパイルします。
    • gccgo: GCC (GNU Compiler Collection) のフロントエンドとして実装されたGoコンパイラです。gcとは異なるコンパイルバックエンドを使用し、GCCの最適化やリンケージ機能を利用できます。これにより、既存のC/C++ライブラリとの連携が容易になる場合がありますが、gcとは異なる挙動を示すこともあります。
  • シンボルとリンケージ:

    • コンパイルされたプログラムでは、関数や変数などの実体は「シンボル」として表現されます。
    • 異なるコンパイル単位(例: GoのオブジェクトファイルとCのオブジェクトファイル)間でシンボルを参照する場合、リンカがそれらを解決(リンケージ)する必要があります。
    • gccgoは、Goの関数シンボルに特定のプレフィックス(例: go_fake_)を付与することがあり、C言語からこれらの関数を呼び出す際には、このプレフィックスを考慮する必要があります。
  • package mainと実行可能ファイル:

    • Go言語において、package mainは実行可能プログラムのエントリポイント(main関数)を含むパッケージを指します。
    • 通常、go buildpackage mainをビルドすると、単一の実行可能ファイルが生成されます。
    • テストにおいては、go testコマンドはテスト対象のパッケージをコンパイルし、テスト用の実行可能ファイルを生成します。package mainのテストは、通常のライブラリパッケージのテストとは異なるリンケージの考慮が必要になる場合があります。
  • Go関数のエクスポート:

    • Goの関数をC言語から呼び出すには、その関数がGo側でエクスポートされている必要があります(関数名が大文字で始まる)。
    • cgoは、エクスポートされたGo関数に対応するCのヘッダファイルとスタブコードを生成し、CコードがGo関数を呼び出せるようにします。

技術的詳細

このコミットの技術的詳細は、主にcgoツールとgoコマンドがgccgo環境でGo関数をCにエクスポートする際の挙動を調整することにあります。

  1. gccgoprefixフラグの導入:

    • src/cmd/cgo/main.go-gccgoprefixという新しいフラグが追加されました。このフラグは、gccgoが生成するGoシンボルのプレフィックスを指定するために使用されます。デフォルト値は"go"です。
    • gccgoは、Goの関数をコンパイルする際に、そのシンボル名に特定のプレフィックスを付与します(例: go_pkgname.FuncName)。C言語からこれらの関数を呼び出すためには、C側でこのプレフィックスを含んだ正しいシンボル名を参照する必要があります。
    • このフラグは、goコマンドがcgoを呼び出す際に、gccgo-fgo-prefixフラグと連携して使用されます。
  2. writeGccgoExports関数の実装:

    • src/cmd/cgo/out.gowriteGccgoExportsという新しい関数が追加されました。この関数は、gccgoを使用する場合にGo関数をCにエクスポートするためのCヘッダファイル(_cgo_export.h)とCソースファイル(_cgo_export.c)を生成します。
    • この関数は、エクスポートされるGo関数の名前、引数、戻り値の型を解析し、対応するCの関数宣言を生成します。
    • 特に重要なのは、生成されるCの関数宣言に__asm__属性を使用して、gccgoが生成する実際のGoシンボル名(gccgoSymbolPrefix.PackageName.FuncNameの形式)をリンカに伝える点です。これにより、CコードがGo関数を正しいシンボル名で参照できるようになります。
    • 複数の戻り値を持つGo関数については、C側で対応する構造体(struct { ... }_result)を定義し、その構造体を戻り値とするC関数としてエクスポートするロジックが実装されています。
    • GoのメソッドやエクスポートされていないGo関数は、gccgoではエクスポートできないという制約がコードに反映されています(fatalf("cannot export unexported function %s with gccgo", fn.Name))。
  3. goコマンドのビルドロジックの変更:

    • src/cmd/go/build.goにおいて、gccgcToolchaingccgoを使用するツールチェイン)のビルドロジックが更新されました。
    • gc関数(Goソースをコンパイルする部分)では、gccgoPrefixヘルパー関数が導入され、パッケージの種類(mainパッケージかライブラリか、fakeパッケージか)に応じて適切な-fgo-prefixフラグがgccgoに渡されるようになりました。これにより、gccgoが生成するシンボル名が適切に制御されます。
    • cgo関数(cgoツールを呼び出す部分)では、gccgoツールチェインが使用されている場合に、新しく追加された-gccgoフラグと-gccgoprefixフラグがcgoツールに渡されるようになりました。これにより、cgogccgo向けの特別なエクスポート処理を実行するようになります。
  4. go testpackage main修正:

    • src/cmd/go/pkg.goforceLibraryという新しいフィールドがPackage構造体に追加されました。これは、たとえパッケージ名が"main"であっても、そのパッケージをライブラリとして扱うべきかどうかを示すフラグです。
    • src/cmd/go/test.goにおいて、テスト用の合成パッケージ(ptest)を準備する際に、ptest.forceLibrary = trueが設定されるようになりました。これにより、go testpackage mainのテストをビルドする際に、そのテストパッケージがライブラリとして扱われ、gccgoでのリンケージ問題が回避されます。
    • また、テストのメイン実行ファイルとなる合成パッケージのbuild.PackageNameフィールドが"main"に設定されるようになりました。これは、go testが最終的に実行可能ファイルを生成する際の整合性を保つためです。

これらの変更により、cgogccgo環境でGo関数をCにエクスポートする機能を獲得し、go testgccgopackage mainの組み合わせで安定して動作するようになりました。

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

このコミットにおける主要なコード変更は以下のファイルに集中しています。

  1. src/cmd/cgo/main.go:

    --- a/src/cmd/cgo/main.go
    +++ b/src/cmd/cgo/main.go
    @@ -136,6 +136,7 @@ var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C
     var objDir = flag.String("objdir", "", "object directory")
     
     var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
    +var gccgoprefix = flag.String("gccgoprefix", "go", "prefix of symbols generated by gccgo")
     var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code")
     var goarch, goos string
    
    • gccgoprefixという新しいコマンドラインフラグが追加されました。
  2. src/cmd/cgo/out.go:

    --- a/src/cmd/cgo/out.go
    +++ b/src/cmd/cgo/out.go
    @@ -107,7 +107,11 @@ func (p *Package) writeDefs() {
     		}
     	}
     
    -	p.writeExports(fgo2, fc, fm)
    +	if *gccgo {
    +		p.writeGccgoExports(fgo2, fc, fm)
    +	} else {
    +		p.writeExports(fgo2, fc, fm)
    +	}
     
     	fgo2.Close()
     	fc.Close()
    @@ -624,6 +628,83 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
     	}
     }
     
    +// Write out the C header allowing C code to call exported gccgo functions.
    +func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
    +	fgcc := creat(*objDir + "_cgo_export.c")
    +	fgcch := creat(*objDir + "_cgo_export.h")
    +	_ = fgcc
    +
    +	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\\n")
    +	fmt.Fprintf(fgcch, "%s\\n", p.Preamble)
    +	fmt.Fprintf(fgcch, "%s\\n", gccExportHeaderProlog)
    +	fmt.Fprintf(fm, "#include \\\"_cgo_export.h\\\"\\n")
    +
    +	clean := func(r rune) rune {
    +		switch {
    +		case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
    +			'0' <= r && r <= '9':
    +			return r
    +		}
    +		return '_'
    +	}
    +	gccgoSymbolPrefix := strings.Map(clean, *gccgoprefix)
    +
    +	for _, exp := range p.ExpFunc {
    +		// TODO: support functions with receivers.
    +		fn := exp.Func
    +		fntype := fn.Type
    +
    +		if !ast.IsExported(fn.Name.Name) {
    +			fatalf("cannot export unexported function %s with gccgo", fn.Name)
    +		}
    +
    +		cdeclBuf := new(bytes.Buffer)
    +		resultCount := 0
    +		forFieldList(fntype.Results,
    +			func(i int, atype ast.Expr) { resultCount++ })
    +		switch resultCount {
    +		case 0:
    +			fmt.Fprintf(cdeclBuf, "void")
    +		case 1:
    +			forFieldList(fntype.Results,
    +				func(i int, atype ast.Expr) {
    +					t := p.cgoType(atype)
    +					fmt.Fprintf(cdeclBuf, "%s", t.C)
    +				})
    +		default:
    +			// Declare a result struct.
    +			fmt.Fprintf(fgcch, "struct %s_result {\\n", exp.ExpName)
    +			forFieldList(fntype.Results,
    +				func(i int, atype ast.Expr) {
    +					t := p.cgoType(atype)
    +					fmt.Fprintf(fgcch, "\\t%s r%d;\\n", t.C, i)
    +				})
    +			fmt.Fprintf(fgcch, "};\\n")
    +			fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName)
    +		}
    +
    +		// The function name.
    +		fmt.Fprintf(cdeclBuf, " "+exp.ExpName)
    +		gccgoSymbol := fmt.Sprintf("%s.%s.%s", gccgoSymbolPrefix, p.PackageName, exp.Func.Name)
    +		fmt.Fprintf(cdeclBuf, " (")
    +		// Function parameters.
    +		forFieldList(fntype.Params,
    +			func(i int, atype ast.Expr) {
    +				if i > 0 {
    +					fmt.Fprintf(cdeclBuf, ", ")
    +				}
    +				t := p.cgoType(atype)
    +				fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i)
    +			})
    +		fmt.Fprintf(cdeclBuf, ")")
    +		cdecl := cdeclBuf.String()
    +
    +		fmt.Fprintf(fgcch, "extern %s __asm__(\\\"%s\\\");\\n", cdecl, gccgoSymbol)
    +		// Dummy declaration for _cgo_main.c
    +		fmt.Fprintf(fm, "%s {}\\n", cdecl)
    +	}
    +}
    +
     // Call a function for each entry in an ast.FieldList, passing the
     // index into the list and the type.
     func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
    
    • gccgoフラグが有効な場合にwriteGccgoExportsを呼び出す条件分岐が追加されました。
    • writeGccgoExports関数が新規追加され、gccgo向けのエクスポートヘッダとスタブコードを生成します。
  3. src/cmd/go/build.go:

    --- a/src/cmd/go/build.go
    +++ b/src/cmd/go/build.go
    @@ -661,7 +661,7 @@ func (b *builder) build(a *action) (err error) {
     		}
     
     		cgoExe := tool("cgo")
    -		if a.cgo != nil {
    +		if a.cgo != nil && a.cgo.target != "" {
     			cgoExe = a.cgo.target
     		}
     		outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles)
    @@ -1239,12 +1239,8 @@ func (gccgcToolchain) gc(b *builder, p *Package, obj string, importArgs []string
     	out := p.Name + ".o"
     	ofile = obj + out
     	gcargs := []string{"-g"}
    -	if p.Name != "main" {
    -		if p.fake {
    -			gcargs = append(gcargs, "-fgo-prefix=fake_"+p.ImportPath)
    -		} else {
    -			gcargs = append(gcargs, "-fgo-prefix=go_"+p.ImportPath)
    -		}
    +	if prefix := gccgoPrefix(p); prefix != "" {
    +		gcargs = append(gcargs, "-fgo-prefix="+gccgoPrefix(p))
     	}
     	args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
     	for _, f := range gofiles {
    @@ -1304,6 +1300,16 @@ func (gccgcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) er
     		"-DGOOS_"+goos, "-DGOARCH_"+goarch, "-c", cfile)
     }
     
    +func gccgoPrefix(p *Package) string {
    +	switch {
    +	case p.build.IsCommand() && !p.forceLibrary:
    +		return ""
    +	case p.fake:
    +		return "fake_" + p.ImportPath
    +	}
    +	return "go_" + p.ImportPath
    +}
    +
     // gcc runs the gcc C compiler to create an object from a single C file.
     func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
     	cfile = mkAbs(p.Dir, cfile)
    @@ -1404,6 +1410,9 @@ 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 err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgoflags, "--", cgoCFLAGS, p.CgoFiles); err != nil {
     		return nil, nil, err
    
    • gccgoPrefixヘルパー関数が追加され、gccgo-fgo-prefixを決定します。
    • gc関数内でgccgoPrefixを使用して-fgo-prefixを渡すように変更されました。
    • cgo関数内でgccgoツールチェインの場合に-gccgo-gccgoprefixフラグをcgoに渡すように変更されました。
  4. src/cmd/go/pkg.go:

    --- a/src/cmd/go/pkg.go
    +++ b/src/cmd/go/pkg.go
    @@ -64,16 +64,17 @@ type Package struct {
     	XTestImports []string `json:",omitempty"` // imports from XTestGoFiles
     
     	// Unexported fields are not part of the public API.
    -	build       *build.Package
    -	pkgdir      string // overrides build.PkgDir
    -	imports     []*Package
    -	deps        []*Package
    -	gofiles     []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
    -	target      string   // installed file for this package (may be executable)
    -	fake        bool     // synthesized package
    -	forceBuild  bool     // this package must be rebuilt
    -	local       bool     // imported via local path (./ or ../)
    -	localPrefix string   // interpret ./ and ../ imports relative to this prefix
    +	build        *build.Package
    +	pkgdir       string // overrides build.PkgDir
    +	imports      []*Package
    +	deps         *Package
    +	gofiles      []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
    +	target       string   // installed file for this package (may be executable)
    +	fake         bool     // synthesized package
    +	forceBuild   bool     // this package must be rebuilt
    +	forceLibrary bool     // this package is a library (even if named "main")
    +	local        bool     // imported via local path (./ or ../)
    +	localPrefix  string   // interpret ./ and ../ imports relative to this prefix
     }
     
     func (p *Package) copyBuild(pp *build.Package) {
    
    • Package構造体にforceLibraryフィールドが追加されました。
  5. src/cmd/go/test.go:

    --- a/src/cmd/go/test.go
    +++ b/src/cmd/go/test.go
    @@ -446,6 +446,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,\
     		ptest.imports = append(append([]*Package{}, p.imports...), imports...)
     		ptest.pkgdir = testDir
     		ptest.fake = true
    +		ptest.forceLibrary = true
     		ptest.Stale = true
     		ptest.build = new(build.Package)
     		*ptest.build = *p.build
    @@ -489,7 +490,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,\
     		ImportPath: "testmain",
     		Root:       p.Root,
     		imports:    []*Package{ptest},
    -		build:      &build.Package{},
    +		build:      &build.Package{Name: "main"},
     		fake:       true,
     		Stale:      true,
     	}
    
    • テストパッケージの準備時にptest.forceLibrary = trueが設定されるようになりました。
    • テストのメイン実行ファイルとなる合成パッケージのbuild.PackageName"main"に設定されるようになりました。

コアとなるコードの解説

src/cmd/cgo/out.gowriteGccgoExports 関数

この関数は、gccgoコンパイラを使用する際に、Goの関数をC言語から呼び出せるようにするためのCヘッダファイル(_cgo_export.h)とCソースファイル(_cgo_export.c)を生成する中心的なロジックを含んでいます。

  1. ファイル生成:

    • _cgo_export.c_cgo_export.hという2つのファイルを作成します。これらはCgoによって生成される中間ファイルであり、CコードがGo関数を呼び出すためのインターフェースを提供します。
  2. シンボルプレフィックスの処理:

    • gccgoprefixフラグ(src/cmd/cgo/main.goで定義)の値を取得し、strings.Map(clean, *gccgoprefix)を使って、シンボル名として安全な形式に変換します。例えば、"go"というプレフィックスはそのまま"go"として使われます。
    • このプレフィックスは、gccgoがGo関数に付与する実際のシンボル名の一部となります。
  3. Go関数のエクスポートループ:

    • p.ExpFunc(エクスポート対象のGo関数リスト)をイテレートします。
    • エクスポート可能チェック: !ast.IsExported(fn.Name.Name)で、Goの関数名が大文字で始まっているか(エクスポートされているか)を確認します。エクスポートされていない関数をgccgoでエクスポートしようとすると、fatalfでエラーを発生させます。これは、Goの言語仕様とgccgoの制約に準拠するためです。
    • Cの関数宣言生成:
      • cdeclBufというbytes.Bufferを使って、Cの関数宣言(戻り値の型、関数名、引数リスト)を構築します。
      • 戻り値の処理:
        • 戻り値がない場合 (resultCount == 0) は、Cのvoid型を使用します。
        • 戻り値が1つの場合 (resultCount == 1) は、そのGoの型に対応するCの型(p.cgoType(atype).C)を使用します。
        • 戻り値が複数ある場合 (resultCount > 1) は、C側で結果を保持するための構造体(例: struct MyFunc_result { ... };)を_cgo_export.hに定義し、その構造体を戻り値とするC関数として宣言します。これは、C言語が複数の戻り値を直接サポートしないためです。
      • 関数名: exp.ExpName(エクスポートされるGo関数の名前)をCの関数名として使用します。
      • gccgoシンボル名: fmt.Sprintf("%s.%s.%s", gccgoSymbolPrefix, p.PackageName, exp.Func.Name)を使って、gccgoが生成する実際のGo関数のシンボル名(例: go.mypackage.MyFunction)を構築します。
      • 引数の処理: Go関数の引数リストをイテレートし、それぞれのGoの型に対応するCの型と仮引数名(例: int p0, char* p1)を生成します。
      • __asm__属性: fmt.Fprintf(fgcch, "extern %s __asm__(\\\"%s\\\");\\n", cdecl, gccgoSymbol)という行が非常に重要です。これはGCCの拡張機能である__asm__属性を使用しており、Cの関数宣言(cdecl)が、実際にはgccgoSymbolという名前のシンボルにリンクされるべきであることをリンカに指示します。これにより、Cコードは通常のC関数呼び出し構文でGo関数を呼び出すことができますが、リンカは内部的にgccgoが生成したGoシンボルに解決します。
      • ダミー宣言: fmt.Fprintf(fm, "%s {}\\n", cdecl)は、_cgo_main.c(Cgoが生成する別のCソースファイル)内で、エクスポートされたGo関数のダミー宣言を提供します。これは、リンケージの目的で必要となる場合があります。

このwriteGccgoExports関数は、gccgoのシンボル命名規則とC言語のリンケージメカニズムの間のギャップを埋めることで、GoとCのシームレスな相互運用性を実現しています。

src/cmd/go/build.gogccgoPrefix 関数

このヘルパー関数は、特定のGoパッケージに対してgccgoが使用すべきシンボルプレフィックスを決定します。

func gccgoPrefix(p *Package) string {
	switch {
	case p.build.IsCommand() && !p.forceLibrary:
		return ""
	case p.fake:
		return "fake_" + p.ImportPath
	}
	return "go_" + p.ImportPath
}
  • package mainの扱い: p.build.IsCommand()は、パッケージが実行可能ファイル(package main)であるかどうかをチェックします。!p.forceLibraryは、そのパッケージが強制的にライブラリとして扱われるべきではないことを確認します。これらの条件が真の場合、プレフィックスは空文字列""を返します。これは、実行可能ファイルのメインパッケージのシンボルには特別なプレフィックスが不要な場合があるためです。
  • fakeパッケージの扱い: p.fakeは、パッケージがテストなどで一時的に生成された「偽の」パッケージである場合に真となります。この場合、"fake_"というプレフィックスがImportPathに付与されます。
  • 通常のライブラリパッケージ: 上記のいずれにも該当しない場合(通常のライブラリパッケージ)、"go_"というプレフィックスがImportPathに付与されます。

この関数は、goコマンドがgccgoを呼び出す際に、-fgo-prefixフラグに渡す値を動的に決定するために使用されます。これにより、gccgoが生成するGoシンボル名が、パッケージの種類に応じて適切に設定され、リンケージの問題が回避されます。

関連リンク

参考にした情報源リンク