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

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

コミット

このコミットは、Go言語プロジェクトのビルドプロセスにおいて、コンパイラの警告を有効にするための変更を導入しています。具体的には、make.bashスクリプトが実行される際に、$HOME/binディレクトリにquietgccという新しいスクリプトをインストールし、ビルド設定ファイルsrc/Make.conf内でCコンパイラ(CC)とリンカ(LD)としてこのquietgccを使用するように変更しています。quietgccスクリプトは、GCCを特定の警告フラグ(-Wallなど)を付けて実行しつつ、Goプロジェクトのビルドにおいて「不適切」または「無用」と判断される特定の警告メッセージをフィルタリングし、さらに正しい64ビット版のGCCが使用されることを保証します。

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

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

元コミット内容

commit d2dfd76b3d30b601e9a92919cd41841459d4473e
Author: Russ Cox <rsc@golang.org>
Date:   Wed Nov 19 12:54:44 2008 -0800

    build with warnings enabled.
    
    new script "quietgcc" installed in $HOME/bin during make.bash
            runs gcc with warnings, turns off inappropriate ones,
            greps out useless output.
    
    quietgcc also makes sure to run the correct 64-bit gcc.
    
    R=r
    DELTA=38  (36 added, 0 deleted, 2 changed)
    OCL=17493
    CL=19599
---
 src/Make.conf     |  4 ++--
 src/make.bash     |  3 +++
 src/quietgcc.bash | 36 ++++++++++++++++++++++++++++++++++++\n 3 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/src/Make.conf b/src/Make.conf
index ddf4b97220..3542b70eef 100644
--- a/src/Make.conf
+++ b/src/Make.conf
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-CC=cc
-LD=cc
+CC=quietgcc
+LD=quietgcc
 CFLAGS=-ggdb -I$(GOROOT)/include
 BIN=$(HOME)/bin
 O=o
diff --git a/src/make.bash b/src/make.bash
index 8d284d88e7..0c9475f4d0 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -14,6 +14,9 @@ fi
 
 bash clean.bash
 
+cp quietgcc.bash $HOME/bin/quietgcc
+chmod +x $HOME/bin/quietgcc
+\n for i in lib9 libbio libmach_amd64 libregexp cmd runtime lib
 do
 	echo; echo; echo %%%% making $i %%%%; echo
 diff --git a/src/quietgcc.bash b/src/quietgcc.bash
new file mode 100755
index 0000000000..560b628c5d
--- /dev/null
+++ b/src/quietgcc.bash
@@ -0,0 +1,36 @@
+#!/bin/bash
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.\n# The master for this file is $GOROOT/src/quietgcc.bash
+# Changes made to $HOME/bin/quietgcc will be overridden.
+\n# Gcc output that we don\'t care to see.
+ignore=\': error: .Each undeclared identifier\'
+ignore=$ignore\'|: error: for each function it appears\'
+ignore=$ignore\'|is dangerous, better use\'
+ignore=$ignore\'|is almost always misused\'
+ignore=$ignore\'|: In function \'\n+ignore=$ignore\'|: At top level: \'\n+ignore=$ignore\'|In file included from\'
+ignore=$ignore\'|        from\'
+\n# Figure out which cc to run.
+# Can use plain cc on real 64-bit machines
+# and on OS X, but have to use crosstool on
+# mixed64-32 machines like thresher.
+gcc=gcc
+case \"`uname -a`\" in
+*mixed64-32*)\n+\tgcc=/usr/crosstool/v10/gcc-4.2.1-glibc-2.3.2/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/bin/gcc
+esac
+\n# Run gcc, save error status, redisplay output without noise, exit with gcc status.
+tmp=/tmp/qcc.$$.$USER.out
+$gcc -m64 -Wall -Wno-sign-compare -Wno-missing-braces \\\n+\t-Wno-parentheses -Wno-unknown-pragmas -Wno-switch -Wno-comment \\\n+\t\"$@\" >$tmp 2>&1
+status=$?\n+egrep -v \"$ignore\" $tmp | uniq
+rm -f $tmp
+exit $status

変更の背景

この変更の主な背景は、Go言語プロジェクトのビルドプロセスにおいて、コンパイラの警告をより効果的に管理することにあります。当時のGoプロジェクトはまだ初期段階であり、C言語で書かれた部分が多く、GCC(GNU Compiler Collection)を使用してコンパイルされていました。

