目的
brew upgradeの実行後にPHP7.4が使えなくなりました。解決に苦労したので、その手順を書き残しておきます。
裏技的な方法なのであまり推奨はできませんが、参考になれば幸いです。
動作環境
- MacBook Air M1 2020
- macOS Ventura 13.2.1
- Homebrew 3.5.4
- PHPはHomebrewのパッケージphp@7.4を使用
% php -v
PHP 7.4.30 (cli) (built: Jun  9 2022 09:20:03) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v3.1.4, Copyright (c) 2002-2022, by Derick Rethans
    with Zend OPcache v7.4.30, Copyright (c), by Zend Technologies
% which php
/opt/homebrew/opt/php@7.4/bin/php
Homebrewのアップグレード
Homebrewのバージョンを3.5.4から4.0.6へアップグレードします。今回はupdateではなくupgradeを使用し、パッケージの更新も合わせて実行しました。
% brew -v
Homebrew 3.5.4
Homebrew/homebrew-core (git revision 6ffb2a2c25e; last commit 2022-07-18)
エラーが発生したので、メッセージの指示通りxcode-selectのインストールを実行します。
% brew upgrade
Error: No developer tools installed.
Install the Command Line Tools:
  xcode-select --install
コマンドを実行するとポップアップが表示されるので「インストール」をクリックします。
% xcode-select --install
xcode-select: note: install requested for command line developer tools

「ソフトウェアがインストールされました。」が表示されれば、xcode-selectのインストールは完了です。
再度brew upgradeを実行します。時間がかかるので気長に待ちます。
% brew upgrade
PHP7.4が使えなくなった
php -vを実行したところ、エラーが発生しました。icu4cライブラリの参照で失敗しているようです。参照先のパスからicu4cはHomebrewのパッケージと分かります。
% php -v
dyld[69930]: Library not loaded: /opt/homebrew/opt/icu4c/lib/libicuio.70.dylib
  Referenced from: <31116583-6CB3-3C7B-AD46-52FF1431267E> /opt/homebrew/Cellar/php@7.4/7.4.30/bin/php
  Reason: tried: '/opt/homebrew/opt/icu4c/lib/libicuio.70.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/opt/icu4c/lib/libicuio.70.dylib' (no such file), '/opt/homebrew/opt/icu4c/lib/libicuio.70.dylib' (no such file), '/usr/local/lib/libicuio.70.dylib' (no such file), '/usr/lib/libicuio.70.dylib' (no such file, not in dyld cache), '/opt/homebrew/Cellar/icu4c/72.1/lib/libicuio.70.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/Cellar/icu4c/72.1/lib/libicuio.70.dylib' (no such file), '/opt/homebrew/Cellar/icu4c/72.1/lib/libicuio.70.dylib' (no such file), '/usr/local/lib/libicuio.70.dylib' (no such file), '/usr/lib/libicuio.70.dylib' (no such file, not in dyld cache)
zsh: abort      php -v
参照先である/opt/homebrew/opt/icu4c/lib/を確認します。エラーメッセージにあったlibicuio.70.dylibではなく、libicuio.72.dylibが配置されています。
% ls /opt/homebrew/opt/icu4c/lib/
icu			libicudata.dylib	libicui18n.dylib	libicuio.dylib		libicutest.dylib	libicutu.dylib		libicuuc.dylib
libicudata.72.1.dylib	libicui18n.72.1.dylib	libicuio.72.1.dylib	libicutest.72.1.dylib	libicutu.72.1.dylib	libicuuc.72.1.dylib	pkgconfig
libicudata.72.dylib	libicui18n.72.dylib	libicuio.72.dylib	libicutest.72.dylib	libicutu.72.dylib	libicuuc.72.dylib
libicudata.a		libicui18n.a		libicuio.a		libicutest.a		libicutu.a		libicuuc.a
icu4cの設定を確認
brew infoから、icu4cの現在のバージョンは72.1であると確認できます。Poured from~の時刻がbrew upgradeと同じタイミングだったので、upgradeの影響を受けたようです。また、/opt/homebrew/opt/icu4c/lib/libicuio.72.dylibの72はicu4cのバージョンと思われます。
% brew info icu4c
==> icu4c: stable 72.1 (bottled) [keg-only]
C/C++ and Java libraries for Unicode and globalization
https://icu.unicode.org/home
/opt/homebrew/Cellar/icu4c/72.1 (263 files, 78.4MB) # 現在のバージョン
  Poured from bottle using the formulae.brew.sh API on 2023-03-12 at 17:28:50
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/icu4c.rb
License: ICU
# 以下省略
今回のエラーは、brew upgradeによりicu4cが72系に更新されたことが原因のようです。PHP7.4は70系を使用するため、このままでは参照エラーが発生します。
icu4cのダウングレード
icu4cを70系に戻します。具体的には、icu4cのFormulae(インストール方法などを含むパッケージの定義書)をgit checkoutで70系に切り替えてicu4cを再インストールします。
icu4cのFormulaeを探す
brew --configのHOMEBREW_PREFIXに記述されているディレクトリの配下でFormulaディレクトリを検索します。
% brew --config | grep HOMEBREW_PREFIX
HOMEBREW_PREFIX: /opt/homebrew
 % find /opt/homebrew -name Formula -type d
