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

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

このコミットは、Go言語のビルドシステムの一部である cmd/dist ツールにおけるコンパイラフラグの扱いに関する変更です。具体的には、コンパイラに渡す引数の形式を、単一の引数に複数のフラグをまとめる形式から、各フラグを個別の引数として渡す形式に変更しています。

コミット

commit 5e46d540c844df8a6dc6009e52b60e6cd67a012e
Author: Russ Cox <rsc@golang.org>
Date:   Wed Jan 2 17:52:54 2013 -0500

    cmd/dist: use separate args for separate compiler flags
    
    This makes dist safe for CL 7035043 (but keeps working now too).
    
    R=golang-dev, remyoudompheng
    CC=golang-dev
    https://golang.org/cl/7029047

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

https://github.com/golang/go/commit/5e46d540c844df8a6dc6009e52b60e6cd67a012e

元コミット内容

cmd/dist: use separate args for separate compiler flags

この変更は、dist ツールがコンパイラフラグを渡す際に、個別の引数を使用するようにします。これにより、CL 7035043(このコミットメッセージで言及されている変更リスト)に対して dist が安全になりますが、現在の動作も維持されます。

変更の背景

Go言語のビルドシステムにおいて、cmd/dist はGoのツールチェイン(コンパイラ、リンカなど)をビルドし、インストールするための重要なツールです。コンパイラにフラグを渡す際、これまでは -DGOOS="linux" -DGOARCH="amd64" のように、-D フラグとそれに続く定義を一つの文字列として渡していました。

しかし、将来のコンパイラの変更(コミットメッセージで言及されている CL 7035043 がこれに該当すると推測されますが、このCLの詳細は不明です)によって、このような結合された引数形式が問題を引き起こす可能性がありました。例えば、コンパイラが引数を解析する方法が変更され、-D とその後の定義を別々の引数として期待するようになる場合などが考えられます。

この変更は、そのような将来の互換性の問題を未然に防ぐための予防的な措置として行われました。各フラグを個別の引数として渡すことで、コンパイラの引数解析ロジックの変更に対してより堅牢なビルドシステムを構築することを目指しています。

前提知識の解説

  • cmd/dist: Go言語のソースコードからGoツールチェイン全体をビルドするためのコマンドラインツールです。Goのコンパイラ、リンカ、アセンブラなどのバイナリを生成し、インストールします。
  • コンパイラフラグ: コンパイラの動作を制御するために渡されるオプションです。例えば、-D フラグはプリプロセッサマクロを定義するために使用されます。
  • プリプロセッサマクロ: C言語やGo言語のコンパイルプロセスにおいて、コンパイル前にソースコードの一部を置換したり、条件付きでコンパイルしたりするために使用される定義です。-DNAME=VALUE の形式で渡されると、ソースコード内の NAMEVALUE に置換されます。
  • GOOSGOARCH: Go言語のクロスコンパイルにおいて非常に重要な環境変数です。
    • GOOS: ターゲットとなるオペレーティングシステム(例: linux, windows, darwin)。
    • GOARCH: ターゲットとなるアーキテクチャ(例: amd64, arm, 386)。 これらは、Goのビルド時に特定のOSやアーキテクチャ向けのコードを生成するために使用されます。
  • GOROOT: Goのインストールディレクトリを示す環境変数です。Goの標準ライブラリやツールチェインのパスを決定するために使用されます。
  • GOVERSION: 現在のGoのバージョンを示す文字列です。
  • GOARM / GO386: ARMやx86アーキテクチャにおける特定のサブアーキテクチャや機能セットを指定するための環境変数です。
  • GOEXPERIMENT: Goの実験的な機能の有効/無効を制御するための環境変数です。

技術的詳細

このコミットの主要な変更は、src/cmd/dist/build.csrc/cmd/dist/buildruntime.c の2つのファイルにわたっています。これらのファイルは、cmd/dist ツールがGoのコンパイラ(6c, 8c, 5c など、それぞれx86-64, x86, ARMアーキテクチャ向けのCコンパイラ)を呼び出す際の引数リストを構築するロジックを含んでいます。

