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編)](http://qiita.com/idaisuke/items/22e2ebc24812681cd61d)

### ソースコードをリポジトリからクローン
```bash
mkdir SQLCipher
cd SQLCipher
git clone git://github.com/sqlcipher/sqlcipher.git src
```

### Android NDK Standalone Toolchainの作成
```bash
$NDK_ROOT/build/tools/make-standalone-toolchain.sh --arch=arm --install-dir=toolchain --platform=android-19
```

### クロスコンパイル時のホストの設定
※ arm-linux-androideabiとするとそんなもん知らんと怒られるのでarm-linuxにする。

```bash
HOST=arm-linux
```

### Toolchainのファイル名を変更する
arm-linux-androideabi-gcc > arm-linux-gcc のように名前を変更する。

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

### ビルドする
```bash
cd src
```

###### Toolchainのパスを設定
```bash
export PATH=/Users/ditabashi/SQLCipher/toolchain/bin:$PATH
```

##### armeabi
###### アーキテクチャを設定
```bash
ARCH=armv5
```

###### インストールディレクトリを設定
```bash
PREFIX=/Users/ditabashi/SQLCipher/dest/armeabi
```

###### OpenSSLのパスを設定
```bash
OPENSSL_INCLUDE_PATH=/Users/ditabashi/OpenSSL/dest/armeabi/include
OPENSSL_LIBRARY_PATH=/Users/ditabashi/OpenSSL/dest/armeabi/lib
```

###### コンフィグ
```bash
./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"
```

###### ビルド & インストール
```bash
make clean && make && make install
```

##### armeabi-v7a
###### アーキテクチャを設定
```bash
ARCH=armv7-a
```

###### インストールディレクトリを設定
```bash
PREFIX=/Users/ditabashi/SQLCipher/dest/armeabi-v7a
```

###### OpenSSLのパスを設定
```bash
OPENSSL_INCLUDE_PATH=/Users/ditabashi/OpenSSL/dest/armeabi-v7a/include
OPENSSL_LIBRARY_PATH=/Users/ditabashi/OpenSSL/dest/armeabi-v7a/lib
```

###### コンフィグ
```bash
./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"
```

###### ビルド & インストール
```bash
make clean && make && make install
```




### Cocos2d-xプロジェクトに追加する
![sqlcipher_path.png](https://qiita-image-store.s3.amazonaws.com/0/67518/f89129a4-2ea1-24fe-3838-0e2f064e2de0.png "sqlcipher_path.png")


###### 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を追加する。
```bash: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

```

### 使ってみる
```cpp
#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
の順に実行して下さい。