通常、コンパイラの警告はコードの潜在的な問題や非推奨の機能使用を示すため、開発プロセスにおいて非常に重要です。しかし、大規模なプロジェクトや、異なる環境でビルドされる場合、以下のような問題が発生することがあります。

  1. 過剰な警告: 厳密な警告フラグ(例: -Wall)を有効にすると、開発者が対処する必要のない、あるいは特定のコンパイラやライブラリのバージョンに固有の「ノイズ」となる警告が大量に発生することがあります。これにより、本当に重要な警告が見過ごされるリスクがあります。
  2. 環境依存の警告: 特定のオペレーティングシステムやアーキテクチャ(例: 32ビットと64ビットの混在環境)では、異なるコンパイラパスや設定が必要となり、それが警告の発生に影響を与えることがあります。
  3. ビルドの安定性: 警告が多すぎると、CI/CDパイプラインや開発者のローカル環境でのビルドが不安定に見えたり、エラーと混同されたりする可能性があります。

このコミットは、これらの課題に対処し、警告を有効にしつつも、開発者が本当に注目すべき警告のみに焦点を当てられるようにするためのものです。特に、quietgccスクリプトは、特定の「不適切な」または「無用な」警告を抑制し、ビルド出力の可読性を向上させることを目的としています。また、64ビット環境での正しいGCCの選択も、クロスコンパイルや異なるアーキテクチャでのビルドの安定性を確保するために重要でした。

前提知識の解説

GCC (GNU Compiler Collection)

GCCは、GNUプロジェクトによって開発された、様々なプログラミング言語(C, C++, Objective-C, Fortran, Ada, Goなど)に対応するコンパイラの集合体です。Go言語の初期段階では、GoのコードはC言語に変換され、その後GCCによってコンパイルされるという仕組みが採用されていました。そのため、GoプロジェクトのビルドにはGCCが不可欠でした。

コンパイラ警告 (Compiler Warnings)

コンパイラ警告は、コンパイラがソースコードを解析する際に、プログラムの実行には影響しないものの、潜在的なバグ、非効率なコード、またはプログラミングのベストプラクティスからの逸脱を示唆するメッセージです。例えば、初期化されていない変数、型変換の不一致、到達不能なコードなどが警告の対象となります。警告を無視すると、将来的に予期せぬ動作やバグにつながる可能性があるため、通常は警告を真剣に受け止め、対処することが推奨されます。

ビルドスクリプトと設定ファイル

  • make.bash: Goプロジェクトのビルドプロセスを自動化するためのシェルスクリプトです。Goの初期のビルドシステムは、Unix系のmakeユーティリティとシェルスクリプトを組み合わせて構築されていました。このスクリプトは、コンパイル、リンク、テストなどの一連のタスクを実行します。
  • src/Make.conf: ビルドプロセスで使用される設定や変数を定義するファイルです。Cコンパイラ(CC)やリンカ(LD)のパス、コンパイルフラグ(CFLAGS)などがここで設定されます。

シェルスクリプト (Bash) の基本コマンド

  • cp (copy): ファイルやディレクトリをコピーするコマンド。
  • chmod (change mode): ファイルやディレクトリのパーミッション(読み取り、書き込み、実行権限)を変更するコマンド。+xは実行権限を追加することを意味します。
  • case ... esac: シェルスクリプトにおける条件分岐の構文。特定のパターンに一致するかどうかで処理を分岐させます。
  • uname -a: システムの情報を表示するコマンド。カーネル名、ホスト名、カーネルバージョン、プロセッサタイプなどが含まれます。このコミットでは、特にシステムが「mixed64-32」であるかどうかを判断するために使用されています。
  • egrep -v: grepコマンドの拡張版で、正規表現パターンに一致しない行を表示します。-vオプションは「inVert match」(一致しない行を表示)を意味します。
  • uniq: 連続する重複行を削除するコマンド。
  • $@: シェルスクリプトに渡されたすべての引数を表す特殊変数。
  • >: 標準出力をファイルにリダイレクトする演算子。
  • 2>&1: 標準エラー出力を標準出力にリダイレクトする演算子。これにより、エラーメッセージも通常の出力として扱われ、パイプで次のコマンドに渡せるようになります。
  • $?: 直前に実行されたコマンドの終了ステータス(終了コード)を表す特殊変数。0は成功、0以外はエラーを示します。
  • $HOME/bin: ユーザーのホームディレクトリ($HOME)の下にあるbinディレクトリ。慣習的に、ユーザーが個人的にインストールした実行可能ファイルやスクリプトを置く場所として使われます。このディレクトリは通常、ユーザーのPATH環境変数に含まれているため、ここに置かれたコマンドはどこからでも実行できます。

