VisualStudio&Gradleでマルチアーキテクチャ向けのAPKを作る


前回の記事

はじめに

armeabi-v7a と arm64-v8a の両方のダイナミックライブラリ(*.so)をを含めたAPKを作る方法を色々検証し、作成する方法が分かりましたのでまとめていきます。

ただし、この方法ですと色々問題があります。
どのようなもんだいがあるのか」「私の場合はどのように対応したのか」も一緒にまとめていきます。

今回は「VisualStudioでGradleを使ってNativeなAPKを作ってみる」のプロジェクトを使って説明します。

マルチアーキテクチャ対応APKの作り方

1. build.gradle.template を書き換える。

複数のアーキテクチャを含めるように $(SolutionDir)AndroidGradle\app\build.gradle.template を下記のように書きまえます。

build.gradle.template
android.productFlavors {
    create("arm7") {
        ndk.abiFilters.add("armeabi-v7a")
        // 追記
        ndk.abiFilters.add("arm64-v8a")
    }
    create("arm8") {
        ndk.abiFilters.add("arm64-v8a")
        // 追記
        ndk.abiFilters.add("armeabi-v7a")
    }
    create("x86") {
        ndk.abiFilters.add("x86")
    }
    create("x86-64") {
        ndk.abiFilters.add("x86_64")
    }
    create("all")
}

これで $(SolutionDir)AndroidGradle\app\src\main\jniLibs フォルダ内に「arm64-v8a」と「armeabi-v7a」が存在する状態で、VisualStudioのソリューションプラットフォームが「ARM」か「ARM64」のときにビルドすると双方のアーキテクチャをAPKに含めてくれるようになります。

2. ソリューションをビルドする。

ソリューションプラットフォームをARMとARM64でそれぞれビルドを行う。

これで「arm64-v8a」と「armeabi-v7a」の双方のダイナミックライブラリ(.so)が入ったAPKが生成できているはずです。

この対応の問題点

gradleファイルを修正するだけで簡単にマルチアーキテクチャに対応できるのですが、ここで問題点があります。

ブレイクポイントがうまく止まらないパターンが有る

これは開発を進めてもらえればすぐにぶつかる問題だと思います。
Android端末に合ったv7aかv8aが実行されます。
私の持っているXperia XZ Premium(SO-04J)はv8aのほうが優先的に実行されます。
v7aとv8aの双方のライブラリが入った状態でソリューションプラットフォームを「ARM」で実行するとエラーになります。

ブレイクポイントを止めるためにv7a向けのシンボルファイルを生成しているのですが、APKの中にv8aが有るために実行時にv8aのダイナミックライブラリ(.so)がロードされてしまい、シンボルファイルが不一致を起こしてしまっているため このようなことが起きると考えられます。

どのように対応すればよいか

開発の段階(ソリューション構成がDebugのとき)は、v7aかv8aのどちらか片方しか含めないようにします。

修正方法

ビルド前タスクの機能を使います。
Sharedプロジェクトのプロパティから「構成プロパティ」->「ビルドイベント」->「ビルド前のイベント」へ移動します。
「構成(C)」を「Debug」に「プラットフォーム(P)」を「すべてのプラットフォーム」にした状態でコマンドラインに下記コードを貼り付けます。

set dir=$(SolutionDir)AndroidGradle\app\src\main\jniLibs\
if exist %dir% (
  for /d %%d in (%dir%*) do (
    echo delete %%d
    rd /s /q %%d
  )
)

jniLibsフォルダ以下のフォルダを全て消すバッチ処理になります。
これでブレイクポイントが止まらないということは起きなくなります。

まとめ

後半の対応はbuild.gradleをうまく使えばもっとスマートにできそうなのでgradle勉強してより良い方法が分かったら新しく記事あげていこうと思います。