Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ビルドに必要な依存パッケージがインストールされていない macOS 環境でエンジンが起動しない #177

Closed
PickledChair opened this issue Nov 4, 2021 · 13 comments · Fixed by #191
Labels

Comments

@PickledChair
Copy link
Member

PickledChair commented Nov 4, 2021

不具合の内容

https://github.com/Hiroshiba/voicevox/issues/399#issuecomment-954785504 で提供されたインストーラーで、まっさらな状態の macOS に VOICEVOX エディターをインストールして起動したときに、エンジンが起動しない例が報告されました(以下の「現象・ログ」を参照。とりあえず起動できるようにする手順についても触れられています)。

現象・ログ

https://github.com/Hiroshiba/voicevox/issues/399 における以下のコメントを参照:

再現手順

エンジンのビルドに必要な Python などの依存パッケージがインストールされていない(理想的には Homebrew や Xcode Command Line Tools を導入していない)クリーンな macOS 環境で、 https://github.com/Hiroshiba/voicevox/issues/399#issuecomment-954785504 で提供されたインストーラーでインストールされた VOICEVOX を以下のコマンドで起動する。

$ cd /Applications/VOICEVOX.app/Contents/MacOS
$ ./VOICEVOX

期待動作

ユーザーが依存パッケージを追加でインストールしなくても VOICEVOX のエンジンを正常に使える。

VOICEVOXのバージョン

0.7.5
(autobuild check 20211029)

OSの種類/ディストリ/バージョン

macOS Monterey
(M1 Mac で現象が確認されました。おそらく Intel Mac でも同様に起こると考えています。)

その他

調査した結果、autobuild check 20211029 で提供されている macOS 向けのテストビルドにおいて、一部の共有ライブラリのリンク先にハードコードされた絶対パスが使われていることがわかりました。そこに原因の一端があると考えられます。詳細は続きのコメントで書きます。

@Hiroshiba
Copy link
Member

issueありがとうございます!
エラーを見るに、Nuitkaビルドする際と、coreをpythonにインストールする際に必要なライブラリがなぜか引っ張ってこれていない印象を受けました。
Macビルドのプルリクエストを作成してくださった @HyodaKazuaki さんにも意見伺いたいかもです。

@PickledChair
Copy link
Member Author

PickledChair commented Nov 4, 2021

エラーを見るに、Nuitkaビルドする際と、coreをpythonにインストールする際に必要なライブラリがなぜか引っ張ってこれていない印象を受けました。

そうですね。より正確には、必要な共有ライブラリはちゃんとコピーして引っ張って来れているものの、共有ライブラリに付与されたリンク情報が適切でない、ということなのだと思います。Nuitka が自動で修正しきれていない印象です。

https://github.com/Hiroshiba/voicevox/issues/399#issuecomment-960425475 で説明されている、VOICEVOX.app をとりあえず起動するための手順では、まず初めに hashlib.py のインポートの失敗を解決していました。hashlib.py は libssl に依存しています。ただし、hashlib.py がコンパイルされた生成物と思われる _hashlib.so の libssl.1.1.dylib へのリンク情報は、エンジンに含まれる libssl.1.1.dylib を正しく指していました。そこで、その libssl.1.1.dylib 自体を調べてみました。

$ cd /Applications/VOICEVOX.app/Contents/MacOS
$ otool -L libssl.1.1.dylib
libssl.1.1.dylib:
	/usr/local/opt/[email protected]/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
	/usr/local/Cellar/[email protected]/1.1.1l_1/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)

このように、 libcrypto.1.1.dylib に対するリンクが /usr/local/Cellar/[email protected]/1.1.1l_1/lib/libcrypto.1.1.dylib という絶対パスで指定されている点が適切ではありません。これに対して brew install python3 でインポートが通るようになったのは、Homebrew の python formulae の依存に [email protected] が含まれており、python3 のインストール時に同時にインストールされるからです。これにより、 /usr/local/Cellar/[email protected]/1.1.1l_1/lib/libcrypto.1.1.dylib が存在するようになり、hashlib.py のインポートが成功します。

一方で、 libcrypto.1.1.dylib はビルド生成物の中にもちゃんとコピーされて含まれているので、配布物を完全にポータブルにするには、こちらへのリンクとするように修正する必要があります。 install_name_tool -change /usr/local/Cellar/[email protected]/1.1.1l_1/lib/libcrypto.1.1.dylib @rpath/libcrypto.1.1.dylib libssl.1.1.dylib で修正できます。

