macOSのEmacsでnative-
compエラーが出た

macOS上でEmacs(30系)を使っていたら、パッケージの読み込み時に大量の Warning が出ました。
テーマや vterm など、普段から使っているものばかりです。

結局、native-comp を完全に無効化することにしました。
回り道をした分、libgccjit の問題についてわかったこともあるので、その経緯を共有します。

(setq native-comp-jit-compilation nil)
(setq native-comp-deferred-compilation nil)

関連記事

1. 発生していたエラーと状況(native-comp)

表示されていたエラーは、次のような内容でした。

Warning (native-compiler): clang: error: invalid version number in '-mmacosx-version-min=14.0'
Warning (native-compiler): libgccjit.so: error: error invoking gcc driver
Warning (native-compiler): ~/.emacs.d/elpa/kanagawa-themes-20260102.1542/kanagawa-themes.el: Error Internal native compiler error: "failed to compile", "~/.emacs.d/eln-cache/30_2-3f95cdce/kanagawa-themes-5996306b-55a81a3e.eln", "error invoking gcc driver"
Warning (native-compiler): ~/.emacs.d/elpa/vterm-20251119.1653/vterm.el: Error Internal native compiler error: "failed to compile", "~/.emacs.d/eln-cache/30_2-3f95cdce/vterm-422728f3-6c65dfac.eln", "error invoking gcc driver"Code language: JavaScript (javascript)

複数の ELPA パッケージで同様の警告が繰り返し出ていました。

! 発生したエラーと状況 native-comp とは Emacs Lispをネイティブコードに変換して高速化 エラー内容 • clang: invalid version number • libgccjit.so: error invoking gcc driver • failed to compile 開発環境の問題 Command Line Tools

ここで出てくる「native-comp」は、Emacs が Lisp をネイティブコードに変換して高速化する仕組みです。
裏側ではC コンパイラ(clang や gcc)や libgccjit というライブラリが使われています1

つまり、Emacs 単体の問題というより、「Emacs が使おうとしている macOS の開発環境」に何か起きている可能性が高そうでした。

2. clang と macOS バージョン

最初に目についたのが、この一行です。

invalid version number in '-mmacosx-version-min=14.0'Code language: JavaScript (javascript)
clangとmacOSバージョンの不整合 invalid version number in -mmacosx-version-min=14.0 Command Line Tools 古い/不整合 macOS 14.0 新しい要求 考えられる原因 • Command Line Toolsが古い • OSアップデート後の不整合

これは「最小対応 macOS バージョンとして 14.0 を指定しているけれど、今使っている clang がそれを正しく扱えない」という意味です2

ここから私は、

  • Command Line Tools が古いまま残っている
  • Xcode 周りの設定が中途半端になっている
  • OS アップデート後にツールチェーンがズレた

2.1. Command Line Tools の入れ直し

そこで、Command Line Tools を一度まっさらにして入れ直すことにしました。

既存の Command Line Tools を削除しました3

sudo rm -rf /Library/Developer/CommandLineTools

少し強引な操作ですが、次に、xcode-select をリセットします。

sudo xcode-select --reset

その後、改めてインストールします4

xcode-select --install

すると、GUIでインストールが進みます。
これで、今の macOS バージョンに対応した clang や SDK が入り直されます。

2.1. Command Line Tools の入れ直し

この時点で、clang のバージョン確認をしておくと安心です。

clang -v
2.1. Command Line Tools の入れ直し

2.2. gcc と libgccjit も入れ直した

エラーには、clang だけでなく libgccjitgcc driver という言葉も出ていました。

Emacs の native-comp は、内部で libgccjit を使って gcc を呼び出します5
そのため、Homebrew で入れた gcc 周りが壊れている可能性も考えました。

gccとlibgccjitの再インストール native-compの依存関係 Emacsはlibgccjitを使ってgccを呼び出す Homebrewで再インストール brew install gcc libgccjit brew reinstall gcc libgccjit ※依存関係のズレやリンク切れを解消

