本当に原因究明がだるかったので残しておきたい。
そもそもAndroid NDK上でvcpkgを使う方法についてもネット上に情報が少ないので解説しておきたいところだが、それはこの記事では一旦置いておく。
注: このページの記述は2023/10/28時点の情報です。今後openal-softのバージョン更新に従って情報は古くなる可能性があるためご注意ください。
結論
vcpkgでopenal-soft
パッケージを入れると、以下のパスにライブラリリンク用のCMakeスクリプトが作られる。
(vcpkgのルートパス)/installed/(triplet)/share/openal-soft/OpenALTargets.cmake
これの63行目に、OpenALが依存するライブラリへのリンク記述がある。
INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:-pthread>;(NDKのルートパス)/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/aarch64-linux-android/21/libOpenSLES.so;\$<LINK_ONLY:dl>;\$<LINK_ONLY:log>;\$<LINK_ONLY:atomic>;\$<LINK_ONLY:m>"
これを以下のように書き換える。
INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:-pthread>;\$<LINK_ONLY:OpenSLES>;\$<LINK_ONLY:dl>;\$<LINK_ONLY:log>;\$<LINK_ONLY:atomic>;\$<LINK_ONLY:m>"
要するに、OpenSLESのライブラリが絶対パスで指定されているが、これをライブラリ名のみによる指定にすることで解決する。
発覚過程
以前に開発したAndroid NDKアプリを別のPCで改めてビルドしようとしたところ、なぜかビルドが通らなかった。
エラー文を見てみると以下のように出ている。
ld: error: undefined symbol: __register_atfork
ld: error: undefined symbol: __fwrite_chk
ld: error: undefined symbol: __fread_chk
ld: error: undefined symbol: __write_chk
この辺の関数が定義されていないということになるが、そんなlibcの内部実装っぽい雰囲気の関数などどうしようもない。そこでググったところ、1つ有力な情報を得た。
https://github.com/android/ndk/issues/964
どうやらAndroid NDK 23以前では__register_atfork
が定義されていないという不具合があるらしい。ではバージョンを上げれば解決なのか、と考えたがこのケースではバージョンを上げても解決しなかった。 別のところに原因があるらしい。
そこで、初期プロジェクトはビルドが通ることを確認した上で少しずつ変えていくことで同様のエラーが起きる条件を探したところ、CMakeスクリプトでvcpkg製のOpenAL(openal-soft)をリンクするとエラーが起きることが分かった。
OpenALのリンク関係に問題があるということが分かったのでCMakeスクリプトを辿っていくと冒頭のコードを発見。Android NDK開発において、OpenSLESは本来絶対パスなどでなくライブラリ名のみでリンクできるはずなので書き換えてみたところ、なんかビルドが通った。正直この違いがどういう理屈で__register_atfork
などの関数の未定義に繋がるのか定かでないが、とにかくこれで解決することはするので記録として残しておく。
余談
実は以前にもOpenSLESのリンク関連でエラーを出したときがあって、その時はリンクするライブラリ名が「OpenSLES」ではなく「OpenSL::OpenSLES」になっていたという顛末だった。どうやらコミットc12ada6で修正したようだが、その結果今回のまた別の不具合が起きてしまったようだ。
issueかなにか立ててやりたいが、vcpkgの方のリポジトリでissueを立てるべきという説もあり、もうちょっと調べてからにしたい。
追記(2023/11/3)
どうやら自分は今までAndroid NDKに対するvcpkgの使い方を完全に勘違いしていたことが分かった。 正しい使い方をしても同様の問題が再現するかどうか現在調査中。