👻

Android NDKのCMakeを使用したProductFlavorごとにネイティブコードを分ける

3 min read

TL;DR

build.gradleのproductFlavorsでFlavorごとに引数を与えてCMakeListsで分岐させる。

Android NDKとは

Android NDK は、C / C++(ネイティブ コード)を Android アプリに埋め込むことができるツールです。
重い演算処理、ネイティブコードに秘匿情報を記述しデコンパイルしても見えないようにする、等に使用されます。

CMakeとは

コンパイラに依存しないビルド自動化のためのツールです。androidで言うところのgradleですかね・・・・(レイヤーが違う気もする(anroidはjava自体はコンパイラに依存しないようになってますので)がビルドツールという点では一緒)

ProductFlavorとは

ProductFlavor
環境依存のコード(API endpointやその他環境変数)を難しいことをせずにソースファイルごとまるっと差し替えるときに使用します。

通常のjavaコードまたはkotlinコードを差し替える場合

パッケージを変えることによって実現することができます。
例えば下記のようにproductFlavorsが定義されてるとします。
例 app/build.gradle

android {
    ...
    defaultConfig {...}
    buildTypes {
        debug{...}
        release{...}
    }
    // ココでProductFlavorの種類を定義する
    flavorDimensions "flavor"
    productFlavors {
        "flavor1" {
        }
        "flavor2" {
        }
    }
}

上記の様に定義すると
src/flavor1/
src/flavor2/
配下にjava, kotlinコードを配置するとbuildする際に指定したproductFlavorによって自動でコードを差し替えてくれます。

Android NDKのコードを差し替える場合はどうするのか

上記の様にソースファイルを差し替えれるのかなと思ったらどうやらできないご様子・・・・。

Cmakeを使用する場合はapp/build.gradleに下記のようにCmakeLists.txtへのパスを記載するのですが、CmakeはproductFlavorを感知しないので先述のやり方でソースコードを差し替えることはできませんでした(やり方あるのかもしれませんが・・・)。

android {
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

じゃあCmakeする際に引数を与えて、CmakeLists.txt内で分岐させよう!となりました。
各ProductFlavor内のCmakeを定義する部分に独自引数を追加します。

android {
    ...
    flavorDimensions "flavor"
    productFlavors {
        "flavor1" {
            externalNativeBuild {
                cmake {
                    // ココ!
                    arguments += "-DFLAVOR=FLAVOR1"
                }
            }
        }
        "flavor2" {
            externalNativeBuild {
                cmake {
                    // ココ!
                    arguments += "-DFLAVOR=FLAVOR2"
                }
            }
        }
    }
}

ここでは-DFLAVORという引数を追加してあげています。
そして、CmakeLists.txt内で読み込むcppファイルを差し替える分岐を作ってあげます。

if (${FLAVOR} STREQUAL "FLAVOR1")
    message("adding the source code for Flavor1...")
    add_library( # Sets the name of the library.
            hello-lib

            SHARED

            // 差し込んでるcppファイルが違う!       
            ${CMAKE_CURRENT_SOURCE_DIR}/flavor1/hello-lib.cpp)
elseif (${FLAVOR} STREQUAL "FLAVOR2")
    message("adding the source code for Flavor2...")
    add_library( # Sets the name of the library.
            hello-lib

            SHARED

            // 差し込んでるcppファイルが違う!
            ${CMAKE_CURRENT_SOURCE_DIR}/flavor2/hello-lib.cpp)
endif ()

こうすることでndkで使用するcppファイルをProductFlavorごとに差し替えることができました!

サンプルプロジェクトをGitHubに置いておくので参考にしてください。
NdkFlavor

Discussion

ログインするとコメントできます