MacOS Catalinaでislをダウングレードした話

 

概要

isl(Integer Set Library)のバージョンが0.22に上がってしまい、avr-gccが動かなくなった件についてサポートした際のログになります。

対症療法としてislを0.21にダウングレードすることにしましたが、私自身CatalinaどころかそもそもMacを触ったことが無いので、「Homebrewってなんだ」というところから勉強した次第です。とりあえず今の理解で記事を書いていくので間違ってたらご指摘いただけるとありがたいです。

なお今回やってもらった環境がCatalina 19C57(10.15.2)だったので、但し書きがない限りこのバージョンについての話です。

 

参考リンク

  1. Homebrewメモ - Qiita

  2. Homebrewで過去バージョンをインストールしたいぞ - Qiita

 

事の発端 ~QMKビルドできない~

qmk_firmwareに含まれるキーボードのFWをビルドしている最中に以下のようなエラーが発生しました。

Compiling: keyboards/hifumi/keymaps/test/keymap.c                                                  dyld: Library not loaded: /usr/local/opt/isl/lib/libisl.21.dylib
  Referenced from: /usr/local/Cellar/avr-gcc@8/8.3.0/libexec/gcc/avr/8.3.0/cc1
  Reason: image not found
avr-gcc: internal compiler error: Abort trap: 6 signal terminated program cc1
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://gcc.gnu.org/bugs/> for instructions.
 [ERRORS]
 | 
 | 
 | 
make[1]: *** [.build/obj_hifumi_test/keyboards/hifumi/keymaps/test/keymap.o] Error 1
make: *** [hifumi:test] Error 1
Make finished with errors

これが今回問題のコアになっていたエラーです。hifumiというキーボードのFWのビルド中に出たエラーでしたが、他のキーボードでも同様のエラーが出ました。

メッセージを見る限り、コンパイル時にavr-gcc/usr/local/opt/isl/lib/libisl.21.dylibをロードしようとしているけど、ファイルが見つからないのでabortという状態のようです。

以下のコマンドで確認してもらったところ、確かにファイルがないです。というか明らかにバージョンが違いますね。

$ find /usr/local | grep libisl
/usr/local/lib/libisl.22.dylib
/usr/local/lib/libisl.a
/usr/local/lib/libisl.dylib
/usr/local/Cellar/isl/0.22/lib/libisl.22.dylib
/usr/local/Cellar/isl/0.22/lib/libisl.a
/usr/local/Cellar/isl/0.22/lib/libisl.dylib
/usr/local/Cellar/isl/0.22/share/gdb/auto-load/libisl.22.dylib-gdb.py

適当にシンボリックリンク貼ってあげれば良いのかなと思ったのですが、貼ってみても同じエラーでabortしました。

そんなことあるのかという感じですが、どうやらlibisl.21.dylibもといislの0.21しか受け付けないようです。brew upgradeした際にislのバージョンが上がってしまって、このような事態になったようです。avr-gccさんlibisl.dylib使ってくれたら良かったのでは?(素人並感)

初めはlibislのバージョンを指定している箇所がavr-gccにあるだろうしそこ直せばいいかなと思ったのですが、しばらく探しても見つからなかったので諦めてislをダウングレードすることにしました。

 

Homebrewについてのお勉強

Homebrewについて

HomebrewというのはMacOS向けのパッケージマネージャらしいです。ただ、標準で入っているものではなく、ユーザーがインストールして初めてbrewコマンドとして使えるようになるらしいです。詳しくは参考リンク1辺りを参考にしてください。

Formulaによるパッケージのバージョン管理について

Formulaはパッケージをインストール/アップグレード等するためのRubyスクリプトです。パッケージ名.rbの名前でどこかのディレクトリに置かれています。バージョンによって変わることがあるようです。
今回は/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/でした。

brew install パッケージ名と打つと、指定したパッケージのFormula(Rubyスクリプト)が走ってインストールが行われます。

また、このFormula達は上記パスのhomebrew-core以下をまとめるローカルなgitリポジトリでバージョン管理されています。

恐らくですが、brew updateするとこのリポジトリを通してFormulaが更新され、brew upgradeするとupgrade可能=インストールされているパッケージのバージョンが最新でないFormulaが走るようです。

それからこのhomebrew-coreリポジトリは『今まで更新を取得してきたログ』になっているようで、brew cleanupすると、このリポジトリの歴史が白紙に戻ります。
ただし既に更新されたFormula本体が消されるわけではなく、Formulaを更新してきた歴史のみが消えます。これは後ほど実ケースが出てきます。

 

本題 ~islのダウングレード~

さて本題のislのダウングレード方法です。

上で説明した通りbrew install時の一連のインストールコマンドは該当パッケージのFormulaに書いてあるので、ざっくり言うと『Formulaの内容を指定のバージョンへダウングレードした上でbrew install』してあげればダウングレードができます。

