KISS

Keep It Simple Stupid

NDK build in the latest gradle-android plugin

| comments

As I have written in a recent post, I migrated an android project to gradle and had to add NDK build steps there. It worked well, until I upgraded the Android Studio to 0.4.0, which triggered an update to gradle 1.9, which triggered an update to 0.7.0. I had a few issues to resolve after that. Read on to know how to resolve them if you’re in the same situation.

jniDir() method not found

The first issue is this:

1
2
3
4
5
6
7
8
FAILURE: Build failed with an exception.

* Where:
Build file '…/build.gradle' line: 143

* What went wrong:
A problem occurred configuring project ':project'.
> org.gradle.api.internal.MissingMethodException: Could not find method jniDir() for arguments [/build/lib] on task ':project:packageDebug'.

So, they removed the jniDir method. After digging into the sources of the gradle-android plugin, here’s the fix. In this method:

1
2
3
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
    pkgTask.jniDir new File(buildDir, 'lib')
}

change the second line to:

1
pkgTask.jniFolders = [new File(buildDir, 'lib')]

“NDK not configured”

The second issue: the 0.7.0 version added an undocumented, rough NDK support. Now the plugin’s NDK step fails:

1
2
3
4
5
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':project:compileDebugNdk'.
> NDK not configured

By http://stackoverflow.com/questions/20674650/how-to-configure-ndk-with-android-gradle-plugin-0-7 we need to add the following line to local.properties (change the path to yours!):

1
ndk.dir=/Users/user/bin/android-ndk-r9/

Turning off NDK support

Unfortunately, in my project the C++ sources are located outside the Android project directory, so the modules’ .mk files have these relative links: LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../../libs/lib1/include. Now the build fails with errors of not found includes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':project:compileDebugNdk'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
    /android-ndk-r9/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/project/build/ndk/english/debug/Android.mk APP_PLATFORM=android-8 NDK_OUT=/project/build/ndk/english/debug/obj NDK_LIBS_OUT=/project/build/ndk/english/debug/lib APP_ABI=all
  Error Code:
    2
  Output:
    /project/src/main/jni/main.cpp:10:71: fatal error: ../../../libs/lib1/include/header.hpp: No such file or directory
    compilation terminated.
    make: *** […/project/build/ndk/english/debug/obj/local/x86/objs/project//project/src/main/jni/main.o] Error 1
    make: *** Waiting for unfinished jobs....
    …/project/src/main/jni/main.cpp:10:71: fatal error: ../../../libs/lib1/include/header.hpp: No such file or directory
    /project/src/main/jni/main.cpp:10:71: fatal error: ../../../libs/lib1/include/header.hpp: No such file or directorycompilation terminated.

    compilation terminated.
    …/project/src/main/jni/main.cpp:10:71: fatal error: ../../../libs/lib1/include/header.hpp: No such file or directory
    compilation terminated.
    make: *** [/project/build/ndk/english/debug/obj/local/armeabi/objs/project/…/project/src/main/jni/main.o] Error 1
    make: *** [/project/build/ndk/english/debug/obj/local/armeabi-v7a/objs/project/…/project/src/main/jni/main.o] Error 1
    make: *** [/project/build/ndk/english/debug/obj/local/mips/objs/project/…/project/src/main/jni/main.o] Error 1

The plugin copies the jni/ directory into the build directory and tries to build it there. That’s the correct approach, but the include paths are wrong then. So to avoid NDK building with the plugin and use the old way instead, I renamed the jni/ dir into native/, and had to add extra parameters to the build command (the buildNative task):

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

And likewise for the cleanNative task:

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

Done! The project gets built fine again.

Comments