錦です。
今回は、M1 MacにGCCを入れてC++の開発環境を整える方法というか、最近発覚したことをまとめてご紹介します。
環境
まず、私の環境ですが、
- MacBook Air Late 2020(M1/8C GPU/16GB RAM)
- macOS Ventura 13.0.1
となります。今回の話は、Xcode Command Line Toolsがインストールされ、Xcodeをインストールした時にClangがインストールされている状態で話をします。また、Homebrewがインストールされ、Homebrewによってgccがインストールされていることを前提とします。と言ってもbrew入れてbrew install gcc
するまでを前提として話します。
もしかしたら、Xcode Command Line Toolsは入れたけど、Xcodeを入れていないという方もいるかも知れませんが、その方は私と同じ状態に陥ると単純にgcc/g++コマンドが使えないという状態に陥っているのではないでしょうか。そういった方もおそらく役に立つかと思います。
経緯
経緯は、g++コマンドを用いて競プロしようとしたらbits/stdc++.hが使えねぇって気づいて、これgccじゃねぇって気づいたというもの。
一応、gccをインストールして、パスをClangより優先してたんですが、そのパスに"gcc"と"g++"というものが存在しなかったというのが今回の問題です。
解決法
- gccを使うときに
gcc-12
コマンドまたはg++-12
コマンドを使う(gcc/g++コマンドでは引き続きClangが呼び出される) - パスが通っているエイリアスの名前を変える(gcc/g++コマンドでgccが呼び出されるようになる)
この12というのはバージョン数です。もし別のバージョンだったらこの数字を変えてください。本稿執筆時点では大概の場合12だと思います。
以下、2つ目の解説をします。
まず、gcc-12のエイリアスがある場所を調べます。Homebrewでgccをインストールされているなら
$ which gcc-12
を実行することでパスが帰ってくると思います。私の環境では/opt/homebrew/bin/gcc-12
というのが帰ってきました。今回はこのファイルがあるディレクトリをFinderで開きたいので、さっきのパスから"gcc-12"の部分を消してOpenコマンド*1を使います。
なお、この時、~/.zshrcでClangのパスよりも、今回開くパスが優先的に通っていることを確認してください(例:export $PATH=/opt/homebrew/bin/:/opt/local/bin:$PATH
詳細は本稿最後の項目「パスの通し方」を確認してください)。
$ open /opt/homebrew/bin/
gccの場所は環境によって異なるかもしれませんが私の場合だったら/opt/homebrew/bin/
にある「g++-12」「gcc-12」というエイリアスがあります。それの名前を「gcc」、「g++」に変更してあげると使えると思います。なお、この時、clangがあるディレクトリよりここのディレクトリへのパスの優先度が高い必要があります。
こちらの画像はg++で解説します。画像で、青で強調されている右側がもとからある「g++-12」というエイリアス、今回私はこれをコピーしてから「g++」という名前に変えました。多分コピーせずに名前を変更しても問題はないです。
これで、g++コマンドでg++が呼び出されていたら問題は解決。以上。お疲れさまでした。
成功例:
$ gcc gcc: fatal error: no input files compilation terminated.
失敗例(Clangにパスが通っている):
$ gcc clang: fatal error: no input files
原因
原因というのはHomebrewでインストールしたら作成されるエイリアスが「g++-12」や「gcc-12」となっているためです。以上
Xcode付属のClang
Xcodeに付属するClangは、Xcodeをインストールしている時点でパスが通ります。ただ、このパスの通り方が厄介で、clangやclang++コマンドと共に、gccコマンドやg++コマンドもclangが動作するように置き換えます(というよりも、Xcodeインストール時に通ったパスのディレクトリの中にg++やgccという名前のclang実行ファイルがある)。
多くの解説記事では、解決法で提示したディレクトリのパスを、Xcode付属Clangのパスより優先的に通す(~/.zshrcのPATHでは左(先頭)側にあるパスのほうが優先度が高くなる)ことでclangではなくg++が動作するようになるという話でしたが、実際に私の環境ではうまく行かず、whichコマンドで色々探っていると結果がわかりました。
追記(2024/1/15)
この記事が結構皆さんの役に立ってるらしく、光栄です。
追記で、gccをアップデートした場合のことをお話します。今回の方法で新しく作ったエイリアスの参照ファイルはgcc-12
あるいはg++-12
に参照されていることになります。残念ながら、Homebrewでgccをアップデートしても参照ファイルの書き換え自体は行われません。
つまり、gcc-12
というファイルが存在しないため、gccコマンドを実行すると、またclangが呼び出されることになります。
この際は、Finderで/opt/homebrew/bin/
を開き、今回作ったエイリアス(gcc
とg++
)を消して、gcc-13
とg++-13
をコピーして、それぞれまたgcc
とg++
とファイル名を変えて上げれば動きます。
gccのアップデートの間隔は1年以上なので何回もやることではないはずです。間もなくgcc 14がリリースされるようですが。
パスの通し方
最後にこの記事の付録みたいな形でパスの通し方を解説しておきます。
パスとは、設定したディレクトリにあるファイルをそこに行き着くまでの相対パス・絶対パスを指定せずとも実行する事ができるようになるものです。例えば、/a/bにあるhogeという実行ファイルを実行したい場合、パスを通していなければ/a/b/hoge
または相対パスを用いて場所を指定して実行する必要がありますが、/a/b/にパスを通すことでどのディレクトリにいてもhoge
と打つだけで実行できます。これでコマンドを作成することができるわけです。
ホームディレクトリ下に.zshrcというファイルを設置します(設置されている場合はそれを編集します)。正直、ホームディレクトリがどこかわからねぇという場合もVSCodeを使う前提で以下のコマンドを実行して保存すれば作成・編集できます。別にこれは編集できればVimでもemacsでも何でも構いません。
$ code ~/.zshrc
そして、.zshrcの中に
export PATH=/opt/homebrew/bin:$PATH
と書いて上げればパスが通ります。複数のディレクトリを通す場合は、ディレクトリを:で区切ります。今回の場合を私の環境で記述すると
となります。この時、左側(先頭側)のほうが優先的になります。この優先とは同じコマンドになった時に優先されるということを意味します。今回の問題を解決した後、/opt/homebrew/bin
と/opt/local/bin
の両方にgccとg++のコマンドが存在することになりましたが、前者のほうが左側にあるので優先されます。
なお、.zshrcを編集した後は
$ source ~/.zshrc
を実行することで設定が反映されます。
これだけです。ちなみに、パスを通した後、どのコマンドにどのパスが通っているのかは、which {調べたいコマンド}
で調べることができます。
*1:Mac特有のコマンド。ダブルクリックに相当