LoginSignup
17
16

More than 5 years have passed since last update.

Android Studioでndk-buildを使う

Posted at

はじめに

Android StudioでNDKをビルドするためのツールとして、cmakeとndk-buildがある。

公式にはcmakeが推奨なため、ndk-buildを使った方法の説明が不十分なので、ここに記録を残す。
https://developer.android.com/studio/projects/add-native-code

externalNativeBuildブロックを使う方法

基本的には、この方法を使う。

フォルダ構造

├── app
│   ├── build.gradle
│   ├── src
│   │   ├─- main
│   │   │   ├── AndroidManifest.xml
│   │   │   ├── java
│   │   │   ├── jni
│   │   │   │   ├── Android.mk
│   │   │   │   ├── Application.mk
│   │   │   │   ├── *.c
│   │   │   │   ├── *.h
│   │   │   ├── res
├── build.gradle
├── settings.gradle

build.gradleの設定

build.gradle


android {

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 28

        ndk {
            // NDKビルドするABIを指定する
            abiFilters 'x86', 'armeabi-v7a'
        }
    }

    externalNativeBuild {
        ndkBuild {
            // Android.mkのファイルパス
            path 'src/main/jni/Android.mk'
        }
    }

    buildTypes {
        debug {
            externalNativeBuild {
                ndkBuild {
                    // debugビルド時にのみ指定する、ndk-buildの引数。
                    arguments 'LOCAL_CFLAGS+=-SOME_FLAG1', 'LOCAL_CFLAGS+=-DSOME_FLAG2'
                }
            }
        }

        release {
            externalNativeBuild {
                ndkBuild {
                    // releaseビルド時にのみ指定する、ndk-buildの引数。
                    arguments 'LOCAL_CFLAGS+=-SOME_FLAG3', 'LOCAL_CFLAGS+=-DSOME_FLAG4'
                }
            }
        }

  • Application.mkの APP_PLATFORMとAPP_ABIは無視され、build.gradleのabiFilters、minSdkVersionから自動で設定される。

ndk-build用カスタムタスクを追加する方法

externalNativeBuildブロックを使う方法だと、Android.mkのAPP_PLATFORMは無視され、build.gradleのminSdkVersionから自動で設定されてしまう。そのため次のようなプロジェクトの場合に問題となる。
* minSdkVersionは9
* NDKで作るnative libraryではOpenGL ES (18以上で利用サポート)を使う
(当然、API levelが18以上時のみSystem.LoadLibrary()をする必要がある。)

このようなプロジェクトの場合、ndk-build用のカスタムタスクを作成して実行する。

フォルダ構造

├── app
│   ├── build.gradle
│   ├── src
│   │   ├─- main
│   │   │   ├── AndroidManifest.xml
│   │   │   ├── java
│   │   │   ├── native   ## jniとするとerrorになる。
│   │   │   │   ├── Android.mk
│   │   │   │   ├── Application.mk
│   │   │   │   ├── *.c
│   │   │   │   ├── *.h
│   │   │   ├── res
├── build.gradle
├── settings.gradle

build.gradleの設定

build.gradle

android {

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 28
    }

    // Put src/main/libs in aar
    sourceSets {
        main {
            jniLibs.srcDir 'src/main/libs'
        }
    }
}

tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn buildNative}

// ndk-build用の buildNativeタスクの作成
task buildNative(type: Exec) {
    // ndk-buildの設定。 環境変数ANDROID_NDK_HOMEで設定
    def ndkBuild;
    def ndkBuildingDir = file(new File("src/main"))
    def hasNdk = false;
    if (System.env.ANDROID_NDK_HOME != null) {
        hasNdk = true;
        ndkBuild = new File(System.env.ANDROID_NDK_HOME, 'ndk-build')
    }

    // ndk-buildの実行
    commandLine ndkBuild, "--directory", ndkBuildingDir, "APP_BUILD_SCRIPT=${ndkBuildingDir}/native/Android.mk", "NDK_APPLICATION_MK=${ndkBuildingDir}/native/Application.mk", "-j", Runtime.runtime.availableProcessors()

    doFirst {
        if (!hasNdk) {
            logger.error("ERROR: ANDROID_NDK_HOME not set.")
        }
        assert hasNdk : "ANDROID_NDK_HOME not set"
    }
}



// ndk-build clean用の task cleanNativeの作成
clean.dependsOn 'cleanNative'
task cleanNative(type: Exec) {
    def ndkBuild;
    def ndkBuildingDir = file(new File("src/main"))
    def hasNdk = false;
    if (System.env.ANDROID_NDK_HOME != null) {
        hasNdk = true;
        ndkBuild = new File(System.env.ANDROID_NDK_HOME, 'ndk-build')
    }

    commandLine ndkBuild, "--directory", ndkBuildingDir, "APP_BUILD_SCRIPT=${ndkBuildingDir}/native/Android.mk", "NDK_APPLICATION_MK=${ndkBuildingDir}/native/Application.mk", "-j1", "clean"

    doFirst {
        if (!hasNdk) {
            logger.error("ERROR: ANDROID_NDK_HOME not set.")
        }
        assert hasNdk : "ANDROID_NDK_HOME not set"
    }
}


17
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16