他のエラーに関しても、上記とほぼ同様の問題が原因となっていると考えています。

この問題の解決方法については、私も @HyodaKazuaki さんにご意見を伺いたいです。

@Hiroshiba
Copy link
Member

なるほど!配布パッケージに含まれているのにリンクされていないということなんですね!!
たしかにrpathの変更などで対処できそうですが、理想的にはNuitkaに任せたいところですね…

一個一個Issue探しつつ、適切な解決策がわからなければリンク書き換え、とかが妥当かもと思いました。
もしくは依存ライブラリを全部舐めて、パッケージ内を参照していないものは全部rpath書き換え、みたいな解決策でも一旦は良いかも?

@HyodaKazuaki
Copy link
Contributor

@PickledChair がフロントエンドのIssueで報告してくれた情報 https://github.com/Hiroshiba/voicevox/issues/399#issuecomment-959268514 などを参考に色々と調査してみましたが、NuitkaがMacOSでは共有オブジェクトを探しに行く機構が十分でないことが原因のようです。
ref. Nuitka/Nuitka#1195

Nuitka側も対応に苦慮しているようなので、どこまで対応できるかは不明ですが @Hiroshiba のおっしゃる通り適宜rpathを書き換える方法がいいかもしれません。
個人的には、最終的にPythonから脱却してNodejsなどに移行するのが一番ベストではないかと思います。

@Hiroshiba
Copy link
Member

報告ありがとうございます!

mac側の問題なのか、Nuitka側が完璧に対応できていないのかがまだ判断できなさそうだと感じました。
前者だったらNodejsに移行しても問題は変わらないかもです。

とはいえ、どうやらパッケージ内にファイルとしては存在しているけどリンクされていない、という状態っぽいという報告なので(認識合ってますか・・・?)、Nuitka側の課題なのかもとはちょっと思いました。
mac対応のために言語移行はちょっとむずかしそうなので、rpathなどでなんとか解決できると嬉しいかもです。

@PickledChair
Copy link
Member Author

mac側の問題なのか、Nuitka側が完璧に対応できていないのかがまだ判断できなさそうだと感じました。

確かに具体的にどこに問題があるのかは調査しきれていないですね。時間がかかるかもですが、もう少し調査してみます。

mac対応のために言語移行はちょっとむずかしそうなので、rpathなどでなんとか解決できると嬉しいかもです。

地道に rpath 修正をやるのが一番確かな解決法かもしれませんね。解決法についても並行して思案してみます。

@Hiroshiba
Copy link
Member

おーー、ありがとうございます・・・!!!
ぜひよろしくおねがいします!!

@PickledChair
Copy link
Member Author

まずは Nuitka だけでどうにかできないか考えました。

Nuitka の問題の扱い(結論:調べないことにした)

以下の2つの視点で考えました。

Nuitka で NumPy や SciPy の問題が起こるのはよくあることらしい

純粋な Python コードだけではないライブラリをコンパイルすることが簡単ではないのはなんとなく分かりますが、それでも NumPy, SciPy, Tkinter といったいくつかのライブラリに関しては、Nuitka は特別扱いして、standalone なバイナリに固められるようにしているようです。しかし、それぞれのライブラリのバージョンアップに伴って、うまくいかなくなるケースもあるらしく、その場合は対象ライブラリのダウングレードを勧めています(参考:Nuitka User Manual - Missing DLLs in standalone)。

今回 voicevox engine において問題が発生したプラットフォームは macOS だけですが、上記を考慮すると、NumPy や SciPy をめぐって問題が生じることはよくある、自然なことだと割り切って、Nuitka に頼らずにこちらで問題を修正するのが、一番速く、かつ適切なように思われます。

(正直に言うと、調べ始めると際限がなかったので諦めました😅)

すでに動作する自動ビルドがあるのでそれを活かしたい

@HyodaKazuaki さんが作成した自動ビルドは、共有ライブラリ周りで少し問題が出た以外は特に問題がないと考えられます。(少なくとも自分の場合) @HyodaKazuaki さん以上に工夫できる余地が見当たらなかったので、これをそのまま使うのが、今の所いちばん筋が良いのではと考えました。

ということで解決策としては、自動ビルド時に追加で dylib の rpath 修正を行うのが良いと思います。後ほど、具体的にどの dylib で rpath の問題が発生しているのか、そこからどんな解決手段が考えられるのかについてコメントしたいと思います。

