macOS Catalina(10.15)でgccを自前でビルドした記録

# はじめに

macOS Catalinaを導入したのですが、fortranのコンパイラなどが必要なので、gccをビルドする必要がありました。

Homebrewなどのパッケージ管理システムが好きでないため、自前でビルドを行ったのですが、試行錯誤しながらの作業だったため、それをここに記録しておきます。

なお、macOSのバージョン・環境やgccのバージョンなど、コンパイルにはいろいろな要因が絡んできます。
まずはこの記事の更新日付を改めて確認していただき、作業に関しては自己責任でお願いいたします。

# 作業環境

バージョン: 10.15.2
Mac Book Pro (13-inch, 2019, Four Thunderbolt 3 pots)
プロセッサ: 2.8 GHz クアッドコアIntel Core i7
メモリ: 16GB

# 参考URL
https://solarianprogrammer.com/2017/05/21/compiling-gcc-macos/ :基本的な流れはこれを参考にしました。ただし、バージョンが古いので、全てそのまま、というわけにはいきません。

https://stackoverflow.com/questions/52211390/trouble-building-gcc-on-mac-cant-find-system-headers/52994839#52994839 : トラブルシューティングに関しては、ここにある情報が非常に参考になりました。

# 事前準備：　関連するライブラリのビルド
gccはGMP,MPFR,MPC,ISLなどのライブラリに依存しています。まずはこれらをダウンロード・ビルドします。
なお、インストール先としては、今回は`~/opt/gcc-9.2/`に依存ライブラリなどを含めて全てインストールするようにしています。
これに関しては通常の手順となんら変わりません。

## 1. GMP
```
> curl -L ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2 | tar xf -
> cd gmp*
> mkdir build
> cd build
> ../configure --prefix=$HOME/opt/gcc-9.2/ --enable-cxx
> make -j 4
> make install-strip
```

## 2. MPFR
``` 
> curl -L ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2 | tar xf -
> cd mpfr*
> mkdir build
> cd build
> ../configure --prefix=$HOME/opt/gcc-9.2 --with-gmp=$HOME/opt/gcc-9.2
> make -j 4
> make instal-strip
```

## 3. MPC
```
> curl -L ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz | tar xf -
> cd mpc*
> mkdir build
> cd build
> ../configure --prefix=$HOME/opt/gcc-9.2/ --with-gmp=$HOME/opt/gcc-9.2/ --with-mpfr=$HOME/opt/gcc-9.2/
> make -j 4
> make install-strip
```
## 4. ISL
```
> curl -L ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2 | tar xf -
> cd isl*
> mkdir build
> cd build
> ../configure --prefix=$HOME/opt/gcc-9.2/ --with-gmp-prefix=$HOME/opt/gcc-9.2/
> make -j 4
> make install-strip
```

# GCCのビルド
## ソースのダウンロード

まずは最新のgcc-9.2をダウンロードしてきます。

```
curl -L http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-9.2.0/gcc-9.2.0.tar.gz | tar xf -
```

## 環境変数の設定とビルド作業
一般的なLINUX環境で行われているようなconfigureだとどうもうまくいきません。試行錯誤の末に、私が行った作業を、下記に示します。そのほかの設定などについては、下記で説明します。

```
> cd gcc*
> mkdir build
> cd build
> SDKPATH=`xcrun --sdk macosx --show-sdk-path`
> echo $SDKPATH
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/

> export LIBRARY_PATH=$SDKPATH/usr/lib
> export BOOT_CFLAGS='-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/'
> export CFLAGS_FOR_TARGET=$BOOT_CFLAGS
> export CXXFLAGS_FOR_TARGET=$BOOT_CFLAGS

> ../configure --prefix=$HOME/opt/gcc-9.2/ \
  --enable-checking=release \
  --with-gmp=$HOME/opt/gcc-9.2/ \
  --with-mpfr=$HOME/opt/gcc-9.2/ \
  --with-mpc=$HOME/opt/gcc-9.2/ \
  --enable-langauges=c,c++,fortran \
  --with-isl=$HOME/opt/gcc-9.2 \
  --program-suffix=-9.2 \
  --with-native-system-header-dir=$SDKPATH/usr/include \
  --disable-bootstrap

> make -j 4
> make install
```
## configureのフラグについて
### 構成
まず、gccの構成としては、c,c++,fortranをビルドするようにしました。(`--enable-languages=c,c++,fortran`)

