[macOS Monterey] ClangからGCCへの切り替え 

## 競プロを始めようと思って
手持ちのMacbookに環境構築を進めていました。 
C++のコンパイラ周りで困ったことがあったのでメモ。

## 環境
- Macbook Pro (13-inch, M1, 2020)
- macOS Monterey 12.2
- gcc 11.2.0 (Homebrew GCC 11.2.0_3)
- Apple clang version 12.0.5 (clang-1205.0.22.9)

## tl;dr
- ClangからGCCに切り替えた
- `#include<bits/stdc++.h>`を含むcppファイルをコンパイルしたら`error: assert.h: No such file or directory`の怒られが発生
- `export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)`　←　**結論**

長くなったので結論までの流れをコンパクトにまとめました（えらい）
ちなみにですがClangでも普段なんら困ることはないみたいなので,面倒なのが嫌な人はここまでにしましょう。

## GCCのインストールとClangからの切り替え
別にこだわりはなかったんですが，競プロで等でよく見かけるヘッダ（`bits/stdc++.h`）を提供しているのがGCCだったりしたのでMac標準(?)のClangではなくてGCCを利用することにしました。
インストールは`brew install gcc`。（Intel MacとM1 MacではHomebrewを使ったパッケージのインストール先が異なるので注意）

次に，まだこの段階ではClangが呼び出されてしまう`gcc`と`g++`それぞれのコマンドでGCCが呼び出されるように切り替えます。
`brew`コマンドでインストールされたGCCは`/opt/homebrew/Cellar/`に入っているのですが，インストールが済んだ時点で自動的に`/opt/homebrew/bin/`からシンボリックリンクが張られているので`ls -l .. | grep ..`コマンドで確認。

```terminal:Terminal
$ ls -l /opt/homebrew/bin | grep gcc
... gcc-11 -> ../Cellar/gcc/11.2.0_3/bin/gcc-11
$ ls -l /opt/homebrew/bin | grep g++
... g++-11 -> ../Cellar/gcc/11.2.0_3/bin/g++-11
```
上の`gcc-11/g++-11`がそうです（実際にはgcc/g++を含む他の結果も表示されます）。
（↑ 11という数字はインストールされた時点でのバージョンによるので適宜読み替えてください）
つまり，この時点で (`opt/homebrew/bin`にパスが通っていれば) `gcc-11`と`g++-11`のコマンドでGCCを呼び出せるわけです。

毎度バージョンを入力するのも面倒なので，`ln -fs`コマンドでバージョンを省略した名前のシンボリックリンクを張っておきます（`-fs`はシンボリックリンクを作成して，同名のリンクファイルが既にある場合に削除してねというお願いをするオプションです）。

```terminal:Terminal
$ ln -fs /opt/homebrew/bin/gcc-11 /opt/homebrew/bin/gcc  
$ ln -fs /opt/homebrew/bin/g++-11 /opt/homebrew/bin/g++     
```

ここで`which`コマンドを使って各コマンドからどのファイルが呼び出されているか確認します。

```terminal:Terminal
$ which gcc
/opt/homebrew/bin/gcc
$ which g++
/opt/homebrew/bin/g++
```
このように先ほど指定したシンボリックリンクのファイルが呼び出されていればOKです。
まだ`/usr/bin/gcc`，`/usr/bin/g++`が表示されている場合，

- `/opt/homebrew/bin/`よりも`/usr/bin/`の方がパスの優先度が高い
- そもそも`opt/homebrew/bin/`にパスが通っていない

コマンド実行時OSのシェルは，パスが通っている（登録されている）ディレクトリを優先度の高い順に探します。
以下のコマンドで`/opt/homebrew/bin/`にパスを通します。
（~/.zshrcがない場合は`touch ~/.zshrc`をしてから），　``echo "export PATH=/opt/homebrew/bin:$PATH" >> ~/.zshrc``
これを実行して，`source ~/.zshrc`で設定を再度読み込めばOKです。

## 使ってみる
意気揚々と`#include<bits/stdc++.h>`したcppファイルをコンパイルしたら，以下の怒られが発生してしまいました。

```terminal:Terminal
＄ g++ main.cpp
In file included from /opt/homebrew/Cellar/gcc/11.2.0_3/include/c++/11/aarch64-apple-darwin21/bits/stdc++.h:33,
                 from a.cpp:2:
/opt/homebrew/Cellar/gcc/11.2.0_3/include/c++/11/cassert:44:10: fatal error: assert.h: No such file or directory
   44 | #include <assert.h>
      |          ^~~~~~~~~~
compilation terminated.
```

この問題，色々調べて勉強になったのですが，[こちらの記事][link-1]が詳しくて分かりやすかったので参考にさせていただきました。感謝。
Xcodeのアップデートに伴ってヘッダーファイル等の参照すべきフォルダが変わっているということのようです。

> The Command Line Tools package installs the macOS system headers inside the macOS SDK. 
> The command line tools will search the SDK for system headers by default. However, some software may fail to build correctly against the SDK and require macOS headers to be installed in the base system under /usr/include. If you are the maintainer of such software, we encourage you to update your project to work with the SDK or file a bug report for issues that are preventing you from doing so. 
- [Xcode 10 Release Notes](https://developer.apple.com/documentation/xcode-release-notes/xcode-10-release-notes#3035624)

macOS SDKにシステムヘッダとか入ってるからそっちを参照するようにしてくれと。 
元々は`/usr/include`というフォルダがあったけど無くなってしまったらしいです。

で，これは環境変数`SDKROOT`を設定することで解決することができるようです。

```terminal:Terminal
$ g++ main.cpp
In file included from /opt/homebrew/Cellar/gcc/11.2.0_3/include/c++/11/aarch64-apple-darwin21/bits/stdc++.h:33,
                 from a.cpp:2:
/opt/homebrew/Cellar/gcc/11.2.0_3/include/c++/11/cassert:44:10: fatal error: assert.h: No such file or directory
   44 | #include <assert.h>
      |          ^~~~~~~~~~
compilation terminated.
$ export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)"
$ g++ main.cpp
$ ls
a.out main.cpp
```
`SDKROOT`の設定の後はヘッダファイルの参照エラーが解消し，無事コンパイルできました！
こちらの変更も``echo "export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)" >> ~/.zshrc``しておきましょう。

## 感想
 ~~Clangで良かったんじゃねえか...~~いや非常に勉強になって楽しかったです。
（SDKROOTの環境変数設定したのちゃんと覚えておかないと後々困ることがありそうな気がする）

*Qiitaに類するサービスを含め記事の投稿が初めてなので間違いや分かりづらい点が多々あるかと思いますのでご指摘いただけるととても嬉しいです。

## 参考

[macOS Catalina(10.15) の Xcode11 だと /usr/include が無い][link-1]


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