@Hiroshiba
Copy link
Member

なるほど、良い方針だと思います!!

numpyやscipyのバージョンをnuitkaサポートされているものに合わせる、という手もありそうですが、ぱっと調べた感じ対応バージョンがどれかわかりませんでした。
rpath修正などを行う方針が良いと思います!

@PickledChair
Copy link
Member Author

もう少し実態を詳しく調査し、それに対してどんな解決手段があるのか考察してみました。

自動ビルドに含まれる一部の dylib が持つ問題

自動ビルドは https://github.com/Hiroshiba/voicevox_engine/releases/tag/0.8.0macos-x64.7z.001 を用いました。このビルドに含まれる一部の dylib の持つ問題について、検証のためのコードを書いて調べてみました(コードは Gist に上げました)。

整理すると2種類の問題があります。

1. 不足している dylib がある

https://github.com/Hiroshiba/voicevox_engine/issues/177#issuecomment-960952083

必要な共有ライブラリはちゃんとコピーして引っ張って来れている

と言ったのですが、よくよく調べると引っ張って来れていない dylib がありました。

開発環境に依存している rpath が指す dylib のうち、ビルド産物の中に含まれていないものを検出するスクリプト (check_lack_of_dylibs.py) を書いて実行してみると、以下のように2つの dylib が検出されました:

$ base_path=/path/to/macos-x64
$ python check_lack_of_dylibs.py $base_path
libintl.8.dylib not found.
libprotobuf.28.dylib not found.

(開発環境に依存していない rpath は OS の標準ライブラリかビルド産物の dylib のどちらかを指すようになっており、かつ自動ビルドが実際に実行可能なので、問題ないとして調べていません。)

2. 開発環境のみに存在しているパスが指定された rpath がある

開発環境に依存している rpath をもつ dylib を列挙するスクリプトも書きました (check_rpaths.py) 。これを実行すると、以下の通り6つの dylib が開発環境に依存する rpath を持っていることがわかります:

$ python check_rpaths.py $base_path
non-distributable rpaths:

/path/to/macos-x64/libtorch.dylib has:
	/usr/local/opt/protobuf/lib/libprotobuf.28.dylib
/path/to/macos-x64/libgdbm_compat.4.dylib has:
	/usr/local/Cellar/gdbm/1.21_1/lib/libgdbm.6.dylib
/path/to/macos-x64/libpython3.7m.dylib has:
	/usr/local/opt/gettext/lib/libintl.8.dylib
/path/to/macos-x64/libssl.1.1.dylib has:
	/usr/local/Cellar/[email protected]/1.1.1l_1/lib/libcrypto.1.1.dylib
/path/to/macos-x64/libtorch_cpu.dylib has:
	/usr/local/opt/protobuf/lib/libprotobuf.28.dylib
/path/to/macos-x64/libcaffe2_detectron_ops.dylib has:
	/usr/local/opt/protobuf/lib/libprotobuf.28.dylib

(スクリプトではついでに Nuitka が生成した so についても調べていますが、出力でわかる通り so については問題ありませんでした。)

解決策について

上記を踏まえ「解決に必要な作業」と「具体的な手段」について考えました。

1. 解決に必要な作業

以下の2点を、以下の順序で行うのが良いと思います。

  1. 配布物に不足している dylib をビルド後にコピーして配布物の適切な位置に含める
  2. 開発環境に依存している rpath を修正し、配布物内の dylib を指すようにする(install_name_tool を使う)

2. 具体的な手段

上記の作業を実現する手段はいくつかあると思います:

  • 不足している dylib や、開発環境に依存している rpath を自動で検出して修正

    • Pros: 依存関係のアップデートに伴う、dylib や rpath の条件の変化に対して強い

    • Cons: 依存関係のアップデートに伴い dylib や rpath の問題が自然に解消したとしても、それを検出できず余計な処理が走ることになる(問題が解消されたことを検出できるようにする?)

    • さらに具体的な手段

      • Python スクリプトでビルド時に行う(先ほどの検証スクリプトをもう少しこねるとできそうです)

        • Pros: VOICEVOX に関わる人で Python を書ける人は多そうなので、保守しやすい
        • Cons: 特になさそう?
      • シェルスクリプトで行う

        • Pros: build.yml に書くので、ファイルが増えない
        • Cons: 複雑なことをしようとすると辛い?
  • 不足している dylib、開発環境に依存している rpath は上記の調査結果のものだけと仮定して、問題のファイルごとに修正を build.yml にハードコードする

    • Pros: 記述量が一番少ない
    • Cons: 依存関係のアップデートに伴う、dylib や rpath の条件の変化に対して弱い