GCCのコンパイルフラグ

  • -m64: 64ビットコードを生成するようにコンパイラに指示します。
  • -Wall: ほぼすべての一般的な警告を有効にします。これは「W all」の略で、非常に多くの警告を有効にするため、コードの品質向上に役立ちますが、同時に多くのノイズを生成することもあります。
  • -Wno-sign-compare: 符号付き整数と符号なし整数の比較に関する警告を無効にします。これはC/C++でよくある警告で、意図しない結果を避けるために通常は注意が必要ですが、特定の状況では無効にされることがあります。
  • -Wno-missing-braces: 構造体初期化子で波括弧が不足している場合の警告を無効にします。
  • -Wno-parentheses: 括弧が不足している可能性のある演算子優先順位に関する警告を無効にします。
  • -Wno-unknown-pragmas: 未知の#pragmaディレクティブに関する警告を無効にします。これは、異なるコンパイラやバージョン間で移植性のあるコードを書く際に役立つことがあります。
  • -Wno-switch: switch文に関する警告(例: caseラベルのフォールスルー)を無効にします。
  • -Wno-comment: コメントに関する警告(例: ネストされたコメント)を無効にします。

技術的詳細

このコミットの技術的詳細の中心は、quietgcc.bashスクリプトの導入とそのビルドシステムへの統合です。

quietgcc.bashスクリプトの機能

quietgcc.bashは、GCCのラッパースクリプトとして機能し、以下の主要なタスクを実行します。

  1. 警告のフィルタリング:

    • スクリプトの冒頭で、ignore変数に正規表現パターンを定義しています。このパターンは、Goプロジェクトのビルドにおいて「ノイズ」と見なされる特定のGCC警告メッセージや出力行を捕捉します。
    • 例として、': error: .Each undeclared identifier'': In function ' など、コンパイラが生成する一般的なエラーや関数開始を示す行が含まれています。
    • GCCの出力は一時ファイル(/tmp/qcc.$$.$USER.out)にリダイレクトされ、その後egrep -v "$ignore"コマンドによって、ignoreパターンに一致する行が除外されます。
    • さらに、| uniqをパイプで繋ぐことで、連続する重複行も削除され、出力がより簡潔になります。
  2. 正しいGCCの選択:

    • スクリプトは、uname -aコマンドの出力に基づいて、実行すべきGCCのパスを決定します。
    • 特に、*mixed64-32*)というパターンマッチングを使用しており、これは「mixed64-32」という文字列を含むシステム(例: 32ビットと64ビットのライブラリが混在する環境)の場合に、特定のクロスツールチェーンのGCCパス(/usr/crosstool/v10/gcc-4.2.1-glibc-2.3.2/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/bin/gcc)を使用するように設定します。
    • それ以外のシステムでは、デフォルトのgccコマンドが使用されます。これは、特定の環境でのビルドの互換性と安定性を確保するために重要です。
  3. GCCの実行とステータスの保持:

    • 選択されたGCC ($gcc) は、以下のコンパイルフラグと共に実行されます。
      • -m64: 64ビットコードを生成。
      • -Wall: ほぼすべての警告を有効にする。
      • -Wno-sign-compare, -Wno-missing-braces, -Wno-parentheses, -Wno-unknown-pragmas, -Wno-switch, -Wno-comment: 特定の警告を無効にする。これらは、Goプロジェクトのコードベースや当時のGCCの挙動において、誤検知が多い、または対処が不要と判断された警告である可能性が高いです。
    • "$@"は、quietgccスクリプトに渡されたすべての引数(元のコンパイルコマンドのファイル名やその他のフラグ)をそのままGCCに渡します。
    • GCCの標準出力と標準エラー出力は一時ファイルにリダイレクトされます。
    • GCCの終了ステータス(成功/失敗)はstatus変数に保存され、スクリプトの最後にこのステータスで終了することで、ビルドシステムにGCCの実際の成否を正確に伝えます。

ビルドシステムへの統合

  1. src/make.bashの変更:

    • このスクリプトは、Goプロジェクトのビルド時に実行されるメインのビルドスクリプトです。
    • cp quietgcc.bash $HOME/bin/quietgccchmod +x $HOME/bin/quietgccの行が追加されました。これにより、srcディレクトリにあるquietgcc.bashがユーザーのホームディレクトリのbinディレクトリにコピーされ、実行可能パーミッションが付与されます。これにより、quietgccコマンドがシステム全体で利用可能になります。
  2. src/Make.confの変更:

    • この設定ファイルでは、Cコンパイラ(CC)とリンカ(LD)として、従来のccではなく、新しくインストールされたquietgccを使用するように変更されました。
    • CC=quietgcc
    • LD=quietgcc
    • これにより、GoプロジェクトのビルドシステムがCコードをコンパイルおよびリンクする際に、自動的にquietgccスクリプトを介してGCCが呼び出されるようになります。