/opt/homebrew/Library/Taps/homebrew/homebrew-core/Formula
Formulaディレクトリへ移動します。
% cd /opt/homebrew/Library/Taps/homebrew/homebrew-core/Formula
切り替え対象のFormulaicu4c.rbを見つけました。
% ls | grep icu4c
icu4c.rb
icu4cのFormulaeを70系に戻す
git logでicu4c.rbのコミット履歴を確認し、70系の最新コミットを探します。参考に、brew log  --oneline icu4cでもほぼ同じ内容が表示されます。
% git log --oneline icu4c.rb
11249c583b5 icu4c: update 72.1 bottle.
025d9d1deaf icu4c 72.1
e3317b86c11 icu4c: update 71.1 bottle.
54fb3277728 icu4c: update 71.1 bottle.
c013b416f31 icu4c: update homepage url
97427b4fde6 icu4c: update 71.1 bottle.
9010e85a7cb icu4c 71.1                 # ここから71系
fe6a2fe48c2 icu4c: update homepage     # このコミットに戻す
aa997d1c221 icu4c 70.1
公式サイトのリンクからログを追うことも可能です。
Formula code: icu4c.rb on GitHub
70系の最新コミットはfe6a2fe48c2です。icu4c.rbをこのコミットにチェックアウトします。
% git checkout fe6a2fe48c2 icu4c.rb
Updated 1 path from bbfb6dca4b4
72系のicu4cをアンインストール
再インストール前に72系のicu4cをアンインストールします。
% brew uninstall icu4c
70系のicu4cをインストール
※Formulaeの名前によりインストールされるパッケージのバージョンが異なりますが、挙動の理由は不明です。
70系のicu4cをインストールします。Formulaeはicu4c.rbを指定してください。icu4cを指定した場合は70系ではなく72系のisu4cがインストールされます。
% HOMEBREW_NO_AUTO_UPDATE=1 brew install icu4c.rb
実行後は70系のみインストールされると思いきや、72.1と70.1の2つがインストールされています。
% brew list icu4c --versions
icu4c 72.1 70.1
icu4cのFormulaeを元に戻す
インストール後はicu4c.rbを元のコミットへ戻します。
% git reset --hard
再度72系のicu4cをアンインストール
再度72系のicu4cをアンインストールします。依存関係を無視するため--ignore-dependenciesオプションを追加します。ここで70系もアンインストールされると思いきや、70系は対象外のようです。
% brew uninstall --ignore-dependencies icu4c
Uninstalling /opt/homebrew/Cellar/icu4c/72.1... (263 files, 78.4MB)
icu4c 70.1 is still installed. # 70系はアンインストールされない
To remove all versions, run:
  brew uninstall --force icu4c
% brew list icu4c --versions
icu4c 70.1
70系のicu4cを反映
brew linkを実行しicu4c 70.1のパッケージを反映します。~/.zshrcの追記は不要です。
% brew link icu4c --force
Linking /opt/homebrew/Cellar/icu4c/70.1... 63 symlinks created.
If you need to have this software first in your PATH instead consider running:
  echo 'export PATH="/opt/homebrew/opt/icu4c/bin:$PATH"' >> ~/.zshrc
  echo 'export PATH="/opt/homebrew/opt/icu4c/sbin:$PATH"' >> ~/.zshrc
icu4cの参照エラーが解決し、再びPHP7.4が使えるようになりました!
% php -v
PHP 7.4.30 (cli) (built: Jun  9 2022 09:20:03) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v3.1.4, Copyright (c) 2002-2022, by Derick Rethans
    with Zend OPcache v7.4.30, Copyright (c), by Zend Technologies
PHP8.2ではエラーが発生する
brew upgradeによりデフォルトのPHPのパッケージが8.2系に更新されました。そのため~/.zshrcからPHP7.4の設定を削除した場合はPHP8.2が参照されます。
# PHP7.4の設定を削除
export PATH="/opt/homebrew/opt/php@7.4/bin:$PATH"
export PATH="/opt/homebrew/opt/php@7.4/sbin:$PATH"
しかし、PHP8.2ではエラーが発生します。PHP8.2系ではicu4cの72系が使われているためです。
% php -v
dyld[45528]: Library not loaded: /opt/homebrew/opt/icu4c/lib/libicuio.72.dylib
  Referenced from: <3680E42B-1530-312F-8F4F-42D652FCEA9B> /opt/homebrew/Cellar/php/8.2.3/bin/php
  Reason: tried: '/opt/homebrew/opt/icu4c/lib/libicuio.72.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/opt/icu4c/lib/libicuio.72.dylib' (no such file), '/opt/homebrew/opt/icu4c/lib/libicuio.72.dylib' (no such file), '/usr/local/lib/libicuio.72.dylib' (no such file), '/usr/lib/libicuio.72.dylib' (no such file, not in dyld cache), '/opt/homebrew/Cellar/icu4c/70.1/lib/libicuio.72.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/Cellar/icu4c/70.1/lib/libicuio.72.dylib' (no such file), '/opt/homebrew/Cellar/icu4c/70.1/lib/libicuio.72.dylib' (no such file), '/usr/local/lib/libicuio.72.dylib' (no such file), '/usr/lib/libicuio.72.dylib' (no such file, not in dyld cache)
zsh: abort      php -v
解決の方法はこちらの記事で説明しています。
パッケージのバージョンは切り替え可能か
brew switchでパッケージのバージョン切り替え行う方法も見つけましたが、自分の環境ではエラーが発生し利用できませんでした。
# バージョンを自由に切り替えたかった...
% brew list icu4c --versions
icu4c 72.1 70.1
# コマンド自体が利用できない
% brew help switch
Error: Unknown command: switch
似た事例を見つけましたが、原因は分かりませんでした。
参考記事
採用PR
弊社で一緒に働く仲間を募集しています。
Devトークやってます。お気軽にご応募ください(^^)
募集要項はこちらをご覧ください!