Formulaの内容を指定バージョンへダウングレードといっても、Formulaは所詮テキストなので、以下のどちらかの操作で十分です。

  • git checkout 指定バージョンのコミット 該当Formula
  • 指定バージョンのFormulaの内容をどこかから拾ってきてローカルのFormulaにコピペする

前者の手法の場合は、git log 該当Formulaすると該当Formulaの歴史が辿れるので、問題のあったバージョンの一つ前辺りのコミット番号を控えてgit checkoutすれば良いと思います。
ただし、上で少し説明したようにbrew cleanupしてしまうとFormulaに関する歴史が消えてしまうのでgit checkoutできなくなります。また、あくまでローカルなgitなので、次で出てくる公式リポジトリのコミット番号を入れても意味がないです。ローカルなgitというのは私の勘違いです。ローカルなgitリポジトリではありますが、以下の公式リポジトリとコミット番号が一緒だったので、公式リポジトリと繋がってはいるようです。単純に残っている分の歴史から消えてしまっているからgit checkoutできないようです。

2の手法はとても簡単です。以下に公式リポジトリがあり、Formulaの更新履歴を作ってくれてるので、ここから指定バージョンのFormulaの中身を拾ってきます。

GitHub - Homebrew/homebrew-core: 🍻 Default formulae for the missing package manager for macOS

このリポジトリはファイルのHistoryとかがうまく表示されないようなので、手元にgit cloneしてあげないとダメそうですね。

isl 0.21のlatestのFormulaは以下のものなので、この内容をローカルのislのFormulaにコピペしてあげます。

homebrew-core/isl.rb at 5784f67552d1b73f404d88504209578a8d388ac0 · Homebrew/homebrew-core · GitHub

これでダウングレードの準備は整ったので、あとは参考リンク2にある通り、以下のコマンドでインストールします。

$ brew unlink isl
$ HOMEBREW_NO_AUTO_UPDATE=1 brew install isl

※HOMEBRE_NO_AUTO_UPDATEなくてもいいかなと思ったのですが、brew updatebrew install前に走って、Formulaが更新されたら水の泡なので付けておきましょう

さてこれでインストールされたはずです。成功していると以下のコマンドで以下のような出力が得られるらしいです。

$ brew info isl
isl: stable 0.21 (bottled), HEAD [pinned at 0.22]
Integer Set Library for the polyhedral model
https://isl.gforge.inria.fr
/usr/local/Cellar/isl/0.21 (72 files, 4.3MB) *
Poured from bottle on 2020-01-01 at 01:30:43
/usr/local/Cellar/isl/0.22 (72 files, 4.7MB)
Poured from bottle on 2019-12-31 at 12:51:27
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/isl.rb
==> Dependencies
Required: gmp ✔
==> Options
--HEAD
Install HEAD version
==> Analytics
install: 51,824 (30 days), 174,648 (90 days), 700,354 (365 days)
install-on-request: 578 (30 days), 1,413 (90 days), 7,621 (365 days)
build-error: 0 (30 days)
$ find /usr/local | grep libisl
/usr/local/lib/libisl.a
/usr/local/lib/libisl.21.dylib
/usr/local/lib/libisl.dylib
/usr/local/Cellar/isl/0.22/lib/libisl.22.dylib
/usr/local/Cellar/isl/0.22/lib/libisl.a
/usr/local/Cellar/isl/0.22/lib/libisl.dylib
/usr/local/Cellar/isl/0.22/share/gdb/auto-load/libisl.22.dylib-gdb.py
/usr/local/Cellar/isl/0.21/lib/libisl.a
/usr/local/Cellar/isl/0.21/lib/libisl.21.dylib
/usr/local/Cellar/isl/0.21/lib/libisl.dylib
/usr/local/Cellar/isl/0.21/share/gdb/auto-load/libisl.21.dylib-gdb.py

 

おわりに

はい、これでislのダウングレード完了です。QMKのビルドも通るようになってると思います。
dylibのパスが違う?細かいことは気にしたら負けです。ライブラリとしてパスが通ったところに置いてあればいいんじゃないでしょうか(思考停止)。

本当は直るまでislのバージョン固定とかbrew switchの挙動確認とかやりたいんですが、手元にMacがないので細かい挙動確認もできずぐぬぬな感じではありますが、まぁ目的は達成したので良しとしましょう。

なおこの『Mac上でislを最新版(0.22)にするとavr-gccがエラーを吐く件』については、QMKでよくお世話になっているdrashnaさんが、avr-gccのFormulaリポジトリにIssueを上げてくれています。そのうち直ると思うので気長に待ちましょう。直ったようです。公開前夜にFormulaのgit辺りの勘違いに気づいてお恥ずかしい限りですが、これはこれで誰かの勉強になるかもしれないのでそのまま残しておきます。

何かあればこちらのコメントかTwitterの方までお願いします。