Cocos2d-xでSQLCipherを使う(Android編)


SQLCipherとは

https://www.zetetic.net/sqlcipher/
オープンソースのSQLite暗号化ライブラリです。
BSDスタイルのライセンスを採用しており、ライセンス表記すれば無償で使用出来ます。
公式サイトにあるAndroidライブラリはJava用なのでそのままではCocos2d-xで使えません。
なのでAndroid向けにビルドしてみました。
今回はその時の手順のメモです。

実行した環境
  • OS X 10.10.3
  • Cocos2d-x v3.6
  • Android NDK r10d

OpenSSLをビルドする

OpenSSLが必要なのでまずOpenSSLをビルドしておく。
Cocos2d-xでOpenSSLを使う(Android編)

ソースコードをリポジトリからクローン

mkdir SQLCipher
cd SQLCipher
git clone git://github.com/sqlcipher/sqlcipher.git src

Android NDK Standalone Toolchainの作成

$NDK_ROOT/build/tools/make-standalone-toolchain.sh --arch=arm --install-dir=toolchain --platform=android-19

クロスコンパイル時のホストの設定

※ arm-linux-androideabiとするとそんなもん知らんと怒られるのでarm-linuxにする。

HOST=arm-linux

Toolchainのファイル名を変更する

arm-linux-androideabi-gcc > arm-linux-gcc のように名前を変更する。

find toolchain/bin -name arm-linux-androideabi* -type f | while read FILE
do
  cp -f $FILE ${FILE%/*}/arm-linux${FILE##*-androideabi}
done

ビルドする

cd src
Toolchainのパスを設定
export PATH=/Users/ditabashi/SQLCipher/toolchain/bin:$PATH
armeabi
アーキテクチャを設定
ARCH=armv5
インストールディレクトリを設定
PREFIX=/Users/ditabashi/SQLCipher/dest/armeabi
OpenSSLのパスを設定
OPENSSL_INCLUDE_PATH=/Users/ditabashi/OpenSSL/dest/armeabi/include
OPENSSL_LIBRARY_PATH=/Users/ditabashi/OpenSSL/dest/armeabi/lib
コンフィグ
./configure --prefix=$PREFIX -host=$HOST --enable-tempstore=yes --disable-tcl --disable-readline CFLAGS="-DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -march=$ARCH -fPIE -I$OPENSSL_INCLUDE_PATH" LDFLAGS="-L$OPENSSL_LIBRARY_PATH"
ビルド & インストール
make clean && make && make install
armeabi-v7a
アーキテクチャを設定
ARCH=armv7-a
インストールディレクトリを設定
PREFIX=/Users/ditabashi/SQLCipher/dest/armeabi-v7a
OpenSSLのパスを設定
OPENSSL_INCLUDE_PATH=/Users/ditabashi/OpenSSL/dest/armeabi-v7a/include
OPENSSL_LIBRARY_PATH=/Users/ditabashi/OpenSSL/dest/armeabi-v7a/lib
コンフィグ
./configure --prefix=$PREFIX -host=$HOST --enable-tempstore=yes --disable-tcl --disable-readline CFLAGS="-DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -march=$ARCH -fPIE -I$OPENSSL_INCLUDE_PATH" LDFLAGS="-L$OPENSSL_LIBRARY_PATH"
ビルド & インストール
make clean && make && make install

Cocos2d-xプロジェクトに追加する

Android.mkの中身
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/$(TARGET_ARCH_ABI)/include/sqlcipher

LOCAL_MODULE := sqlcipher
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/lib/libsqlcipher.a
include $(PREBUILT_STATIC_LIBRARY)

プロジェクトのAndroid.mkを修正

Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

$(call import-add-path,$(LOCAL_PATH)/../../cocos2d)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/cocos)

# **これを追加**
$(call import-add-path,$(LOCAL_PATH)/../../Libraries)

LOCAL_MODULE := cocos2dcpp_shared

LOCAL_MODULE_FILENAME := libcocos2dcpp

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../Classes/AppDelegate.cpp \
                   ../../Classes/HelloWorldScene.cpp

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes

# _COCOS_HEADER_ANDROID_BEGIN
# _COCOS_HEADER_ANDROID_END


LOCAL_STATIC_LIBRARIES := cocos2dx_static

# **これを追加**
LOCAL_STATIC_LIBRARIES += crypto ssl
LOCAL_STATIC_LIBRARIES += sqlcipher

# _COCOS_LIB_ANDROID_BEGIN
# _COCOS_LIB_ANDROID_END

include $(BUILD_SHARED_LIBRARY)

$(call import-module,.)

# _COCOS_LIB_IMPORT_ANDROID_BEGIN
# _COCOS_LIB_IMPORT_ANDROID_END

# **これを追加**
$(call import-module,OpenSSL/Android)
$(call import-module,SQLCipher/Android)

Application.mkにCPPFLAGSを追加する。

Application.mk
APP_STL := gnustl_static

APP_CPPFLAGS := -frtti -DCC_ENABLE_CHIPMUNK_INTEGRATION=1 -std=c++11 -fsigned-char

# **これを追加**
APP_CPPFLAGS += -DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2

APP_LDFLAGS := -latomic


ifeq ($(NDK_DEBUG),1)
  APP_CPPFLAGS += -DCOCOS2D_DEBUG=1
  APP_OPTIM := debug
else
  APP_CPPFLAGS += -DNDEBUG
  APP_OPTIM := release
endif

使ってみる

#include <sqlite3.h>

void testSQLCipher() {
    auto path = cocos2d::FileUtils::getInstance()->getWritablePath() + "test.db";
    std::string passphrase("abcdefghijklmn");
    sqlite3 *db;
    sqlite3_open(path.c_str(), &db);
    sqlite3_key(db, passphrase.c_str(), passphrase.length());
    sqlite3_exec(db, "CREATE TABLE chara(id INTEGER, name TEXT);", nullptr, nullptr, nullptr);
    sqlite3_exec(db, "INSERT INTO chara VALUES(1, 'キャラA');", nullptr, nullptr, nullptr);
    sqlite3_exec(db, "INSERT INTO chara VALUES(2, 'キャラB');", nullptr, nullptr, nullptr);
    sqlite3_exec(db, "INSERT INTO chara VALUES(3, 'キャラC');", nullptr, nullptr, nullptr);

    sqlite3_stmt *stmt;
    sqlite3_prepare(db, "SELECT * FROM chara;", -1, &stmt, nullptr);
    while (SQLITE_DONE != sqlite3_step(stmt)) {
        auto id = sqlite3_column_int(stmt, 0);
        auto name = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
        CCLOG("id = %d, name = %s", id, name);
    }
    sqlite3_finalize(stmt);

    sqlite3_close(db);
}

おしまい

以上のことをまとめてシェルスクリプトにしてGitHubに置いておきました。
https://github.com/idaisuke/hydrogenium
cloneした後、
①build-libssl-for-android.sh
②build-libsqlcipher-for-android.sh
の順に実行して下さい。