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 のサブセットで、
git、make、clang(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 の下でライセンスされています。