AGPを8.4に上げると「Missing classes detected while running R8. 〜」というビルドエラーが出る
事象
AndroidStudio JellyfishのStableが出たので、早速アップデートをして、一緒にAGP(Android gradle plugin)も8.4.0に上げたらビルドエラーが出た。
具体的には下記のようなエラーが出る。
Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in (module)/build/outputs/mapping/release/missing_rules.txt.
NoClassDefFoundError
が出ることもある。
環境
- AndroidStudio Jellyfish
- AGP8.4.0(上げる前は8.3.2)
- マルチモジュール構成のプロジェクト
解決策
マルチモジュールにおいて、ライブラリモジュールでは難読化をしないようisMinifyEnabled=false
にする。(AARとして公開する、かつ、先に難読化したい場合は別)
つまり、アプリモジュールのみでisMinifyEnabled=true
にする。
ライブラリモジュール内でproguardルールを指定したい場合は、consumerProguardFiles
で、そのモジュールのconsumer-rules.pro
を指定する
原因
AGP8.4の更新内容に書いてある。
ドキュメントを見ると、AGP8.4では、「ライブラリのクラスが縮小される」という更新がある。
アプリが圧縮バージョンの Android ライブラリ サブプロジェクトに依存している場合、APK には圧縮された Android ライブラリ クラスが含まれます。APK に欠落しているクラスがある場合、ライブラリ保持ルールの調整が必要になることがあります。
以前の動作に戻すには、gradle.properties ファイルで android.disableMinifyLocalDependenciesForLibraries を設定し、バグを報告してください。AGP の今後のバージョンでは、このフラグは削除されます。
実際に、 disableMinifyLocalDependenciesForLibraries
を設定するとビルドが通った。
このフラグは削除されるため、根本対応をする必要がある。
解説
ライブラリモジュールのドキュメントに以下の記載がある。
ライブラリ モジュールに ProGuard ファイルを埋め込むと、ライブラリに依存するアプリ モジュールで、ライブラリを使用するために ProGuard ファイルを手動で更新する必要がなくなります。Android Studio のビルドシステムでアプリをビルドする際には、アプリ モジュールとライブラリの両方のディレクティブが使用されます。したがって、ライブラリで別途コード圧縮ツールを実行する必要はありません。
APK にコンパイルされ AAR を生成しないマルチモジュール ビルドにライブラリ モジュールが含まれている場合は、ライブラリを使用するアプリ モジュールでのみコード圧縮を実行してください。ProGuard ルールとその使用方法について詳しくは、アプリの圧縮、難読化、最適化をご覧ください。
まとめると、以下になる。
- ライブラリモジュールは、アプリモジュールで難読化指定してれば一緒に難読化される
- proguardルールを指定したければ、
consumerProguardFiles
を設定すれば良い - そのため、圧縮した状態のAARを配信したい場合を除き、単体でコード圧縮ツールを実行する必要はない
- proguardルールを指定したければ、
- AARをビルドして公開しない場合は、アプリモジュールでのみコード圧縮をするべき
ちなみに、リファレンスアプリであるnow in androidや、我らのDroidKaigi2023アプリもappモジュールのみに難読化指定をしていた。
調査メモ
エラー発生から解決までのメモ
エラーメッセージの対応
Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in (module)/build/outputs/mapping/release/missing_rules.txt.
AGP更新を読んでその影響だとは分かったが、直したが分からないので調査していく。
エラーを要約すると「難読化で足りないKeepルールがあるから、missing_rules.txt
に出力したよ」とのこと。
missing_rules.txt
は下記のようになっている。
# Please add these rules to your existing keep rules in order to suppress warnings.
# This is generated automatically by the Android Gradle plugin.
-dontwarn xxx.yyy.ZZ
dontwarn
でクラス名が入っており、これをproguard-rulesに入れれば通りそうである。
しかし、これをモジュールのproguard-rules.proに入れてビルドしても、別のモジュールで同じエラーが出た。
全部直すのは大変なので、他の方法がないか調べていく。
他に発生している人がいないか
同じ事象が起きていないか確認すると、いくつか確認できた。
AGP8.4に関する投稿。appモジュールのみ難読化をtrueにせよとある。
「ライブラリモジュールは難読化すべきでない」のかもしれないと思い、これはAPGは関係なさそうだったので、他の情報がないか調べる。
これらは数年前の投稿だが、こちらもappモジュールのみ難読化をtrueにすべきと回答がある。
「ライブラリモジュールは難読化すべきでない」の確度が高まったので、改めて公式ドキュメントを探してみる。
consumerProguardFiles
やマルチモジュール
といった単語でドキュメントを探していたら、解説に載せた公式ページの言及を見つけることが出来た。
実際の確認
その後、念の為、ライブラリモジュールが難読化されるか実際に試したが、難読化されることが確認できた。
AGP8.3.2でappモジュールのみにisMinifyEnabled=true
を入れたものと、今まで通り全てのモジュールに入れたものとでアプリサイズ・mapping.txtを確認したところ、ライブラリモジュールが難読化されていることが確認できた。
最後に
今回の調査で、根本的な推奨設定を知ることが出来た。
(個人的には)公式情報が見付けづらいと思ったので、メモとして残しておく。
ご指摘などあればお気軽にコメントください!
Discussion