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

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

このコミットは、Go言語のビルドスクリプトである make.bash に変更を加え、CC 環境変数が設定されておらず、かつ gcc がシステムに存在しない場合に、代わりに clang および clang++ を使用するようにフォールバックするロジックを追加するものです。これにより、特に新しいバージョンのFreeBSD環境において、CC および CXX 環境変数を明示的に設定することなくGoをビルドできるようになります。

コミット

commit 382cc8cb398c011a1701c410b747f1e80fa66687
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Tue Apr 29 00:32:16 2014 -0400

    make.bash: if CC is not set, and gcc doesn't exist, try clang/clang++.
    This should make Go build without setting CC and CXX on newer FreeBSDs.
    
    LGTM=iant
    R=golang-codereviews, dave, gobot, iant
    CC=golang-codereviews
    https://golang.org/cl/89230045

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

https://github.com/golang/go/commit/382cc8cb398c011a1701c410b747f1e80fa66687

元コミット内容

make.bash: if CC is not set, and gcc doesn't exist, try clang/clang++.
This should make Go build without setting CC and CXX on newer FreeBSDs.

LGTM=iant
R=golang-codereviews, dave, gobot, iant
CC=golang-codereviews
https://golang.org/cl/89230045

変更の背景

Go言語のビルドプロセスでは、C言語で書かれた部分(例えば、ランタイムの一部やcmd/distツールなど)をコンパイルするためにCコンパイラが必要です。伝統的に、多くのUnix系システムではgcc(GNU Compiler Collection)が標準的なCコンパイラとして広く利用されてきました。しかし、FreeBSDのような一部のオペレーティングシステムでは、近年clang(LLVM Clang)がデフォルトのC/C++コンパイラとして採用される傾向にあります。

この変更が行われた2014年頃、特に新しいバージョンのFreeBSDでは、gccがデフォルトでインストールされていないか、あるいはclangが優先的に使用される環境が増えていました。Goのビルドスクリプトであるmake.bashは、Cコンパイラとしてデフォルトでgccを想定していましたが、clangがデフォルトの環境では、ユーザーが手動でCC=clangCXX=clang++といった環境変数を設定しない限り、ビルドが失敗する可能性がありました。

このコミットは、このような環境におけるGoのビルド体験を向上させることを目的としています。ユーザーが明示的にコンパイラを指定しない場合でも、システムにgccが存在しない場合にclangを自動的に検出して使用することで、ビルドの互換性と利便性を高めています。

前提知識の解説

Go言語のビルドプロセスとCコンパイラ

Go言語は、その大部分がGo自身で書かれていますが、ランタイムの一部や、Goのツールチェインを構築するための初期段階のツール(例えばcmd/dist)はC言語で書かれています。これらのC言語部分をコンパイルするためには、システムにCコンパイラがインストールされている必要があります。Goのビルドスクリプトは、通常、CC環境変数で指定されたコンパイラを使用し、指定がない場合はデフォルトでgccを探します。

make.bash

make.bashは、Go言語のソースコードからGoのツールチェイン全体をビルドするための主要なシェルスクリプトです。このスクリプトは、Goのコンパイラ、リンカ、標準ライブラリ、およびその他のツールを構築する複雑なプロセスをオーケストレーションします。C言語で書かれた部分のコンパイルもこのスクリプトによって行われます。

CC および CXX 環境変数

  • CC: Cコンパイラを指定するための環境変数です。例えば、CC=clangと設定すると、ビルドシステムはCコードのコンパイルにclangを使用します。
  • CXX: C++コンパイラを指定するための環境変数です。Goのビルドプロセスでは主にCコンパイラが重要ですが、一部のツールや依存関係でC++コンパイラが必要になる場合があります。

gcc (GNU Compiler Collection)

gccは、GNUプロジェクトによって開発された、非常に広く使われているコンパイラシステムです。C、C++、Objective-C、Fortran、Ada、Goなどの多くのプログラミング言語をサポートしています。長年にわたり、Unix系システムのデファクトスタンダードなコンパイラとして機能してきました。

clang (LLVM Clang)

clangは、LLVMプロジェクトの一部として開発されているC、C++、Objective-C、Objective-C++コンパイラのフロントエンドです。gccと比較して、より高速なコンパイル、より良いエラーメッセージ、よりモジュール化されたアーキテクチャなどの利点があります。macOSや新しいバージョンのFreeBSDなど、多くのモダンなシステムでデフォルトのコンパイラとして採用されています。

type -t コマンド

type -tは、シェル組み込みコマンドの一つで、引数として与えられたコマンド名がどのような種類(エイリアス、キーワード、関数、組み込みコマンド、ファイル)であるかを返します。このコミットでは、type -t gcctype -t clangのように使用されており、これはそれぞれgccclangという名前の実行可能ファイルがシステムパス上に存在するかどうかを確認するために使われています。存在しない場合、何も出力されません。