これらの変更により、Goプロジェクトはコンパイラの警告を有効にしつつも、その出力を開発者にとってより有用なものに整形し、特定の環境でのビルドの堅牢性を高めることができました。

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

このコミットでは、以下の3つのファイルが変更されています。

  1. src/Make.conf:

    --- a/src/Make.conf
    +++ b/src/Make.conf
    @@ -2,8 +2,8 @@
     # Use of this source code is governed by a BSD-style
     # license that can be found in the LICENSE file.
     
    -CC=cc
    -LD=cc
    +CC=quietgcc
    +LD=quietgcc
     CFLAGS=-ggdb -I$(GOROOT)/include
     BIN=$(HOME)/bin
     O=o
    
    • CC変数がccからquietgccに変更。
    • LD変数がccからquietgccに変更。
  2. src/make.bash:

    --- a/src/make.bash
    +++ b/src/make.bash
    @@ -14,6 +14,9 @@ fi
     
     bash clean.bash
     
    +cp quietgcc.bash $HOME/bin/quietgcc
    +chmod +x $HOME/bin/quietgcc
    +\n for i in lib9 libbio libmach_amd64 libregexp cmd runtime lib
     do
     	echo; echo; echo %%%% making $i %%%%; echo
    
    • cp quietgcc.bash $HOME/bin/quietgccが追加。
    • chmod +x $HOME/bin/quietgccが追加。
  3. src/quietgcc.bash:

    --- /dev/null
    +++ b/src/quietgcc.bash
    @@ -0,0 +1,36 @@
    +#!/bin/bash
    +# Copyright 2009 The Go Authors. All rights reserved.
    +# Use of this source code is governed by a BSD-style
    +# license that can be found in the LICENSE file.\n# The master for this file is $GOROOT/src/quietgcc.bash
    +# Changes made to $HOME/bin/quietgcc will be overridden.
    +\n# Gcc output that we don\'t care to see.
    +ignore=\': error: .Each undeclared identifier\'
    +ignore=$ignore\'|: error: for each function it appears\'
    +ignore=$ignore\'|is dangerous, better use\'
    +ignore=$ignore\'|is almost always misused\'
    +ignore=$ignore\'|: In function \'\n+ignore=$ignore\'|: At top level: \'\n+ignore=$ignore\'|In file included from\'
    +ignore=$ignore\'|        from\'
    +\n# Figure out which cc to run.
    +# Can use plain cc on real 64-bit machines
    +# and on OS X, but have to use crosstool on
    +# mixed64-32 machines like thresher.
    +gcc=gcc
    +case \"`uname -a`\" in
    +*mixed64-32*)\n+\tgcc=/usr/crosstool/v10/gcc-4.2.1-glibc-2.3.2/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/bin/gcc
    +esac
    +\n# Run gcc, save error status, redisplay output without noise, exit with gcc status.
    +tmp=/tmp/qcc.$$.$USER.out
    +$gcc -m64 -Wall -Wno-sign-compare -Wno-missing-braces \\\n+\t-Wno-parentheses -Wno-unknown-pragmas -Wno-switch -Wno-comment \\\n+\t\"$@\" >$tmp 2>&1
    +status=$?\n+egrep -v \"$ignore\" $tmp | uniq
    +rm -f $tmp
    +exit $status
    
    • quietgcc.bashという新しいファイルが追加され、その内容が定義されています。

コアとなるコードの解説

src/Make.confの変更

CC=quietgccLD=quietgccへの変更は、GoプロジェクトのビルドシステムがCコンパイラとリンカとして、システムデフォルトのccコマンドではなく、新しく導入されたquietgccスクリプトを使用するように指示します。これにより、すべてのCコードのコンパイルとリンクがquietgccの制御下で行われるようになり、警告のフィルタリングや特定のGCCバージョンの選択といったquietgccの機能が適用されます。これは、ビルドプロセス全体にわたって警告管理の一貫性を確保するための重要な設定変更です。

src/make.bashの変更

cp quietgcc.bash $HOME/bin/quietgccchmod +x $HOME/bin/quietgccの追加は、quietgccスクリプトをビルド環境にデプロイする役割を担います。

  • cpコマンドは、Goのソースツリー内にあるquietgcc.bashファイルを、ユーザーの実行可能ファイルパス(通常は$HOME/bin)にコピーします。これにより、quietgccがシステム上の任意の場所からコマンドとして呼び出せるようになります。
  • chmod +xコマンドは、コピーされたファイルに実行権限を付与します。これにより、シェルがそのファイルをスクリプトとして実行できるようになります。 これらのステップは、quietgccがビルドプロセス中に正しく利用されるための前提条件となります。