変更前は、例えば -DGOOS="linux" のように、-D フラグとそれに続く定義(GOOS="linux")が bprintf 関数によって一つの文字列としてフォーマットされ、vadd 関数によって引数リストに追加されていました。

変更後は、-D フラグがまず単独の引数として vadd され、その後に GOOS="linux" のような定義が別の引数として bprintf され、vadd されるようになりました。これにより、コンパイラに渡される引数リストでは、-D とその定義が常に別々の要素として扱われるようになります。

例えば、変更前はコンパイラに ["-DGOOS=\"linux\""] のような引数が渡されていたのが、変更後は ["-D", "GOOS=\"linux\""] のように渡されるようになります。

同様の変更が、GOARCH, GOROOT, GOVERSION, GOARM, GO386, GOEXPERIMENT などの定義、および -FVw-I といった他のコンパイラフラグにも適用されています。特に -FVw は、変更前は一つの引数でしたが、変更後は -F, -V, -w の3つの個別の引数として渡されるようになっています。

この変更は、コンパイラの引数解析の厳密化や、将来的な引数処理の変更に備えるためのものです。これにより、cmd/dist が生成するコンパイラコマンドラインが、より標準的で予測可能な形式になり、異なるコンパイラバージョン間での互換性が向上することが期待されます。

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

src/cmd/dist/build.c

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -892,20 +892,27 @@ install(char *dir)
 
 			// lib9/goos.c gets the default constants hard-coded.
 			if(streq(name, "goos.c")) {
-				vadd(&compile, bprintf(&b, "-DGOOS=\"%s\"", goos));
-				vadd(&compile, bprintf(&b, "-DGOARCH=\"%s\"", goarch));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOOS=\"%s\"", goos));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOARCH=\"%s\"", goarch));
 				bprintf(&b1, "%s", goroot_final);
 				bsubst(&b1, "\\", "\\\\");  // turn into C string
-				vadd(&compile, bprintf(&b, "-DGOROOT=\"%s\"", bstr(&b1)));
-				vadd(&compile, bprintf(&b, "-DGOVERSION=\"%s\"", goversion));
-				vadd(&compile, bprintf(&b, "-DGOARM=\"%s\"", goarm));
-				vadd(&compile, bprintf(&b, "-DGO386=\"%s\"", go386));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOROOT=\"%s\"", bstr(&b1)));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOVERSION=\"%s\"", goversion));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOARM=\"%s\"", goarm));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GO386=\"%s\"", go386));
 			}
 
 			// gc/lex.c records the GOEXPERIMENT setting used during the build.
 			if(streq(name, "lex.c")) {
 				xgetenv(&b, "GOEXPERIMENT");
-				vadd(&compile, bprintf(&b1, "-DGOEXPERIMENT=\"%s\"", bstr(&b)));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b1, "GOEXPERIMENT=\"%s\"", bstr(&b)));
 			}
 		} else {
 			// Supporting files for a Go package.
@@ -913,12 +920,16 @@ install(char *dir)
 			if(streq(gochar, "a"))
 				vadd(&compile, bpathf(&b, "%s/%sa", tooldir, gochar));
 			else {
 				vadd(&compile, bpathf(&b, "%s/%sc", tooldir, gochar));
-				vadd(&compile, "-FVw");
+				vadd(&compile, "-F");
+				vadd(&compile, "-V");
+				vadd(&compile, "-w");
 			}
 			vadd(&compile, "-I");
 			vadd(&compile, workdir);
-			vadd(&compile, bprintf(&b, "-DGOOS_%s", goos));
-			vadd(&compile, bprintf(&b, "-DGOARCH_%s", goarch));
+			vadd(&compile, "-D");
+			vadd(&compile, bprintf(&b, "GOOS_%s", goos));
+			vadd(&compile, "-D");
+			vadd(&compile, bprintf(&b, "GOARCH_%s", goarch));
 		}
 
 		bpathf(&b, "%s/%s", workdir, lastelem(files.p[i]));

