5.9. GCC-4.7.1 - 2回め

GCC パッケージは C コンパイラーや C++ コンパイラーなどの GNU コンパイラーコレクションを提供します。

概算ビルド時間: 7.1 SBU
必要ディスク容量: 1.8 GB

5.9.1. GCC のインストール

第1回めの GCC のビルドでは、内部的なシステムヘッダーをインストールしています。 その1つ limits.h は、これに対応づくシステムヘッダー limits.h を読み込みます。 そのファイルは実際には /tools/include/limits.h となります。 しかし1回めの GCC のビルド時には /tools/include/limits.h は存在しません。 したがって GCC がインストールする内部ヘッダーは、部分的で自己完結した (self-contained) もののみとなり、システムヘッダーが持つ拡張機能は含まれません。 一時的な libc を構築するならこれは正しかったのですが、この段階での GCC のビルドでは、内部ヘッダーが完全な形のものでなければなりません。 完全な内部ヘッダーを生成するために、GCC ビルドシステムが通常行っている方法と同じようにするための、以下のコマンドを実行します。

cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
  `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/include-fixed/limits.h

x86 マシンにおいてブートストラップビルドを行うと、コンパイラーフラグ -fomit-frame-pointer が設定されます。 しかしブートストラップではないビルドの場合はデフォルトではこのフラグが無効化されてしまいます。 ここで実現したいのは、ブートストラップビルドを行った場合とまったく同じコンパイラーをビルドすることです。 そこで以下の sed コマンドにより、強制的に上のフラグを利用するようにします。

cp -v gcc/Makefile.in{,.tmp}
sed 's/^T_CFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in.tmp \
  > gcc/Makefile.in

もう一度、GCC のデフォルトのダイナミックリンカーの配置ディレクトリを、既にインストールされている /tools とします。

for file in \
 $(find gcc/config -name linux64.h -o -name linux.h -o -name sysv4.h)
do
  cp -uv $file{,.orig}
  sed -e 's@/lib\(64\)\?\(32\)\?/ld@/tools&@g' \
  -e 's@/usr@/tools@g' $file.orig > $file
  echo '
#undef STANDARD_STARTFILE_PREFIX_1
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_1 "/tools/lib/"
#define STANDARD_STARTFILE_PREFIX_2 ""' >> $file
  touch $file.orig
done

GCC を初めてビルドする際には GMP、MPFR、MPC の各パッケージを必要とします。 tarball を解凍して、所定のディレクトリ名に移動させます。

tar -Jxf ../mpfr-3.1.1.tar.xz
mv -v mpfr-3.1.1 mpfr
tar -Jxf ../gmp-5.0.5.tar.xz
mv -v gmp-5.0.5 gmp
tar -zxf ../mpc-1.0.tar.gz
mv -v mpc-1.0 mpc

専用のディレクトリを再度生成します。

mkdir -v ../gcc-build
cd ../gcc-build

GCC のビルドに入る前に、デフォルトの最適化フラグを上書きするような環境変数の設定がないことを確認してください。

GCC をコンパイルするための準備をします。

CC=$LFS_TGT-gcc \
AR=$LFS_TGT-ar                  \
RANLIB=$LFS_TGT-ranlib          \
../gcc-4.7.1/configure          \
    --prefix=/tools             \
    --with-local-prefix=/tools  \
    --with-native-system-header-dir=/tools/include \
    --enable-clocale=gnu        \
    --enable-shared             \
    --enable-threads=posix      \
    --enable-__cxa_atexit       \
    --enable-languages=c,c++    \
    --disable-libstdcxx-pch     \
    --disable-multilib          \
    --disable-bootstrap         \
    --disable-libgomp           \
    --with-mpfr-include=$(pwd)/../gcc-4.7.1/mpfr/src \
    --with-mpfr-lib=$(pwd)/mpfr/src/.libs

configure オプションの意味:

--enable-clocale=gnu

このオプションはあらゆる状況において C++ ライブラリに対するロケールモデルが正しく設定されるようにします。 configure スクリプト実行時に de_DE ロケールがインストール済みであることが分かれば、正しい GNU ロケールモデルが設定されます。 しかし de_DE ロケールがインストールされていなかったら、誤った汎用ロケールモデルが設定されてしまうため、アプリケーションバイナリインターフェース (Application Binary Interface; ABI) とは非互換の C++ ライブラリが生成されてしまう可能性があります。

--enable-threads=posix

マルチスレッドコードを扱う C++ の例外処理を有効にします。

--enable-__cxa_atexit

このオプションは atexit を使用せず __cxa_atexit の使用を有効にします。 これによりローカルなスタティックオブジェクトおよびグローバルオブジェクトに対する C++ デストラクターを登録します。 このオプションは、標準に完全準拠したデストラクタ実装のために必要です。 またこれは C++ ABI に影響するものであり C++ 共有ライブラリ、C++ プログラムを作り出し、他の Linux ディストリビューションとの互換性を実現します。

--enable-languages=c,c++

C と C++ の両コンパイラーを生成することを指示します。

--disable-libstdcxx-pch

libstdc++ に対してプリコンパイルヘッダー (pre-compiled header; PCH) をビルドしないように指示します。 これを含めてしまうとサイズが増えることになり、そもそも利用する必要がありません。

--disable-bootstrap

GCC のネイティブビルドを行うには、デフォルトでは "ブートストラップ" ビルドを行ないます。 これは単に GCC をコンパイルするのではなく、数回のコンパイルを繰り返します。 つまり一回めにビルドされたプログラムを使って二回め、三回めのコンパイルを行うものです。 二回め、三回めとコンパイルを繰り返すのは、これによって自分自身を再生成して完璧なものを作り出すためです。 このことによってコンパイルが正確に行われたことを暗に示すことにもなります。 しかし LFS のビルドでは、何度もブートストラップを行う必要のない、手堅い(solid) コンパイラーを作り出します。

パッケージをコンパイルします。

make

パッケージをインストールします。

make install

最後にシンボリックリンクを作成します。 プログラムやスクリプトの中には gcc ではなく cc を用いるものが結構あります。 シンボリックリンクを作ることで各種のプログラムを汎用的にすることができ、通常 GNU C コンパイラーがインストールされていない多くの UNIX システムでも利用できるものになります。 cc を利用することにすれば、システム管理者がどの C コンパイラーをインストールすべきかを判断する必要がなくなります。

ln -vs gcc /tools/bin/cc
[注意]

注意

この時点で、構築したツールチェーンの基本的な (コンパイルやリンクなどの) 機能が正しく動作していることを確認する必要があります。 健全性検査 (sanity check) を行うために以下を実行してください。

echo 'main(){}' > dummy.c
cc dummy.c
readelf -l a.out | grep ': /tools'

問題なく動作した場合はエラーがなかったということで、最後のコマンドから出力される結果は以下のようになるはずです。

[Requesting program interpreter: /tools/lib/ld-linux.so.2]

ここでダイナミックリンカーのディレクトリが /tools/lib であることを確認してください。 あるいは 64 ビットマシンであれば /tools/lib64 であることを確認してください。

コマンドの出力結果が上と異なっていたり、あるいは何も出力されなかった場合は、何かがおかしいことを意味します。 どこに問題があるのか調査、再試行を行って解消してください。 解決せずにこの先に進まないでください。 cc ではなく gcc を使って再度健全性検査を行ってみてください。 これで解決したなら /tools/bin/cc のシンボリックリンクが正しくないということです。 正しく生成し直してください。 また環境変数 PATH が正しいかどうかも確認してください。 echo $PATH を実行して、実行パスリストの先頭が /tools/bin であるかどうか確認します。 PATH が間違っていたなら、実はあなたは lfs ユーザーでログインしていないのかもしれませんし 4.4.「環境設定」での作業に間違いがあったのかもしれません。

すべてが終了したらテストファイルを削除します。

rm -v dummy.c a.out

本パッケージの詳細は 6.17.2.「GCC の構成」を参照してください。