投稿

brew の Python 3.14 で pyexpat の Symbol not found が出たらソースビルドで直す

brew の Python 3.14 で pyexpat の Symbol not found が出たらソースビルドで直す

TL;DR

  • brew upgrade で Python 3.14 に上がった後、aws コマンドが Symbol not found: _XML_SetAllocTrackerActivationThreshold で死ぬ
  • brew reinstall --build-from-source python@3.14 でソースビルドすれば直る
  • 再発防止に brew pin python@3.14

エラー内容

ImportError: dlopen(.../pyexpat.cpython-314-darwin.so, 0x0002): Symbol not found: _XML_SetAllocTrackerActivationThreshold Referenced from: .../pyexpat.cpython-314-darwin.so Expected in: /usr/lib/libexpat.1.dylib

aws だけでなく Python 3.14 の xml モジュールを使う全ツールに影響する。

原因

brew のビルド済みボトル(バイナリ配布)の pyexpat.so が expat 2.7+ の新シンボルに依存しているが、macOS のシステムライブラリ /usr/lib/libexpat.1.dylib にはそのシンボルが存在しない。

otool -L $(python3.14 -c "import _pyexpat; print(_pyexpat.__file__)") # /usr/lib/libexpat.1.dylib にリンクされている(brew の expat ではなくシステム版)

試したこと(全部ダメだった)

1. brew reinstall 系

方法 結果
brew reinstall python@3.14 同じボトルが入るだけ
brew reinstall expat pyexpat のリンク先は変わらない
brew reinstall awscli 依存の python@3.14 は変わらない

全て同じビルド済みボトルが再インストールされるだけなので、リンク先は変わらない。

2. Command Line Tools の更新

「システムライブラリが古いなら、Command Line Tools を更新すれば新しくなるのでは?」と考えた。

sudo xcode-select --install # → "already installed" と言われる softwareupdate --list # → アップデートなし softwareupdate --install "Command Line Tools for Xcode-26.3" # → "No such update"

どれも効かず、結局 Command Line Tools を削除して再インストール:

sudo rm -rf /Library/Developer/CommandLineTools sudo xcode-select --install

しかし xcode-select --install でポップアップが出ないケースがあり、developer.apple.com/download/all/ から手動で .dmg をダウンロードした。

注意: 同じページに Xcode 本体(数GB)もあるが、必要なのは Command Line Tools for Xcode(200MB程度の .dmg) だけ。

結果: Command Line Tools 26.3 をインストールしたが、システムの expat は更新されず、問題は解消しなかった

そもそも Command Line Tools / Xcode とは

  • Xcode は Apple の公式 IDE。iPhone / Mac アプリ開発向け
  • Command Line Tools は Xcode のサブセットで、gitmakeclang(Cコンパイラ)、システムヘッダ(SDK) が含まれる
  • システムヘッダ(SDK)は macOS の機能(ファイル操作、ネットワーク等)にアクセスするための API 定義ファイル
  • brew でパッケージをソースビルドする際に C コンパイラとこれらのヘッダが必要になるため、Web 開発でも間接的に必要
  • Linux の apt install build-essential に相当するが、macOS では Apple が一括管理しており個別インストールはできない

解決手順

# ソースからビルド(7分程度) brew reinstall --build-from-source python@3.14 # 動作確認 aws --version # 再発防止 brew pin python@3.14

ソースビルドでは --with-system-expat フラグによりローカル環境の expat に合わせてコンパイルされるため、シンボル不整合が解消される。

教訓

  • brew upgrade はメジャーバージョンの Python も上げてしまう。依存が多いパッケージは brew pin で固定しておく
  • ビルド済みボトルはビルド環境とユーザー環境の差異で壊れることがある。--build-from-source は最終手段として有効
  • Command Line Tools の更新ではシステムの動的ライブラリ(/usr/lib/ 配下)は更新されない場合がある
この投稿は投稿者によって CC BY 4.0 の下でライセンスされています。

トレンドのタグ