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

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

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

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

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

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

# ダウンロードと依存関係

はじめに、[ミラーサイト](http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-4.9.4/)からソースコードをダウンロードします。

```bash
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`を実行するだけのようです。

```bash
./contrib/download_prerequisites
```

# インストール

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

```bash
./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がいる環境でインストールするときは指定したほうが良いみたいです。（[参考](https://qiita.com/Tats_U_/items/5fed0f9dafb4ecb15c12)）|
|`--program-suffix`|生成されるバイナリのサフィックスです。システムのGCCと区別するために今回は`4.9`としました。|
|`--host`|指定しない場合は、`x86_64_unknown-linux`が使われました。（あえて指定する必要もないかもしれません）|
|`--build`|`--host`と同じ|
|`--target`|`--host`と同じ|
|`--enable-languages`|今回はJavaはいらないので、このようになりました。|
|`--disable-multilib`|デフォルトだと32bitと64bit両方のバイナリが作成されてしまうので、ここでは64bitのみとしました。|

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

```bash
make
make install
```

`make`には当方環境ではおよそ2時間かかりました。  
また、本当は、`make check`したかったのですが、`autogen`コマンドが見つからないといわれてしまいできませんでした。

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

# テスト

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

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

```c++
#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`という名前で保存して、コンパイルしてみます。

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

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

~~通常ですと、[https://qiita.com/qiitamatumoto/items/c2de3f976b86f21ce2a6](https://qiita.com/qiitamatumoto/items/c2de3f976b86f21ce2a6)でも言われているように、LD_LIBRARY_PATHにインストールしたGCCが入っていない状態だと、リンカーがリンク先を間違えてしまう問題が発生してしまいますが、そのような現象がおきていません。  
`--with-local-prefix`を指定すると、上記の問題は自動的に回避されるのでしょうか。
よくわかりませんが、動いたので、ひとまず良かったということにします。~~

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

```bash
$ 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`を指定してコンパイルすると、

```bash
$ /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のライブラリを指すようになりました。