前回記事で Unity では、 Windows プラットフォーム向けの SQLCipher DLL ファイルの作り方と使い方を書きました。
今回は、Android 向けの SQLCipher の .so ファイルの作り方をメモした内容です。
環境構築
- WSL (Windows subsystem for linux)
- Unity 2019.3 に合わせて Android NDK (r19)
- OpenSSL
- sqlite3.c (前回記事で作成したものを再利用)
NDK のバージョンは Unity のバージョンにあわせる必要があります。「Unity Editor system requirements」などを参照します。
Windows で開発しているため、Android 向けの .so ファイルを作成したくても Windows では通常、適当なコンパイルが難しいです。そこで WSL 環境下の Linux で、コンパイルしました。
これだと、Windows ユーザーでも簡単です。
WSL の環境準備
つぎの記事のように、WSL で Ubuntu を立ち上げます。ちゃんと、起動して C ドライブ(/mnt/c/)を参照できれば OK でしょう。
基本的な Linux コマンドの説明は省略します。
OpenSSL
WSL 環境下で OpenSSL を静的ライブラリー (.a) を作成します。初めてやってみるとけっこうむずかしいです。(やってみた例)
Windows のときは、「Shining Light Prductions」から OpenSSL をインストールしたように今回も用意されたものでやろうと思います。ちょうど Android 向けに openssl を公開しているリポジトリーがあったので、これをクローンすることにします。
mkdir sqlite3 cd sqlite3 git clone https://github.com/KDAB/android_openssl.git
git のコマンドが走らないときは、パッケージをインストール、または、更新しよう。
あっという間に OpenSSL の準備が完了しました。
sqlite3.c のコピー
SQLite3 の関数を定義した最もコアなソース sqlite3.c
ファイルは、Windows で作成したものと同じものにしたいので、Windows 版で作成したものをコピーすることにします。
WSL は /mnt/c/
を通して C ドライブ直下にアクセスできるので、こんな感じになります。
cp /mnt/c/repo/sqlcipher/sqlite3.c sqlite3.c
これで、ファイルの準備ができました。
sqlite3.c ファイルは x86/x64 で別々にコピーしたほうがよいと思います。(データを比べてないので、詳細を調べていません)
コンパイラー (NDK) の準備
Unity 2019.3 にあわせて NDK 19c をダウンロードして、圧縮ファイルを解凍します。
ファイルがかなりあるため、解凍するまで数分待ちます。
wget https://dl.google.com/android/repository/android-ndk-r19c-linux-x86_64.zip
unzip android-ndk-r19c-linux-x86_64.zip -d ndk
解凍完了すると、こんな感じになりました。
補足として、NDK r19 からビルド(コンパイル)のやり方が変わっています。古い記事とやりかたを混同しないように注意が必要です。
コンパイル
export ANDROID_NDK_HOME=$HOME/sqlite3/ndk/android-ndk-r19c export LLVM_L_X86_64=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64 export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64 export TOOLCHAIN_BIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin export PATH=$TOOLCHAIN_BIN:$PATH echo $PATH
結論としては、ビルドしやすいように PATH に NDK のツールチェインのパスを通してあげることです。
今度は、OpenSSL の環境変数も設定します。
export OPENSSL_STATIC_LIB=$HOME/sqlite3/android_openssl/static
今回のコンパイルでは、Android 28 を指定しています。(詳細は「Android version history」などを参考にします)
# x64 のビルド mkdir arm_x64 aarch64-linux-android28-clang -shared -DSQLITE_HAS_CODEC -fPIC -I ${OPENSSL_STATIC_LIB}/include sqlite3.c -o arm_x64/libsqlcipher.so ${OPENSSL_STATIC_LIB}/lib/libcrypto_arm64-v8a.a # x86 のビルド mkdir arm_x86 armv7a-linux-androideabi28-clang -shared -DSQLITE_HAS_CODEC -fPIC -I ${OPENSSL_STATIC_LIB}/include sqlite3.c -o arm_x86/libsqlcipher.so ${OPENSSL_STATIC_LIB}/lib/libcrypto_armeabi-v7a.a
sqlite3.c は x86/x64 で別々に用意する必要があるのかどうかは知らないです。Windows では別々に作れてるし、使い分けました。
完成しました。
暗号化に対応しているかチェックする要点
これも Windows の dumpbin と同じようにちゃんと sqlite3_key
関数が定義されたライブラリーかどうかをチェックしておきましょう。
cd arm_x86 /usr/bin/objdump --all-headers libsqlcipher.so > libsqlcipher.so.dump cd arm_x64 /usr/bin/objdump --all-headers libsqlcipher.so > libsqlcipher.so.dump
x86/x64 かどうかのチェックは「補足」の記事を参考に。
問題なさそうですね。
これで、Windows と Android 向けの DllImport
に対応したライブラリーファイル (x86/x64) を用意することができました。
おまけ
参考にした記事にも書かれていることですが、ビルドしたファイルは、ライブラリーのファイルサイズを削減できていることや、JAVA などの依存も消えてシンプルにスマートになりました。
SQLiteUnityKit を基礎にして、自分なりに DB 用クラスをカスタマイズできるのもメリットですが、個人的には、こうした試行錯誤を1回経験しておくというのもよかったと思います。広い経験値があります。(純血の Windows ユーザーなら特にそう思う)
こうして結果だけ書くとシンプルなコンパイルの工程だけど、試行錯誤にけっこうな時間がかかるやつでした。
デバッグ
むずかしくてうまくコンパイルできない、どうしてだ! ってなったときは、とりあえず SQLite3 だけのコンパイルが NDK でやれるのかチェックしてみるとよいと思います。
mkdir sqlite-test cd sqlite-test wget https://www.sqlite.org/2020/sqlite-amalgamation-3310100.zip unzip sqlite-amalgamation-3310100.zip cd sqlite-amalgamation-3310100 mkdir arm_x86 mkdir arm_x64 armv7a-linux-androideabi28-clang -shared sqlite3.c -fPIC -o arm_x86/sqlite3.so aarch64-linux-android28-clang -shared sqlite3.c -o arm_x64/sqlite3.so
環境変数を export
で、ちゃんとパスを定義できているか見てみるのも大切。(ウィンドウをあたらしくすると export 環境変数も消える)
env echo $PATH
補足として、sqlite3.c のファイルはここにそもそもあるじゃないか! と思って、これを代用しても SQLCipher のコンパイルは通ります。通りますが、
sqlite3_key
の関数定義は追加されません。この sqlite3.c には定義されていないからですね。
参考
- 作者:結城 浩
- 発売日: 2015/08/26
- メディア: 単行本