src/cmd/dist/buildruntime.c

--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -199,13 +199,16 @@ mkzasm(char *dir, char *file)
 	fatal("unknown $GOOS/$GOARCH in mkzasm");
 ok:
 
-	// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -a proc.c
+	// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a proc.c
 	// to get acid [sic] output.
 	vreset(&argv);
 	vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
-	vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
-	vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
-	vadd(&argv, bprintf(&b, "-I%s", workdir));
+	vadd(&argv, "-D");
+	vadd(&argv, bprintf(&b, "GOOS_%s", goos));
+	vadd(&argv, "-D");
+	vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
+	vadd(&argv, "-I");
+	vadd(&argv, bprintf(&b, "%s", workdir));
 	vadd(&argv, "-a");
 	vadd(&argv, "proc.c");
 	runv(&in, dir, CheckExit, &argv);
@@ -299,12 +302,15 @@ mkzruntimedefs(char *dir, char *file)
 	);
 
 	
-	// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -q
+	// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -q
 	// on each of the runtimedefs C files.
 	vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
-	vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
-	vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
-	vadd(&argv, bprintf(&b, "-I%s", workdir));
+	vadd(&argv, "-D");
+	vadd(&argv, bprintf(&b, "GOOS_%s", goos));
+	vadd(&argv, "-D");
+	vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
+	vadd(&argv, "-I");
+	vadd(&argv, bprintf(&b, "%s", workdir));
 	vadd(&argv, "-q");
 	vadd(&argv, "");
 	p = argv.p[argv.len-1];

コアとなるコードの解説

変更の核心は、vadd 関数と bprintf 関数の組み合わせ方にあります。

  • 変更前: vadd(&compile, bprintf(&b, "-DGOOS=\"%s\"", goos)); この行では、bprintf-DGOOS="linux" のような文字列を生成し、その結果が vadd によってコンパイラの引数リストに単一の要素として追加されます。

  • 変更後: vadd(&compile, "-D"); vadd(&compile, bprintf(&b, "GOOS=\"%s\"", goos)); この2行では、まず -D という文字列が単独の引数として追加され、次に GOOS="linux" のような文字列が別の引数として追加されます。

この変更により、コンパイラが引数を解析する際に、-D とその後の定義が明確に分離された引数として認識されるようになります。これは、コンパイラの内部的な引数処理ロジックが、結合された文字列ではなく、個別の引数を期待するようになった場合に特に重要です。

例えば、gccclang のような一般的なCコンパイラでは、-DNAME=VALUE の形式は単一の引数として扱われますが、より厳密な引数解析を行うツールや、将来的なコンパイラの変更によっては、-DNAME=VALUE を別々の引数として渡すことが推奨される場合があります。このコミットは、Goのビルドシステムがそのような変更に柔軟に対応できるようにするためのものです。

また、-FVw のような複数のフラグをまとめた形式も、-F, -V, -w と個別のフラグに分割されています。これも同様に、コンパイラの引数解析の堅牢性を高めるための変更です。

関連リンク

  • Go言語の公式ドキュメント: https://golang.org/doc/
  • Goのソースコードリポジトリ: https://github.com/golang/go
  • GoのCL (Change List) について: Goプロジェクトでは、Gerritというコードレビューシステムを使用して変更を管理しています。各変更はCL番号で識別されます。

参考にした情報源リンク

  • Go言語のソースコード (特に src/cmd/dist ディレクトリ)
  • Go言語のビルドシステムに関する一般的な知識
  • C言語のコンパイラフラグに関する一般的な知識 (特に -D フラグ)
  • コミットメッセージに記載されているCL番号 7029047 のGerritページ: https://golang.org/cl/7029047
    • (注: コミットメッセージに記載されている CL 7035043 については、Web検索では詳細な情報を見つけることができませんでした。これは内部的なCLであるか、または番号が誤っている可能性があります。)