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

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

このコミットは、Go言語のビルドツールである cmd/dist におけるビルドプロセスの修正に関するものです。具体的には、src/cmd/dist/build.c ファイル内のコンパイラ検出ロジックが変更され、clang コンパイラの検出方法がより堅牢になりました。

コミット

commit e6ddddadda8e578838c7d8f692791ea74423b161
Author: Russ Cox <rsc@golang.org>
Date:   Fri Aug 2 15:13:06 2013 -0400

    cmd/dist: fix build
    
    TBR=bradfitz
    CC=golang-dev
    https://golang.org/cl/12369043

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

https://github.com/golang/go/commit/e6ddddadda8e578838c7d8f692791ea74423b161

元コミット内容

    cmd/dist: fix build
    
    TBR=bradfitz
    CC=golang-dev
    https://golang.org/cl/12369043

変更の背景

この変更の背景には、Go言語のビルドシステムが clang コンパイラを検出する方法の改善があります。以前のバージョンでは、clang コンパイラが使用されているかどうかを判断するために、おそらく特定のビルドフラグや環境変数に依存する bool clang 変数を使用していたと考えられます。しかし、このような静的なフラグは、clang が異なるパスやエイリアスで呼び出される多様なビルド環境において、常に正確に機能するとは限りませんでした。

このコミットは、clang の検出をより動的に、かつ堅牢に行うことを目的としています。これにより、Goのビルドプロセスが様々なシステム構成やコンパイラのセットアップに対して、より適応性が高くなるように修正されました。

前提知識の解説

  • cmd/dist: cmd/dist はGo言語のソースコードからGoツールチェイン全体をビルドするためのブートストラップツールです。Goのコンパイラ、リンカ、アセンブラなどのツール群を構築する役割を担っています。Goのビルドシステムの中核をなす部分であり、Goの自己ホスト型コンパイラがまだ利用できない初期段階や、異なるアーキテクチャ向けのクロスコンパイル環境を構築する際に特に重要です。
  • build.c: cmd/dist ツールの一部である build.c ファイルは、Goのビルドプロセスの具体的なロジック、特にC言語で書かれた部分のコンパイルとリンクに関する処理を定義しています。GoのツールチェインにはC言語で書かれた部分も含まれるため、これらの部分をコンパイルするためにCコンパイラ(GCCやClangなど)が使用されます。
  • GCC (GNU Compiler Collection): 広く使用されているコンパイラコレクションで、C、C++、Goなど様々なプログラミング言語をサポートしています。
  • Clang: LLVMプロジェクトの一部として開発されているC、C++、Objective-C、Objective-C++コンパイラです。GCCと比較して、より高速なコンパイル、優れたエラーメッセージ、モジュール性などの利点があります。
  • コンパイラ検出: ビルドシステムが、利用可能なCコンパイラがGCCなのかClangなのか、あるいはその他のコンパイラなのかを識別するプロセスです。これによって、コンパイラ固有のオプションや最適化を適用することができます。

技術的詳細

このコミットの技術的な核心は、clang コンパイラの検出ロジックの変更にあります。

変更前は、install 関数内で bool clang; という変数が宣言され、この変数の値に基づいて clang 固有のコンパイラオプション(例: -fno-caret-diagnostics, -Qunused-arguments)が適用されていました。この clang 変数がどのように設定されていたかはコミット差分からは直接読み取れませんが、おそらくビルドスクリプトの引数や環境変数、あるいはコンパイラのパスの事前チェックなど、何らかの静的な方法で設定されていたと推測されます。

変更後は、bool clang; 変数が削除され、if(clang) という条件分岐が if(contains(gccargs.p[0], "clang")) に置き換えられました。

  • gccargs.p[0] は、コンパイラとして実行されるコマンドのパスまたは名前を保持していると考えられます。例えば、/usr/bin/clangclang といった文字列です。
  • contains(string, substring) 関数は、最初の文字列が2番目の部分文字列を含んでいるかどうかをチェックするユーティリティ関数です。

この変更により、ビルドシステムは、実際に実行しようとしているコンパイラのコマンドライン引数(gccargs.p[0])を検査し、その中に "clang" という文字列が含まれているかどうかで clang コンパイラが使用されているかを判断するようになりました。

