[インデックス 13143] ファイルの概要
このコミットは、Go言語の公式リポジトリにおける cmd/api
ツールに関連するものです。cmd/api
は、Goの標準ライブラリのAPIサーフェスを検査し、互換性のない変更がないかを確認するために使用されるコマンドラインツールです。具体的には、goapi.go
ファイルがこのツールの主要なロジックを含んでいます。このファイルは、異なるビルドコンテキスト(オペレーティングシステム、アーキテクチャ、Cgoの有効/無効など)におけるGoパッケージのAPIを分析し、APIの変更点を追跡する役割を担っています。
コミット
commit f430d0e6096093c9b21b05c48acabe4ab15f87cd
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Wed May 23 13:45:53 2012 -0700
cmd/api: add flag to specify contexts
I needed this to explore per-GOOS/GOARCH differences in pkg
syscall for a recent CL. Others may find it useful too.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6236046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/f430d0e6096093c9b21b05c48acabe4ab15f87cd
元コミット内容
cmd/api: add flag to specify contexts
I needed this to explore per-GOOS/GOARCH differences in pkg
syscall for a recent CL. Others may find it useful too.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6236046
変更の背景
この変更は、cmd/api
ツールに新しいコマンドラインフラグ -contexts
を追加するものです。コミットメッセージによると、作者のBrad Fitzpatrick氏は、pkg syscall
の特定の変更セット(CL: Change List)において、異なる GOOS
(オペレーティングシステム)と GOARCH
(アーキテクチャ)の組み合わせによるAPIの違いを調査する必要がありました。
cmd/api
ツールは、デフォルトで複数のビルドコンテキスト(例: Linux/386, Windows/amd64など)を考慮してAPIを分析します。しかし、特定のOS/アーキテクチャの組み合わせに限定して分析を行いたい場合や、デフォルトで含まれていない特定のコンテキストでAPIを検査したい場合に、既存の機能では対応できませんでした。
この新しいフラグ -contexts
を導入することで、ユーザーはカンマ区切りの <goos>-<goarch>[-cgo]
形式で任意のビルドコンテキストを指定できるようになります。これにより、より柔軟かつ詳細なAPI分析が可能となり、特定の環境におけるAPIの挙動や互換性の問題を効率的に特定できるようになります。作者は、この機能が自分だけでなく、他の開発者にとっても有用であると考えています。
前提知識の解説
cmd/api
ツール
cmd/api
はGo言語のツールチェインの一部であり、Goの標準ライブラリのAPIサーフェスを検査するために使用されます。その主な目的は、Goのリリース間でAPIの互換性が維持されていることを確認することです。このツールは、Goのソースコードを解析し、エクスポートされた型、関数、メソッド、変数などのAPI要素を抽出し、それらを以前のバージョンのAPIと比較します。これにより、意図しないAPIの変更(特に破壊的変更)を検出することができます。
GOOS
と GOARCH
GOOS
(Go Operating System) と GOARCH
(Go Architecture) は、Goのビルドシステムで使用される環境変数です。これらは、GoプログラムがコンパイルされるターゲットのオペレーティングシステムとCPUアーキテクチャを指定します。
GOOS
:linux
,windows
,darwin
(macOS),freebsd
,android
,ios
など。GOARCH
:amd64
,386
,arm
,arm64
,ppc64
,s390x
など。
Goのソースコードには、これらの環境変数に基づいて条件付きでコンパイルされる部分(ビルドタグやファイル名サフィックスなど)が存在します。これにより、特定のOSやアーキテクチャに特化したコードを記述し、クロスプラットフォーム対応を実現しています。
build.Context
Goの go/build
パッケージには Context
という構造体があります。これは、Goのビルドプロセスにおける環境設定をカプセル化するものです。Context
構造体には、GOOS
, GOARCH
, CgoEnabled
(Cgoが有効かどうか), Compiler
(使用するコンパイラ) などのフィールドが含まれています。cmd/api
ツールは、この build.Context
のインスタンスを使用して、異なるターゲット環境でのAPIをシミュレートし、分析します。
cgo
cgo
は、GoプログラムからC言語のコードを呼び出すためのGoの機能です。CgoEnabled
フラグは、特定のビルドコンテキストで cgo
が有効になっているかどうかを示します。cgo
を使用するGoパッケージは、cgo
が無効な環境ではコンパイルできないか、異なるAPIを提供する可能性があります。そのため、API分析において cgo
の有効/無効を考慮することは重要です。
技術的詳細
このコミットの技術的詳細は、主に src/cmd/api/goapi.go
ファイルへの変更に集約されます。
-
新しいフラグ
-contexts
の追加:flag.String
を使用して、forceCtx
という新しいグローバル変数が定義されました。これは、コマンドラインから-contexts
フラグで渡される文字列(例:"linux-amd64,windows-386-cgo"
)を保持します。var ( // ... 既存のフラグ定義 ... forceCtx = flag.String("contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.") )
-
デフォルトコンテキストの初期化ロジックの変更: 以前は
init()
関数内でcontexts
スライス内の各build.Context
のCompiler
フィールドがbuild.Default.Compiler
に設定されていました。このコミットにより、この初期化ロジックはmain()
関数内に移動され、-contexts
フラグが指定された場合に新しいコンテキストが設定された後に実行されるようになりました。// 変更前: // func init() { // for _, c := range contexts { // c.Compiler = build.Default.Compiler // } // } // 変更後 (main関数内): // if *forceCtx != "" { // setContexts() // } // for _, c := range contexts { // c.Compiler = build.Default.Compiler // }
-
parseContext
関数の追加: この新しい関数は、<goos>-<goarch>[-cgo]
形式の文字列を受け取り、対応する*build.Context
オブジェクトを生成します。入力文字列をハイフンで分割し、GOOS
とGOARCH
を抽出し、オプションでcgo
が指定されていればCgoEnabled
をtrue
に設定します。不正な形式の文字列が渡された場合はlog.Fatalf
でプログラムを終了させます。func parseContext(c string) *build.Context { parts := strings.Split(c, "-") if len(parts) < 2 { log.Fatalf("bad context: %q", c) } bc := &build.Context{ GOOS: parts[0], GOARCH: parts[1], } if len(parts) == 3 { if parts[2] == "cgo" { bc.CgoEnabled = true } else { log.Fatalf("bad context: %q", c) } } return bc }
-
setContexts
関数の追加: この関数は、-contexts
フラグで指定されたカンマ区切りの文字列を解析し、グローバル変数contexts
を新しい*build.Context
スライスで上書きします。strings.Split
で文字列を分割し、各部分文字列をparseContext
に渡してbuild.Context
オブジェクトを生成し、それをcontexts
スライスに追加します。func setContexts() { contexts = []*build.Context{} // デフォルトコンテキストをクリア for _, c := range strings.Split(*forceCtx, ",") { contexts = append(contexts, parseContext(c)) } }
-
main
関数でのフラグ処理:main
関数内でflag.Parse()
の後、*forceCtx
(つまり-contexts
フラグの値) が空文字列でない場合にsetContexts()
が呼び出されます。これにより、ユーザーが指定したコンテキストがデフォルトのコンテキストリストを上書きします。その後、contexts
スライス内のすべてのbuild.Context
オブジェクトに対してCompiler
フィールドが設定されます。func main() { flag.Parse() if *forceCtx != "" { setContexts() } for _, c := range contexts { c.Compiler = build.Default.Compiler } // ... 既存のロジック ... }
これらの変更により、cmd/api
ツールは、ユーザーがコマンドラインから明示的に指定したビルドコンテキストに基づいてAPI分析を実行できるようになり、特定のプラットフォームやビルド設定に特化したAPIの差異を効率的に調査することが可能になりました。
コアとなるコードの変更箇所
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 533636cd8a..b10a51c510 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -41,8 +41,11 @@ var (
allowNew = flag.Bool("allow_new", true, "allow API additions")
nextFile = flag.String("next", "", "optional filename of tentative upcoming API features for the next release. This file can be lazily maintained. It only affects the delta warnings from the -c file printed on success.")
verbose = flag.Bool("v", false, "verbose debugging")
+ forceCtx = flag.String("contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
)
+// contexts are the default contexts which are scanned, unless
+// overridden by the -contexts flag.
var contexts = []*build.Context{
{GOOS: "linux", GOARCH: "386", CgoEnabled: true},
{GOOS: "linux", GOARCH: "386"},
@@ -56,12 +59,6 @@ var contexts = []*build.Context{
{GOOS: "windows", GOARCH: "386"},
}
-func init() {
- for _, c := range contexts {
- c.Compiler = build.Default.Compiler
- }
-}
-
func contextName(c *build.Context) string {
s := c.GOOS + "-" + c.GOARCH
if c.CgoEnabled {
@@ -70,9 +67,42 @@ func contextName(c *build.Context) string {
return s
}
+func parseContext(c string) *build.Context {
+ parts := strings.Split(c, "-")
+ if len(parts) < 2 {
+ log.Fatalf("bad context: %q", c)
+ }
+ bc := &build.Context{
+ GOOS: parts[0],
+ GOARCH: parts[1],
+ }
+ if len(parts) == 3 {
+ if parts[2] == "cgo" {
+ bc.CgoEnabled = true
+ } else {
+ log.Fatalf("bad context: %q", c)
+ }
+ }
+ return bc
+}
+
+func setContexts() {
+ contexts = []*build.Context{}
+ for _, c := range strings.Split(*forceCtx, ",") {
+ contexts = append(contexts, parseContext(c))
+ }
+}
+
func main() {
flag.Parse()
+ if *forceCtx != "" {
+ setContexts()
+ }
+ for _, c := range contexts {
+ c.Compiler = build.Default.Compiler
+ }
+
var pkgs []string
if flag.NArg() > 0 {
pkgs = flag.Args()
コアとなるコードの解説
このコミットは、src/cmd/api/goapi.go
ファイルに以下の主要な変更を加えています。
-
forceCtx
フラグの追加:var (
ブロック内にforceCtx
という新しいstring
型のフラグが追加されました。これは-contexts
コマンドライン引数に対応し、ユーザーが指定するビルドコンテキストのリストをカンマ区切り文字列として受け取ります。 -
init()
関数の削除とCompiler
設定の移動: 以前はinit()
関数内でcontexts
スライス内の各build.Context
のCompiler
フィールドをbuild.Default.Compiler
に設定していました。このinit()
関数は削除され、そのロジックはmain()
関数内に移動されました。これにより、ユーザーが-contexts
フラグで新しいコンテキストを指定した場合でも、正しくCompiler
が設定されるようになります。 -
parseContext(c string) *build.Context
関数の追加: この関数は、"goos-goarch"
または"goos-goarch-cgo"
形式の文字列を解析し、対応する*build.Context
オブジェクトを返します。- 入力文字列をハイフン (
-
) で分割します。 - 少なくとも2つの部分(
GOOS
とGOARCH
)があることを確認します。そうでなければ、不正なコンテキストとしてプログラムを終了します。 build.Context
の新しいインスタンスを作成し、GOOS
とGOARCH
を設定します。- もし3番目の部分があり、それが
"cgo"
であれば、CgoEnabled
をtrue
に設定します。それ以外の場合は、不正なコンテキストとしてプログラムを終了します。
- 入力文字列をハイフン (
-
setContexts()
関数の追加: この関数は、forceCtx
フラグ(ユーザーが-contexts
で指定した文字列)を読み取り、それをカンマ (,
) で分割します。分割された各部分文字列に対してparseContext
を呼び出し、生成された*build.Context
オブジェクトをグローバルなcontexts
スライスに追加します。これにより、デフォルトで定義されていたcontexts
スライスが、ユーザーが指定したコンテキストで完全に上書きされます。 -
main()
関数内のロジック変更:flag.Parse()
の呼び出し後、main()
関数はまず*forceCtx
が空文字列でないか(つまり、ユーザーが-contexts
フラグを指定したか)をチェックします。- もし指定されていれば、
setContexts()
を呼び出して、contexts
スライスをユーザー定義のコンテキストで更新します。 - その後、
contexts
スライス内のすべてのbuild.Context
オブジェクトに対して、Compiler
フィールドをbuild.Default.Compiler
に設定します。このステップは、init()
関数から移動されたものです。
- もし指定されていれば、
これらの変更により、cmd/api
ツールは、デフォルトのビルドコンテキストのセットに加えて、またはそれを完全に置き換えて、ユーザーが指定した特定のビルドコンテキストでAPI分析を実行する柔軟性を獲得しました。
関連リンク
- Go CL 6236046: https://golang.org/cl/6236046
参考にした情報源リンク
- Go Command
api
: https://pkg.go.dev/cmd/api - Go
go/build
package: https://pkg.go.dev/go/build - Go
flag
package: https://pkg.go.dev/flag - Go
strings
package: https://pkg.go.dev/strings - Go
log
package: https://pkg.go.dev/log - Go Environment Variables (
GOOS
,GOARCH
): https://go.dev/doc/install/source#environment - Cgo: https://go.dev/blog/c-go-is-not-go