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

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

このコミットは、Go言語のsyscallパッケージ内で使用されるmkerrors.shスクリプトが、clangコンパイラでも動作するように修正するものです。具体的には、スクリプト内でハードコードされていたgccコマンドの呼び出しを、環境変数CCで指定されたコンパイラを使用するように変更し、CCが設定されていない場合はデフォルトでgccを使用するようにフォールバックするようになります。

コミット

commit fe330cf5bb28c3e29514ce78ed4b88ba89508de7
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Mon Feb 24 16:34:51 2014 +0900

    syscall: make mkerrors.sh work with clang
    
    LGTM=iant
    R=golang-codereviews, minux.ma, gobot, iant
    CC=golang-codereviews
    https://golang.org/cl/67170043

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

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

元コミット内容

syscall: make mkerrors.sh work with clang

このコミットは、syscallパッケージのmkerrors.shスクリプトがclangコンパイラでも正しく動作するように修正することを目的としています。

変更の背景

Go言語のビルドシステムやツールチェーンは、様々な環境やコンパイラに対応する必要があります。mkerrors.shスクリプトは、システムコールに関連するエラーコードやシグナル名を生成するために、Cコンパイラ(通常はgcc)を使用してヘッダーファイルを解析していました。しかし、特定の環境や開発ワークフローでは、gccの代わりにclangを使用することが一般的です。

このコミット以前は、mkerrors.shスクリプトがgccを直接呼び出すようにハードコードされていたため、clangがデフォルトのCコンパイラとして設定されている環境では、スクリプトが期待通りに動作しない可能性がありました。この変更は、より柔軟なコンパイラ選択を可能にし、clangを使用する開発者やビルドシステムがGoのsyscallパッケージを問題なくビルドできるようにするために行われました。

前提知識の解説

  • syscallパッケージ: Go言語の標準ライブラリの一つで、オペレーティングシステムの低レベルな機能(システムコール)にアクセスするためのインターフェースを提供します。ファイル操作、ネットワーク通信、プロセス管理など、OSに依存する多くの機能がこのパッケージを通じて実現されます。
  • mkerrors.sh: syscallパッケージのビルドプロセスの一部として実行されるシェルスクリプトです。このスクリプトの主な目的は、C言語のシステムヘッダーファイル(例: <errno.h>, <signal.h>)を解析し、Go言語のコードから利用できるエラーコード(EACCES, ENOENTなど)やシグナル名(SIGINT, SIGTERMなど)の定数を自動生成することです。これにより、GoプログラムがOS固有のエラーやシグナルを適切に処理できるようになります。
  • gcc (GNU Compiler Collection): GNUプロジェクトによって開発された、C、C++、Objective-C、Fortran、Ada、Goなどのプログラミング言語をサポートするコンパイラ群です。Linux環境で広く利用されています。
  • clang: LLVMプロジェクトの一部として開発されているC、C++、Objective-C、Objective-C++コンパイラです。gccと比較して、より高速なコンパイル、優れたエラーメッセージ、モジュール性などの利点があります。macOSやiOS開発環境で広く採用されています。
  • export LC_ALL=C, export LC_CTYPE=C: シェルスクリプトの冒頭で設定されている環境変数です。これらはロケール設定をCロケール(POSIXロケール)に強制することで、スクリプトの実行環境に依存しない安定した挙動を保証します。特に、文字列処理や正規表現の挙動がロケールによって変わることを防ぐために重要です。
  • -x c - -E -dM: gccclangなどのCコンパイラに渡されるオプションです。
    • -x c: 入力ファイルの種類をC言語として扱います。
    • -: 標準入力から読み込むことを意味します。
    • -E: プリプロセスのみを実行し、コンパイルやリンクは行いません。
    • -dM: プリプロセッサが定義したすべてのマクロを出力します。これにより、ヘッダーファイル内で定義されている#defineマクロの情報を抽出できます。
  • awk: テキスト処理を行うためのプログラミング言語です。このスクリプトでは、コンパイラの-dMオプションの出力から、特定のマクロ定義(エラーコードやシグナル名)を抽出するために使用されています。
  • egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)': egrepgrep -Eと同じ)は拡張正規表現をサポートするgrepコマンドです。-vオプションは、指定されたパターンにマッチしない行を出力します。ここでは、SIGSTKSIZE, SIGSTKSZ, SIGRTを含むシグナル名をフィルタリングして除外しています。これらは通常、Goのsyscallパッケージで直接扱う必要がないか、特定のプラットフォームに依存する可能性があるためです。
  • sort: 行をソートするコマンドです。抽出されたエラーコードやシグナル名をアルファベット順に並べ替えるために使用されます。