そこで、次の操作を行いました。

brew install gcc libgccjit
brew reinstall gcc libgccjit

すでに入っていたとしても、再インストールすることでリンク切れや依存関係のズレが解消されることがあります。

2.3. eln-cache を消した

もう一つやったことがあります。

rm -rf ~/.emacs.d/eln-cache/Code language: JavaScript (javascript)

eln-cache には、native-comp によって生成されたバイナリが入っています6
一度失敗した状態のファイルが残っていると、修復後も警告が出続けることがあります7

eln-cacheの削除 eln-cache とは native-compで生成されたバイナリを保存 失敗したファイルが残ると警告が出続ける 削除コマンド rm -rf ~/.emacs.d/eln-cache/

これは「ビルド成果物を消す」ようなものなので、消しても大丈夫です。

3. 【追記】Emacs で native-comp エラーが消えない

エラーが出なくなったと思っていましたが、それはemacsclientから起動していただけでした。
emacsサーバを起動するタイミングでは、やはりnative-compができないエラーになりました。

3.1. libgccjit があっても動かない

最初は「libgccjit をインストールすれば解決する」と思ったのですが、話はそう単純ではありませんでした。

もう少し詳しく調べると、エラーの内容はこうでした。

ld: library not found for -lemutls_w
libgccjit.so: error: error invoking gcc driver
Code language: HTTP (http)

これは、libgccjit が内部で gcc を使ってコンパイルしようとしたときに、リンカ(linker)が -lemutls_w というライブラリを見つけられないというエラーです。
emutls_w は、GCC がスレッドローカルストレージ(Thread Local Storage、スレッドごとに独立した変数領域)を扱うために使うライブラリなのですが、macOS の標準環境には存在しないのです8

3.2. configure の段階で問題が起きる

native-comp を有効にして Emacs をビルドしようとすると、configure の段階でテストに失敗します9

checking for gcc_jit_context_acquire in -lgccjit... yes
checking for libgccjit.h... yes
configure: error: The installed libgccjit failed to compile and run a test program
Code language: CSS (css)

libgccjit のライブラリもヘッダーファイルも見つかっているのに、テストプログラムの実行に失敗する。
これは何が起きているのか。

configure のログを見ると、dyld(dynamic linker、動的リンカ)がライブラリをロードできないというエラーが記録されていました。

dyld: Library not loaded: @rpath/libgccjit.0.dylib
Reason: no LC_RPATH's found
Code language: HTTP (http)

macOS では、ダイナミックリンクされたライブラリを実行時に探すために @rpath という仕組みを使います10
これは実行ファイルに埋め込まれた相対パスの情報なのですが、この設定が正しくないとライブラリが見つからないわけです。

3.3. macOS + Homebrew の環境制約

ここまで調べて気づいたのは、これは設定の問題ではなく、macOS と Homebrew の環境における構造的な制約だということです。

libgccjit 自体は Homebrew でインストールできます。
でも、それが Emacs の native-comp で実際に使える状態になるかというと、そうではない。
ダイナミックリンクの設定、GCC の内部ライブラリの配置、macOS 特有のシステムライブラリの違いなど、複数の問題が重なっています。

実際、emacs-plus のリポジトリには同様の問題を報告する Issue が大量にあります。
人によっては、カスタムの tap(サードパーティのリポジトリ)を使ったり、環境変数を細かく調整したりして動かせたケースもあるようですが、それでも macOS のバージョンが変わったり gcc が更新されたりすると、また動かなくなる、という状況が繰り返されています11

4. 結論:native-comp を無効化した

色々と試行錯誤しましたが、最終的には「native-comp を使わない」という選択をしました。

init.el に以下の設定を追加します。