このアプローチの利点は以下の通りです。

  1. 堅牢性: clang/usr/local/bin/clangxcrun clang のように、様々なパスやラッパーを介して呼び出される場合でも、コマンド名自体に "clang" が含まれていれば正しく検出できます。
  2. 動的な検出: ビルド時に実際に使用されるコンパイラの名前を直接調べるため、ビルド環境の多様性に対応しやすくなります。
  3. 依存関係の削減: clang 変数を設定するための外部ロジックや、ビルドスクリプトの複雑な条件分岐への依存が減ります。

この修正は、Goのビルドシステムが異なるオペレーティングシステムや開発環境において、より安定して動作するための重要な改善と言えます。特に、macOSのようなClangがデフォルトのCコンパイラである環境では、この変更がビルドの信頼性を向上させることに貢献します。

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

変更は src/cmd/dist/build.c ファイルの install 関数内で行われています。

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -589,7 +589,7 @@ static void
 install(char *dir)
 {
  	char *name, *p, *elem, *prefix, *exe;\n-\tbool islib, ispkg, isgo, stale, clang;\n+\tbool islib, ispkg, isgo, stale;\n  	Buf b, b1, path;\n  	Vec compile, files, link, go, missing, clean, lib, extra;\n  	Time ttarg, t;\n@@ -639,7 +639,7 @@ install(char *dir)\n  	\tsplitfields(&gccargs, bstr(&b));\n  	\tfor(i=0; i<nelem(proto_gccargs); i++)\n  	\t\tvadd(&gccargs, proto_gccargs[i]);\n-\t\tif(clang) {\n+\t\tif(contains(gccargs.p[0], \"clang\")) {\n  	\t\t// disable ASCII art in clang errors, if possible\n  	\t\tvadd(&gccargs, \"-fno-caret-diagnostics\");\n  	\t\t// clang is too smart about unused command-line arguments\n```

## コアとなるコードの解説

1.  **`bool clang;` の削除**:
    `static void install(char *dir)` 関数のローカル変数宣言から `clang` という `bool` 型の変数が削除されました。これは、`clang` コンパイラの検出を静的なフラグではなく、動的な文字列チェックに移行したことを意味します。

2.  **`if(clang)` から `if(contains(gccargs.p[0], "clang"))` への変更**:
    以前は `if(clang)` という条件分岐によって、`clang` 固有のコンパイラオプション(`-fno-caret-diagnostics` と `-Qunused-arguments`)が追加されていました。この条件が `if(contains(gccargs.p[0], "clang"))` に変更されました。
    *   `gccargs.p[0]` は、コンパイラとして実行されるコマンドの文字列(例: "clang", "/usr/bin/clang", "gcc" など)を指します。
    *   `contains(string, substring)` は、`string` の中に `substring` が含まれているかを判定する関数です。
    *   この変更により、実際に呼び出されるコンパイラの名前が "clang" を含んでいる場合にのみ、`clang` 固有のオプションが適用されるようになりました。これにより、`clang` の検出がより柔軟かつ正確になります。

この変更は、Goのビルドシステムが、使用されるCコンパイラの種類をより確実に識別し、それに応じて適切なコンパイラオプションを適用できるようにするためのものです。特に、`clang` が様々な環境で異なる方法で呼び出される可能性があるため、この動的な検出方法はビルドの堅牢性を高めます。

## 関連リンク

*   Go言語の公式リポジトリ: [https://github.com/golang/go](https://github.com/golang/go)
*   Go言語のIssueトラッカー (Go CL 12369043 に関連する可能性のあるIssue): [https://github.com/golang/go/issues](https://github.com/golang/go/issues)
*   Go言語のコードレビューシステム (Gerrit): [https://go-review.googlesource.com/](https://go-review.googlesource.com/) (CL 12369043 を検索すると詳細が見つかる可能性があります)

## 参考にした情報源リンク

*   Go言語のソースコード (特に `cmd/dist` ディレクトリ): [https://github.com/golang/go/tree/master/src/cmd/dist](https://github.com/golang/go/tree/master/src/cmd/dist)
*   GCC公式ドキュメント: [https://gcc.gnu.org/onlinedocs/](https://gcc.gnu.org/onlinedocs/)
*   Clang公式ドキュメント: [https://clang.llvm.org/docs/](https://clang.llvm.org/docs/)
*   LLVMプロジェクト: [https://llvm.org/](https://llvm.org/)