### システムのヘッダパスの設定
Mac OSX Catalinaでは、/usr/include/のディレクトリがありません。以前のバージョンのOSX(Mojave)では、これに関する処方箋があったようですが、これも無くなったとのことです[^1]。
本来はSDKのパスを直接参照するのは避けた方が良いようですが[^1]、gccのビルド中にシステムヘッダのパスを決め打ちで参照している箇所があるため、止むを得ず、システムヘッダの絶対パスをconfigureで渡してやる必要があるようです。
これらのシステムヘッダは、下記の場所にあります。

```
> SDKPATH=`xcrun --sdk macosx --show-sdk-path`
> ls $SDKPATH/usr/include
AppleTextureEncoder.h
AssertMacros.h
Availability.h
AvailabilityInternal.h
AvailabilityMacros.h
...(省略)
```
この場所をconfigureの際に教えてやる必要があります。(`--with-native-system-header-dir=$SDKPATH/usr/include`)

### ブートストラップの無効化

ブートストラップに関しては至る所に書かれていますが、一応簡単に説明します。

gccは通常、初めにシステムにインストールされているコンパイラ(Macの場合、XCodeのclang)でビルドされ、バイナリが作られます。この時に作られたコンパイラをgcc-Aと呼ぶこととします。
続いて、gcc-Aで自分自身をもう一度ビルドし、gccのバイナリを作成します。これを、gcc-Bと呼ぶ事とします。
さらに、gcc-Bでもう一度ビルドを行い、これが最終的にインストールされるコンパイラのバイナリとなります(gcc-Cとします）。
最後に、gcc-Cでランタイムなどのビルドが行われます。

ブートストラップはデフォルトでは有効になっていますが、単純にこれだと時間がかかるので、これをオフにしておきます（`--disable-bootstrap`）。
こうする事で、初回のビルドでできたコンパイラ(gcc-A)ですぐにランタイムのビルドが走るようになります。無事にランタイムのビルドまでできるようになれば、（気になる方は）ブートストラップを有効にして再度ビルドするという風にした方が時間の節約になるかと思います。

### 環境変数の設定
上記の`BOOT_CFLAGS, CFLAGS_FOR_TARGET,CXXFLAGS_FOR_TARGET`を設定しなければ、恐らくランタイムのビルドプロセス中、libasan.dylibのコンパイル時に下記のようなエラーで落ちます。

```
In file included from ../../../../libsanitizer/asan/asan_malloc_mac.cc:60:
../../../../libsanitizer/sanitizer_common/sanitizer_malloc_mac.inc:19:10: 致命的エラー: CoreFoundation/CFBase.h: No such file or directory
   19 | #include <CoreFoundation/CFBase.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~
コンパイルを停止しました。
```

これに対する対処として、`BOOT_CFLAGS, CFLAGS_FOR_TARGET,CXXFLAGS_FOR_TARGET`を上記のように設定し、Frameworkの格納場所を渡しました。

# 最後に

上記の手順を踏む事で、私の環境ではビルドが通りました。再度、`--disable-bootstrap`のオプションを外して、ブートストラップが有効な状態で設定・ビルドを行いましたが、こちらも通りました。

また、今回はsudoが必要になるような作業は何も行っていませんが、それでも危ない設定の仕方をしているようでしたら、誰か教えていただければ大変助かります。

[^1]: https://qiita.com/yoya/items/c0b26cba3c040c581643