src/quietgcc.bashの新規追加

このスクリプトは、このコミットの核心部分であり、コンパイラ警告の管理とGCCの選択という二つの主要な目的を果たします。

  1. 警告フィルタリングロジック:

    • ignore変数に定義された正規表現パターンは、GCCの出力から特定の「ノイズ」となる警告やメッセージを除外するために使用されます。例えば、': error: .Each undeclared identifier'のようなメッセージは、Goの初期のCコードベースで頻繁に発生し、必ずしも開発者が即座に対処する必要のない、あるいはGoのコンテキストでは意味をなさない警告であった可能性があります。
    • egrep -v "$ignore" $tmp | uniqのパイプラインは、GCCの生出力を一時ファイルに保存し、そこから不要な行をegrep -vで除外し、さらにuniqで連続する重複行を削除することで、最終的なビルド出力をクリーンで読みやすいものにします。これにより、開発者は本当に重要な警告やエラーに集中できるようになります。
  2. GCCの選択ロジック:

    • case "uname -a" in *mixed64-32*)のブロックは、システムが「mixed64-32」環境であるかどうかを検出します。これは、32ビットと64ビットのライブラリやツールが混在するような特定のLinuxディストリビューションやビルド環境を指す可能性があります。このような環境では、システムデフォルトのgccが意図しないバージョンのGCCを指す可能性があり、ビルドの失敗や予期せぬ動作につながることがあります。
    • この条件に合致する場合、スクリプトは明示的に特定のパス(/usr/crosstool/v10/gcc-4.2.1-glibc-2.3.2/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/bin/gcc)にあるGCCを使用するようにgcc変数を設定します。これは、クロスコンパイル環境や特定のツールチェーンが要求される複雑なビルド設定において、正しいコンパイラが確実に使用されるようにするための堅牢なアプローチです。
  3. コンパイルフラグの適用:

    • -m64は、生成されるバイナリが64ビットアーキテクチャ向けであることを保証します。
    • -Wallは、広範囲の警告を有効にすることで、コード品質の向上を促します。
    • -Wno-で始まる一連のフラグは、特定の警告を無効にします。これらは、GoプロジェクトのCコードベースにおいて、誤検知が多い、または当時のGCCのバージョンで過剰に報告される傾向があった警告を抑制するために選択されたと考えられます。例えば、-Wno-sign-compareは符号付き/符号なし比較の警告を、-Wno-parenthesesは括弧の不足に関する警告を無効にします。これらの警告は、コードの意図が明確であるにもかかわらず発生することがあり、ビルド出力のノイズとなる可能性があります。

これらの変更は、Goプロジェクトが初期段階で直面していたビルドの課題、特にコンパイラ警告の管理と多様なビルド環境への対応において、実用的な解決策を提供しました。

関連リンク

  • Go言語の初期のビルドプロセスに関する議論やドキュメントは、現在のGoの公式ドキュメントからは見つけにくい場合があります。当時のメーリングリストのアーカイブや、Goの初期のコミット履歴を深く掘り下げると、より詳細な情報が見つかる可能性があります。
  • GCCの警告フラグに関する公式ドキュメント: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

参考にした情報源リンク

  • コミット情報: /home/orange/Project/comemo/commit_data/1186.txt
  • GitHubコミットページ: https://github.com/golang/go/commit/d2dfd76b3d30b601e9a92919cd41841459d4473e
  • GCC Warning Options: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html (一般的なGCCフラグの解説のため)
  • Bash Scripting Tutorial (一般的なシェルスクリプトのコマンド解説のため)
  • unameコマンドのmanページ (一般的なunameコマンドの解説のため)
  • grepコマンドのmanページ (一般的なgrepコマンドの解説のため)
  • uniqコマンドのmanページ (一般的なuniqコマンドの解説のため)
  • cpコマンドのmanページ (一般的なcpコマンドの解説のため)
  • chmodコマンドのmanページ (一般的なchmodコマンドの解説のため)
  • case文のBashドキュメント (一般的なcase文の解説のため)
  • $@$?のBash特殊変数に関するドキュメント (一般的なBash特殊変数の解説のため)
  • 2>&1のリダイレクトに関するBashドキュメント (一般的なリダイレクトの解説のため)
  • $HOME/binの慣習に関するLinux/Unixのドキュメント (一般的なディレクトリ構造の解説のため)
  • "mixed64-32 linux"に関する一般的な情報源 (特定のシステム環境の理解のため)
  • Go言語の初期のビルドシステムに関する一般的な知識 (Goプロジェクトの背景理解のため)