技術的詳細

このコミットの核心は、mkerrors.shスクリプトがCコンパイラを呼び出す方法の変更にあります。

変更前は、スクリプト内でGCC=gccとハードコードされており、Cコンパイラの呼び出しはすべて$GCC変数を通じて行われていました。これは、gccがシステムにインストールされていることを前提としており、clangのような別のコンパイラを使用したい場合には、スクリプトを直接編集するか、gccへのシンボリックリンクを作成するなどの回避策が必要でした。

変更後は、CC=${CC:-gcc}という行が追加されました。これはシェルスクリプトのパラメータ展開の機能を利用しています。

  • ${CC:-gcc}: 環境変数CCが設定されている場合はその値を使用し、設定されていない(または空の)場合はデフォルト値としてgccを使用するという意味です。

これにより、スクリプトを実行する前にexport CC=clangのように環境変数CCを設定することで、mkerrors.shclangをCコンパイラとして使用するようになります。もしCCが設定されていなければ、以前と同様にgccが使用されるため、後方互換性も維持されます。

スクリプト内の$GCCのすべての出現箇所が$CCに置き換えられています。これにより、エラーコードやシグナル名を抽出するためにCヘッダーファイルをプリプロセスする際に、ユーザーが指定した(またはデフォルトの)Cコンパイラが使用されるようになります。

この変更は、Goのビルドシステムがより柔軟になり、異なるCコンパイラ環境での互換性を向上させる上で重要です。特に、macOSのようなclangがデフォルトのCコンパイラである環境でのGoのビルドを容易にします。

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

変更はsrc/pkg/syscall/mkerrors.shファイルに集中しています。

--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -11,7 +11,7 @@ unset LANG
 export LC_ALL=C
 export LC_CTYPE=C
 
-GCC=gcc
+CC=${CC:-gcc}
 
 uname=$(uname)
 
@@ -194,7 +194,7 @@ ccflags="$@"
 
 	# The gcc command line prints all the #defines
 	# it encounters while processing the input
-	echo "${!indirect} $includes" | $GCC -x c - -E -dM $ccflags |
+	echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
 	awk '
 		$1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
 
@@ -263,24 +263,24 @@ ccflags="$@"
 
 # Pull out the error names for later.
 errors=$(
-	echo '#include <errno.h>' | $GCC -x c - -E -dM $ccflags |
+	echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
 	awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
 	sort
 )
 
 # Pull out the signal names for later.
 signals=$(
-	echo '#include <signal.h>' | $GCC -x c - -E -dM $ccflags |
+	echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
 	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
 	egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
 	sort
 )
 
 # Again, writing regexps to a file.
-echo '#include <errno.h>' | $GCC -x c - -E -dM $ccflags |
+echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
 	awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
 	sort >_error.grep
-echo '#include <signal.h>' | $GCC -x c - -E -dM $ccflags |
+echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
 	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
 	egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
 	sort >_signal.grep
@@ -390,4 +390,4 @@ main(void)\n \'\n ) >_errors.c
 
-$GCC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out
+$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out

コアとなるコードの解説

  1. GCC=gcc から CC=${CC:-gcc} への変更:

    • 元のコードでは、Cコンパイラとしてgccが直接指定されていました。
    • 変更後では、環境変数CCが設定されていればその値を使用し、設定されていなければgccをデフォルトとして使用するように変更されました。これにより、ユーザーがCC環境変数を設定することで、任意のCコンパイラ(例: clang)を使用できるようになります。
  2. $GCC から $CC への置換:

    • スクリプト内でCコンパイラを呼び出しているすべての箇所(echo ... | $GCC -x c - -E -dM ...$GCC $ccflags -o _errors _errors.c ... など)で、変数名が$GCCから$CCに変更されました。
    • これにより、mkerrors.shスクリプトは、環境変数CCで指定されたコンパイラ(またはデフォルトのgcc)を使用して、システムヘッダーファイルの解析や中間Cファイルのコンパイルを行うようになります。

この変更により、mkerrors.shはより汎用的なCコンパイララッパーとして機能し、Goのビルドシステムが異なるCコンパイラ環境(特にclangが主流の環境)でもスムーズに動作するようになりました。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (GitHub): https://github.com/golang/go
  • Go言語のコードレビューシステム (Gerrit): https://go.dev/cl/67170043 (コミットメッセージに記載されているCLリンク)
  • シェルスクリプトのパラメータ展開に関するドキュメント (例: Bashのmanページなど)
  • gccおよびclangのmanページ(-E, -dM, -xオプションについて)
  • awk, grep, sortコマンドのmanページ
  • Go言語のビルドプロセスに関する一般的な情報源