RHEL6にGCC4.9をソースコードからインストールする


C++11サポートが必要になり、タイトルを行ったので、備忘録として残しておきます。

インストールディレクトリ

システムに入っているGCCと競合関係を起こすと非常に面倒なことになると思うので、他のソフトウェアとは異なる場所にインストールして、必要なときだけ使うという方法にします。

以下インストールディレクトリは/usr/local/src/gcc-4.9として作業を進めていきます。

cd /usr/local/src
sudo mkdir gcc-4.9
suco chown USERNAME gcc-4.9
cd gcc-4.9

USERNAMEは適宜ご自身の名前に変更してください。

ダウンロードと依存関係

はじめに、ミラーサイトからソースコードをダウンロードします。

wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-4.9.4/gcc-4.9.4.tar.gz
tar zxvf gcc-4.9.4.tar.gz
cd gcc-4.9.4

gcc4.9には以下の依存関係があります。

gcc 4.9
 |- MPC 0.8.0+
     |- MPFR 2.4.0+
         |- GMP 4.2+

ですので、はじめに依存するライブラリをダウンロードします。

(はじめは、すべて手作業で行っていたのですが、)これを行うには./contrib/download_prerequisitesを実行するだけのようです。

./contrib/download_prerequisites

インストール

はじめに、Makefileを作ります。

./configure --prefix=/usr/local/src/gcc-4.9 --with-local-prefix=/usr/local/src/gcc-4.9 --program-suffix=4.9 --host=x86_64-redhat-linux --build=x86_64-redhat-linux --target=x86_64-redhat-linux --enable-languages=c,c++,fortran --disable-multilib

各オプションの意味は以下の通りです。

オプション
--prefix インストール先のディレクトリ
--with-local-prefix 他のバージョンのGCCがいる環境でインストールするときは指定したほうが良いみたいです。(参考
--program-suffix 生成されるバイナリのサフィックスです。システムのGCCと区別するために今回は4.9としました。
--host 指定しない場合は、x86_64_unknown-linuxが使われました。(あえて指定する必要もないかもしれません)
--build --hostと同じ
--target --hostと同じ
--enable-languages 今回はJavaはいらないので、このようになりました。
--disable-multilib デフォルトだと32bitと64bit両方のバイナリが作成されてしまうので、ここでは64bitのみとしました。

あとは、以下のコマンドでインストールしました。

make
make install

makeには当方環境ではおよそ2時間かかりました。

また、本当は、make checkしたかったのですが、autogenコマンドが見つからないといわれてしまいできませんでした。

あれ、もしかして、案外簡単?

テスト

簡単なテストを行ってみます。

https://kaworu.jpn.org/cpp/C++11にあるC++11でないと動かないサンプルコード

#include <iostream>
using namespace std;
class C {
        int i;
        public:
        C (int ia) : i(ia) {}
        C () : C (123) {}

};
int main(int argc, char const* argv[])
{
        C c;
        return 0;
}

foo.ccという名前で保存して、コンパイルしてみます。

/usr/local/src/gcc-4.9/bin/g++4.9 -std=c++11 foo.cc

無事、コンパイルできて、実行もエラーなくできました。

通常ですと、https://qiita.com/qiitamatumoto/items/c2de3f976b86f21ce2a6でも言われているように、LD_LIBRARY_PATHにインストールしたGCCが入っていない状態だと、リンカーがリンク先を間違えてしまう問題が発生してしまいますが、そのような現象がおきていません。

--with-local-prefixを指定すると、上記の問題は自動的に回避されるのでしょうか。
よくわかりませんが、動いたので、ひとまず良かったということにします。

生成されたバイナリのリンクを確認すると、

$ ldd a.out
        linux-vdso.so.1 =>  (0x00007ffcca195000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f7228641000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f72283bc000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f72281a6000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f7227e12000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f7228965000)

となり、リンク先がシステム標準のGCCライブラリを指しており間違っています。

やはり、明示的にGCC4.9のライブラリを指すように指示する必要があるようです。

そこで、-Wl,-rpathを指定してコンパイルすると、

$ /usr/local/src/gcc-4.9/bin/g++4.9 -std=c++11 -Wl,-rpath=/usr/local/src/gcc-4.9/lib64 foo.cc
$ ldd a.out
        linux-vdso.so.1 =>  (0x00007fffe0d62000)
        libstdc++.so.6 => /usr/local/src/gcc-4.9/lib64/libstdc++.so.6 (0x00007feb412ab000)
        libm.so.6 => /lib64/libm.so.6 (0x00007feb41009000)
        libgcc_s.so.1 => /usr/local/src/gcc-4.9/lib64/libgcc_s.so.1 (0x00007feb40df3000)
        libc.so.6 => /lib64/libc.so.6 (0x00007feb40a5f000)
        /lib64/ld-linux-x86-64.so.2 (0x00007feb415be000)

となり、無事正しいGCC4.9のライブラリを指すようになりました。