FreeBSD

FreeBSDは、UNIX系のオペレーティングシステムの一つで、高性能、安定性、セキュリティに重点を置いています。サーバー、デスクトップ、組み込みシステムなど、幅広い用途で利用されています。近年、FreeBSDはデフォルトのコンパイラとしてgccからclangへの移行を進めていました。

技術的詳細

このコミットは、src/make.bashスクリプトのCコンパイラ選択ロジックを強化します。既存のロジックでは、CC環境変数が設定されていない場合、デフォルトでgccを使用しようとします。しかし、gccがシステムにインストールされていない場合、この試みは失敗し、ビルドエラーが発生します。

追加されたロジックは、以下の条件をチェックします。

  1. [ -z "$CC" ]: CC環境変数が空である(設定されていない)ことを確認します。
  2. [ -z "$(type -t gcc)" ]: gccという名前の実行可能ファイルがシステムパス上に存在しないことを確認します。type -t gccが何も出力しない場合、-z(文字列が空であるか)の条件が真となります。
  3. [ -n "$(type -t clang)" ]: clangという名前の実行可能ファイルがシステムパス上に存在することを確認します。type -t clangが何か出力する場合、-n(文字列が空でないか)の条件が真となります。

これら3つの条件がすべて真である場合、つまり「CCが設定されておらず、かつgccが存在せず、かつclangが存在する」場合に、スクリプトはCC環境変数をclangに、CXX環境変数をclang++に設定します。これにより、後続のCコードのコンパイルステップでclangが自動的に使用されるようになります。

この変更は、特にclangがデフォルトのコンパイラであるFreeBSDのような環境で、ユーザーが手動でコンパイラを設定する手間を省き、Goのビルドプロセスをより堅牢にします。

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

変更は src/make.bash ファイルの以下の部分です。

--- a/src/make.bash
+++ b/src/make.bash
@@ -125,6 +125,10 @@ if [ "$(uname)" == "Darwin" ]; then
 	# golang.org/issue/5261
 	mflag="-mmacosx-version-min=10.6"
 fi
+# if gcc does not exist and $CC is not set, try clang if available.
+if [ -z "$CC" -a -z "$(type -t gcc)" -a -n "$(type -t clang)" ]; then
+	export CC=clang CXX=clang++
+fi
 ${CC:-gcc} $mflag -O2 -Wall -Werror -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
 
 # -e doesn't propagate out of eval, so check success by hand.

コアとなるコードの解説

追加された4行のコードは、if文によって条件付きでCCCXX環境変数を設定しています。

# if gcc does not exist and $CC is not set, try clang if available.
if [ -z "$CC" -a -z "$(type -t gcc)" -a -n "$(type -t clang)" ]; then
	export CC=clang CXX=clang++
fi
  • # if gcc does not exist and $CC is not set, try clang if available.:この行は、追加されたコードの目的を説明するコメントです。
  • if [ -z "$CC" -a -z "$(type -t gcc)" -a -n "$(type -t clang)" ]; then
    • [ ... ]:これはBashの条件式です。
    • -z "$CC"$CC変数が空文字列である(つまり、CC環境変数が設定されていないか、空に設定されている)場合に真となります。
    • -a:論理AND演算子です。これに続く条件も真である必要があります。
    • -z "$(type -t gcc)"type -t gccコマンドの出力が空文字列である場合に真となります。これは、システムパス上にgccという実行可能ファイルが見つからないことを意味します。
    • -a:再び論理AND演算子です。
    • -n "$(type -t clang)"type -t clangコマンドの出力が空文字列ではない場合に真となります。これは、システムパス上にclangという実行可能ファイルが見つかることを意味します。
    • これらの3つの条件がすべて満たされた場合、thenブロック内のコマンドが実行されます。
  • export CC=clang CXX=clang++
    • export:このコマンドは、指定された変数を現在のシェルとその子プロセスで利用可能な環境変数として設定します。
    • CC=clang:Cコンパイラとしてclangを使用するように設定します。
    • CXX=clang++:C++コンパイラとしてclang++を使用するように設定します。

このifブロックの直後にある以下の行は、設定されたCC(またはデフォルトのgcc)を使用してcmd/distツールをコンパイルしています。

${CC:-gcc} $mflag -O2 -Wall -Werror -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
  • ${CC:-gcc}:これはBashのパラメータ展開の機能です。CC変数が設定されていればその値を使用し、設定されていなければデフォルト値としてgccを使用します。このコミットで追加されたロジックにより、CCclangに設定された場合はclangが使用され、それ以外の場合はgccが使用されることになります。

この変更により、Goのビルドシステムは、gccが存在しない環境(特に新しいFreeBSDなど)で自動的にclangに切り替えることができ、ユーザーの手動設定なしにビルドの成功率を高めることができます。

関連リンク

参考にした情報源リンク