(setq native-comp-jit-compilation nil)
(setq native-comp-deferred-compilation nil)
  • native-comp-jit-compilation は、実行時の JIT(Just-In-Time)コンパイルを制御する変数です。これを nil に設定することで、Elisp を実行するときに動的にネイティブコンパイルしようとする動作を止めます。
  • native-comp-deferred-compilation は、バックグラウンドでの遅延コンパイル(deferred compilation)を制御します。通常、Emacs は起動後にバックグラウンドプロセスで Elisp ファイルを順次コンパイルしていくのですが、これも無効化します。

この設定を追加すると、native-comp 関連のエラーは完全に消えました。

native-comp は確かに Elisp の実行速度を向上させる機能です。でも、無効化したからといって Emacs が使えなくなるわけではありません。

  1. native-compはEmacs 28から正式に導入された機能で、Emacs Lispをlibgccjitを使ってネイティブコードにコンパイルすることで、バイトコンパイルと比較して2.5〜5倍のパフォーマンス向上を実現します。Andrea Coralloによって開発されました。 – EmacsWiki: GccEmacs
  2. -mmacosx-version-minフラグは、コンパイル時に最小サポートmacOSバージョンを指定するためのclangオプションです。古いCommand Line Toolsや不整合な状態では、このフラグが正しく処理されず、互換性エラーが発生します。 – How to support old OSX version with a recent xcode
  3. Command Line Toolsは、Xcodeとは別にインストールできる、macOS SDKとclangなどのコマンドラインツールを含む開発環境パッケージです。/Library/Developer/CommandLineToolsにインストールされます。 – Technical Note TN2339: Building from the Command Line with Xcode FAQ
  4. xcode-select –installコマンドは、古いバージョンをインストールする傾向があるため、インストール後にSoftware Updateで最新版を確認することが推奨されます。 – macOS Monterey — command line tools — brew and Xcode disagree
  5. libgccjitはGCCの一部で、プログラムがGCCコンパイラをライブラリとして利用できるようにするJIT(Just-In-Time)コンパイルライブラリです。Emacsがnative-compでEmacsLispをネイティブコードに変換する際に必要です。 – Native Compilation (GNU Emacs Lisp Reference Manual)
  6. eln-cacheディレクトリには、native-compによって生成された.elnファイル(ネイティブコンパイル済みのEmacsLispバイナリ)が保存されます。デフォルトでは~/.emacs.d/eln-cache/配下に配置され、アーキテクチャとEmacs設定によってサブディレクトリが作成されます。 – gccemacs
  7. eln-cacheを削除しても安全です。必要なファイルはEmacsが自動的に再コンパイルします。ただし、最後のエントリ(システムキャッシュディレクトリ)は削除しないよう注意してください。 – gccemacs
  8. emutls(Emulated Thread Local Storage)は、ネイティブな TLS をサポートしていない環境で GCC がスレッドローカル変数を実現するために使用するライブラリです。macOS では Apple の toolchain が独自の TLS 実装を持つため、GCC の emutls ライブラリが標準では提供されていません。 – Installation fails with libgccjit (and possibly gcc) 14.1.0 recent release
  9. この問題は emacs-plus リポジトリで継続的に報告されており、2022年から2024年にかけて複数のバージョン(gcc 12.1.0, 14.1.0, libgccjit の各バージョン)で同様のエラーが発生しています。 – Installation fails with libgccjit (and possibly gcc) 12.1.0 recent releaseBuild Failure: The installed libgccjit failed to compile and run
  10. @rpath(Run-path dependent library)は macOS の dyld が使用する動的ライブラリの検索パスで、実行ファイルや共有ライブラリに LC_RPATH ロードコマンドとして埋め込まれます。この情報が正しく設定されていないと、実行時にライブラリが見つからないエラーが発生します。 – Software linked against libgccjit no longer works after upgrade to 14.1.0
  11. 成功例として報告されているのは、catesandrew/tap という非公式リポジトリから gcc と libgccjit をインストールし、CPATH と LIBRARY_PATH 環境変数を設定する方法です。ただし、この方法も macOS のバージョンアップや gcc の更新により動作しなくなる可能性があります。 – Solution to native-comp installation on Apple Silicone