個人的には修正用の Python スクリプトをビルド時に走らせて解決するのが手っ取り早い気がしています(この場合は自分もお手伝いできるかもしれません)。

@PickledChair
Copy link
Member Author

PickledChair commented Nov 12, 2021

ちなみに、 https://github.com/Hiroshiba/voicevox/issues/399#issuecomment-954785504 のインストーラーでインストールした VOICEVOX.app に含まれるバイナリについて同様に check_rpaths.py で調査すると、以下のように出力が結構違うので、この app bundle に含まれるエンジンは voicevox engine リポジトリの自動ビルドを用いていないと考えられます。Apple-Yuki さんの手元の環境でビルドされたものなのではと推測しています:

$ base_path=/Applications/VOICEVOX.app/Contents/MacOS
$ python check_rpaths.py $base_path
non-distributable rpaths:

/Applications/VOICEVOX.app/Contents/MacOS/liblapack.dylib has:
	/usr/local/opt/openblas/lib/libopenblas.0.dylib
	/usr/local/opt/gcc/lib/gcc/11/libgfortran.5.dylib
	/usr/local/opt/gcc/lib/gcc/11/libgomp.1.dylib
	/usr/local/opt/gcc/lib/gcc/11/libquadmath.0.dylib
	/usr/local/lib/gcc/11/libgcc_s.1.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libtorch.dylib has:
	/usr/local/opt/protobuf/lib/libprotobuf.28.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libgdbm_compat.4.dylib has:
	/usr/local/Cellar/gdbm/1.21_1/lib/libgdbm.6.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libssl.1.1.dylib has:
	/usr/local/Cellar/[email protected]/1.1.1l_1/lib/libcrypto.1.1.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libtorch_cpu.dylib has:
	/usr/local/opt/protobuf/lib/libprotobuf.28.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libgfortran.5.dylib has:
	/usr/local/Cellar/gcc/11.2.0/lib/gcc/11/libquadmath.0.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libopenblasp-r0.3.18.dylib has:
	/usr/local/opt/openblas/lib/libopenblas.0.dylib
	/usr/local/opt/gcc/lib/gcc/11/libgfortran.5.dylib
	/usr/local/opt/gcc/lib/gcc/11/libgomp.1.dylib
	/usr/local/opt/gcc/lib/gcc/11/libquadmath.0.dylib
	/usr/local/lib/gcc/11/libgcc_s.1.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libopenblas.dylib has:
	/usr/local/opt/gcc/lib/gcc/11/libgfortran.5.dylib
	/usr/local/opt/gcc/lib/gcc/11/libgomp.1.dylib
	/usr/local/opt/gcc/lib/gcc/11/libquadmath.0.dylib
	/usr/local/lib/gcc/11/libgcc_s.1.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libcaffe2_detectron_ops.dylib has:
	/usr/local/opt/protobuf/lib/libprotobuf.28.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libblas.dylib has:
	/usr/local/opt/openblas/lib/libopenblas.0.dylib
	/usr/local/opt/gcc/lib/gcc/11/libgfortran.5.dylib
	/usr/local/opt/gcc/lib/gcc/11/libgomp.1.dylib
	/usr/local/opt/gcc/lib/gcc/11/libquadmath.0.dylib
	/usr/local/lib/gcc/11/libgcc_s.1.dylib
/Applications/VOICEVOX.app/Contents/MacOS/libopenblas.0.dylib has:
	/usr/local/opt/gcc/lib/gcc/11/libgfortran.5.dylib
	/usr/local/opt/gcc/lib/gcc/11/libgomp.1.dylib
	/usr/local/opt/gcc/lib/gcc/11/libquadmath.0.dylib
	/usr/local/lib/gcc/11/libgcc_s.1.dylib

@Hiroshiba
Copy link
Member

詳細をありがとうございます!!

おそらく将来に足りないdylibは増えそうなこと、もうすでにコードをある程度実装されていることから、Pythonでチェック&修正を行うのが良いのかなと感じました!
(Pythonで足りないものを見つけて、rpathを修正するのはシェルスクリプトでも良いかもです)

buildディレクトリを作ってそちらに追加いただけると!

@PickledChair
Copy link
Member Author

分かりました! 取り組んでみます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants