MacでGCCを"正しく"環境構築しよう！

# [0] はじめに

## (1) 本記事の目的

本記事では、パッケージ管理システムであるHomebrewを用いてGCCの環境構築を行う方法を<font color="red">**どの記事よりも丁寧に**</font>解説した記事です。

GCCの環境構築におけるそれぞれの手順を詳しく説明することを心がけ、**GCCの環境構築でエラーが出ても自力で対処できる人**が増えることを目的としています。

## (2) なぜGCCを使うのか？

C言語やC++などをコンパイルする環境を提供するのがGCC（GNU Compiler Collection）やClangです。Macの場合は標準でClangのみを搭載しているため、C言語やC++などを通常の用途で利用する際は**Clangで十分です**。

ただ、自分は競技プログラミングにおいてGCCが標準で提供している特定のヘッダファイル[^7]を利用したかったため、Homebrewを利用してGCCをインストールしました。

## (3) 環境の確認

OSのバージョンは`% sw_vers`[^1]により確認することができます。参考として自分の環境での出力を以下に載せます。

自分のバージョンと比べて極端に古いまたは新しいバージョンの場合、下記の環境構築で多少の違い[^2]があるのでご注意ください。

また、本記事の内容はIntel Macを用いて確認しております。<font color="red">M1 MacではHomebrewでのパッケージのインストール先が異なるため、下記の環境構築をそのまま適用することはできません。</font>

```zsh
% sw_vers
ProductName:    macOS
ProductVersion: 11.1
BuildVersion:   20C69
```

# [1] Homebrewのインストール

本節では、Homebrewのインストールを行います。Homebrewのインストールについては、[こちらの記事](https://qiita.com/DaikiSuyama/items/5a2a96859b44595cba76)に移植したため、そちらを参照してください。

また、インストール終了後に下記のコマンドを実行し、適切に出力されるかを確認してください。出力については自分の環境のものを示しているため、バージョン等で多少の違いがあると思います。

```zsh
% brew --config
HOMEBREW_VERSION: 2.6.2
ORIGIN: https://github.com/Homebrew/brew
HEAD: 1a52862e6d24cd3bf87bec557a8886a1a825ee3c
Last commit: 7 days ago
Core tap ORIGIN: https://github.com/Homebrew/homebrew-core
Core tap HEAD: c06f553c5f07a31e06ebebf806286141e0af7e0b
Core tap last commit: 3 days ago
Core tap branch: master
HOMEBREW_PREFIX: /usr/local
HOMEBREW_CASK_OPTS: []
HOMEBREW_MAKE_JOBS: 4
Homebrew Ruby: 2.6.3 => /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby
CPU: quad-core 64-bit skylake
Clang: 12.0 build 1200
Git: 2.24.3 => /Library/Developer/CommandLineTools/usr/bin/git
Curl: 7.64.1 => /usr/bin/curl
macOS: 11.0.1-x86_64
CLT: 12.2.0.0.1.1604076827
Xcode: N/A
```

# [2] GCCのインストール

本節では、GCCのインストールを行います。

## (1) インストールの手順

下記のコマンドにより、Homebrewを通してGCCをインストールできます。

```zsh
% brew install gcc
```

## (2) インストールの確認

下記のコマンドにより、GCCがインストールされたかを確認できます。

また、`% brew list`により、Homebrewを通してインストールされたパッケージのリストが表示されます。

```zsh
% brew list | grep gcc
```

Homebrewでインストールしたパッケージは`/usr/local/Cellar`にあるため、下記のコマンドでも同様の出力となります。

```zsh
% ls /usr/local/Cellar | grep gcc
```

# [3] GCC環境への切り替え

本節では、GCC環境での**C++ファイルのコンパイル**を可能にします。Cファイルのコンパイルを行いたい場合は、下記の処理を`g++`コマンドだけでなく、`gcc`コマンドにも行う必要があります。また、下記で"コンパイラ"と記載している場合、C++コンパイラを指します。

## (1) 概説

現段階ではC++ファイルのコンパイルに用いられる`g++`コマンドを打つと、GCC環境のコンパイラではなくClang環境のコンパイラが呼び出されます。下記では、コマンドの呼び出し先を変えることで、`g++`コマンドを打つことでGCC環境のコンパイラが呼び出されるようにします。

## (2) インストールされたGCCの確認

インストール時に`/usr/local/bin`からインストールされたGCC環境のコンパイラへとシンボリックリンクが張られます。このシンボリックリンクは下記のコマンドによって確認することができます。出力は自分の環境のものです。

```zsh
% ls -l /usr/local/bin | grep g++
 g++-10 -> ../Cellar/gcc/10.2.0/bin/g++-10
 x86_64-apple-darwin20-g++-10 -> ../Cellar/gcc/10.2.0/bin/x86_64-apple-darwin20-g++-10
```

上記の`/usr/local/bin`にある`g++-{num}`というコマンドを`g++`コマンドによって呼び出すことが以降の目標となります。また、自分の環境ではnum=10ですが、環境によって変わります。

ちなみに、この段階では、インストールしたGCC環境のコンパイラは下記のコマンドで呼び出すことができます。

```zsh
% /usr/local/bin/g++-{num} hoge.cc
```

## (3) バージョンの省略

`/usr/local/bin`内に`g++`をシンボリックリンクとして作成し、リンク先に`/usr/local/bin`内の`g++-{num}`を指定することで、バージョンを省略することができます。下記のコマンドにより、このシンボリックリンクを張ることができます。

```zsh
% ln -s /usr/local/bin/g++-{num} /usr/local/bin/g++
```

また、張ったシンボリックリンクは下記のコマンドにより確認することができます。出力は自分の環境のものです。

```zsh
% ls -l /usr/local/bin | grep g++
 g++ -> /usr/local/bin/g++-10
 g++-10 -> ../Cellar/gcc/10.2.0/bin/g++-10
 x86_64-apple-darwin20-g++-10 -> ../Cellar/gcc/10.2.0/bin/x86_64-apple-darwin20-g++-10
```

ちなみに、この段階では、インストールしたGCC環境のコンパイラは下記のコマンドで呼び出すことができます。

```zsh
% /usr/local/bin/g++ hoge.cc
```

## (4) コマンド検索パスの設定

コマンド検索パスを設定すると、`/usr/local/bin/g++`を`g++`というコマンドで呼び出すことができます。コマンド検索パスを設定する[環境変数](https://ja.wikipedia.org/wiki/%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0)はPATHです。PATHは`:`によって区切られており、区切られた中で左にあるディレクトリにあるコマンドの優先順位が高いです。

まず、PATHは下記のコマンドにより出力することができます。出力は自分の環境のものです。

```zsh
% echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```

上記は自分の環境のPATHであると同時にMacのデフォルトのPATHでもあります。ここで、上記のように、`/usr/local/bin`が含まれ、`/usr/bin`よりも優先順位が高い場合は次節に移って構いません。この条件を満たさない場合、次の手順を踏む必要があります。

詳しい説明はここでは省きますが[^6]、`export PATH=/usr/local/bin:$PATH`を`~/.zshrc`に書き込んだ後に下記のコマンドを実行することで期待通りに動作するはずです。`~/.zshrc`が存在しない場合は`touch`コマンド等で作成してください。

```zsh
% source ~/.zshrc
```

以上により、インストールしたGCC環境のコンパイラは下記のコマンドで呼び出すことができるはずです。

```zsh
% g++ hoge.cc
```

# [4] `g++`コマンドの確認

上記の手順に従うことで、`g++`コマンドを用いてGCC環境でのC++ファイルのコンパイルが可能となったはずです。本節では、`g++`コマンドについていくつか確認していきます。

## (1) 実行可能な`g++`コマンド

まず、呼び出される`g++`コマンドは下記の`which`コマンドで確認することができます。また、`-a`オプションを用いると、**実行可能な任意の**`g++`コマンドを確認することができます。ここまでの手順に従っていれば、いずれも同じ出力になるはずです。

```zsh
% which g++
/usr/local/bin/g++
% which -a g++
/usr/local/bin/g++
/usr/bin/g++
```

## (2) GCC環境とClang環境

さらに、`/usr/local/bin/g++`はインストールしたGCC環境のC++コンパイラを指し、`/usr/bin/g++`はすでにインストールされているClang環境のC++コンパイラ[^10]を指します。また、それぞれのコンパイラの情報については下記のコマンドで確認することができます。出力は自分の環境のものです。

```zsh:GCC環境のC++コンパイラ
% /usr/local/bin/g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc/10.2.0/libexec/gcc/x86_64-apple-darwin20/10.2.0/lto-wrapper
Target: x86_64-apple-darwin20
Configured with: ../configure --build=x86_64-apple-darwin20 --prefix=/usr/local/Cellar/gcc/10.2.0 --libdir=/usr/local/Cellar/gcc/10.2.0/lib/gcc/10 --disable-nls --enable-checking=release --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-10 --with-gmp=/usr/local/opt/gmp --with-mpfr=/usr/local/opt/mpfr --with-mpc=/usr/local/opt/libmpc --with-isl=/usr/local/opt/isl --with-system-zlib --with-pkgversion='Homebrew GCC 10.2.0' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --disable-multilib --with-native-system-header-dir=/usr/include --with-sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX11.0.sdk SED=/usr/bin/sed
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.2.0 (Homebrew GCC 10.2.0) 
```

```zsh:Clang環境のC++コンパイラ
% /usr/bin/g++ -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: x86_64-apple-darwin20.2.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
```

# [5] コマンドや語句の説明

（別記事に移植予定です。）

1. `ls`
    - パスで指定したディレクトリの内部のファイル及びディレクトリの一覧を出力するコマンド
    - `-l`引数を加えると長いフォーマットでの表示になり、シンボリックリンクが張られる場合は右側に矢印で表示される
2. `|`
    - パイプラインと呼ばれ、別のコマンドに出力を渡す働きをする。
3. `grep`
    - 指定したパターンの文字列のみを出力する。
    - `% grep 〇〇`とした場合は〇〇が含まれる文字列のみを出力する。
4. シンボリックリンク
    - ファイルやディレクトリを参照するファイルのこと。
    - [ソフトリンク](https://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%83%AA%E3%83%B3%E3%82%AF)の一種である。


[^1]: これ以降、`% コマンド名`で実行するコマンドを示します。シェルによっては`%`が`$`ですが、適宜読み替えてください。

[^2]: インストール先のディレクトリやインストールされるGCCのバージョンの違いなど

[^3]: コマンドのオンラインマニュアルページを表示するコマンド

[^4]: Homebrewの概要を把握するには[homebrewとは何者か。仕組みについて調べてみた](https://qiita.com/omega999/items/6f65217b81ad3fffe7e6)が役に立ちます。

[^6]: 後日、PATH関連の記事を投稿予定です。

[^7]: `bits/stdc++.h`のことです。`bits/stdc++.h`の使い方については[こちらの記事](https://qiita.com/DaikiSuyama/items/e502e09a1090f4a2cee3)を参照してください。

[^10]: CommandLineToolsの一部としてインストールされたものです。