自分のことをGCCと思い込むClang。【西田の戯言。】

今回の記事はMac限定で起きる問題の話。問題というか仕様。

Macでは標準でLLVMが搭載されており、C用のフロントエンドとしてClang、C++用としてClang++が、Xcode Command Line Tools(CLT)をインストールした段階で使えるようになっているはずです。しかし、おもに競技プログラミングなどの影響によりClangではなくGCCが必要な場面があるかと思われます。そうしたときにMacだととんでもない問題に出くわすことになります。

問題

どんな問題かというと、gccコマンドを実行すると、Clangが呼び出されるという問題。ちなみに後述しますが、これはバグではなく仕様です。

CLTインストール後の状態のMacでgccコマンドを実行。Clangが呼び出されていることがわかる。

上の画像は、CLTをインストールしたMacでgccコマンドを実行した結果です。clangコマンドが呼び出されていることがわかります。これがいわゆる「自分のことをGCCと思い込んでいるClang」です。ちなみに、C++用のg++でもClang++が呼び出されます。恐ろしいですね。

原因

この先は、HomebrewでGCCをインストールした前提で話を進めます。なお、GCCのバージョンは14です。また、Apple Silicon Macを使用している前提で話を進めます。Intel Macの場合、ディレクトリが若干異なります。
ダラダラと原因特定のフェーズを続けます。解決法はつぎの節まで飛んでください。

さて、原因を特定していきましょう。

まず、いまあたってるgccコマンドが、どこにあるのかというところから見ていきます。

ターミナルを開いて、which gccと実行してみましょう。

すると/usr/bin/gccにあたっているようです。

他方で、Homebrewからインストールしたgccはどこにあるのか。これはネタバレしてしまうと、エイリアス自体は/opt/homebrew/binにあります。見に行きましょう。

Macには非常に便利なopenコマンドがあります。open /opt/homebrew/binを実行。するとFinderが開かれます。

/opt/homebrew/binをFinderで開いた(gccとg++を選択)

見ますと、gccとg++にはそれぞれバージョンのサフィックスが入ったgcc-14g++-14というエイリアスが作成されていますね。ということは。

gcc-14コマンドを実行。gccが実行された

gcc-14というコマンドを実行すると正真正銘のGCCが実行されました。

Homebrewでは過去のGCCをインストールすること自体も可能であるため、サフィックスをつけて管理しています。例えば、brew install gcc@13を実行することで、GCC v13.3(本稿執筆時点)がインストールされます。

解決法

そのままGCC-14で使う

解決法その1は、そのままgcc-14コマンドを使い続けることです。まあ、これが多分いちばん正しい使い方。

それに、何らかの理由で他のバージョンも並行して使うのであれば、この使い方がマストとなります。

gccコマンドを置き換える

こだわりがあるのであれば、gccコマンドを置き換えることにしましょう。

まず、/opt/homebrew/binのパスが/usr/binよりも優先されるように変更します。具体的には、~/.zshrcを弄ります。

VimやVSCodeなどで、~/.zshrcを開き、export PATH=から始まる行を探します。なければ作ります。

そして、この行のPATH=の直後に/opt/homebrew/binを書き足してあげます。

この行では、コマンドを実行するとき、どのパスをどの順番に見ていくのかを設定しています。俗に「パスを通す」という行為をしているわけです。

この行に記述したパス内にある実行可能なファイルは、絶対パスあるいは相対パスを指定しなくとも、ファイル名のみで実行する事ができます。

基本的に、この行の左(先頭)に行けば行くほど優先度が高く、同名のファイルがあった場合、そちら側が優先されます。デフォルトの場合、gccという名前のclangがあるディレクトリが、Homebrewのgccよりも優先度が高いため、gccが実行されるよりも前にclangが実行されてしまうのです。

なお、.zshrcを編集した後は

$ source ~/.zshrc

を実行することで設定が反映されます。

clangは消さないほうがいい

gccを入れた後、もう不要だからとclangを消してしまうのはおすすめできません。

ClangはXcode向けに最適化されている可能性があり、またXcodeなどがコンパイラにClangというかLLVMを使用しているので、特に理由がなければClangも残しておくことをおすすめします。


この記事を書いた人

西田(総合情報学部 情報学科 2021年入学)

通信研究会OB。当ホームページの保守運用を支援しています。組み込み系のソフトウェアエンジニア。応用情報技術者・修習技術者。