I'm running into an Error when I open a new project in Android Studio from the Code Samples (Hello JIN). When the Project is opened the following:
Build command failed.
Error while executing process /opt/android-sdk/cmake/3.6.4111459/bin/cmake with arguments {-H/home/max/Documents/AndroidStudioProjects/HelloJNI1/app/src/main/cpp -B/home/max/Documents/AndroidStudioProjects/HelloJNI1/app/.externalNativeBuild/cmake/arm8Release/arm64-v8a -GAndroid Gradle - Ninja -DANDROID_ABI=arm64-v8a -DANDROID_NDK=/opt/android-sdk/ndk-bundle -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/home/max/Documents/AndroidStudioProjects/HelloJNI1/app/build/intermediates/cmake/arm8/release/obj/arm64-v8a -DCMAKE_BUILD_TYPE=Release -DCMAKE_MAKE_PROGRAM=/opt/android-sdk/cmake/3.6.4111459/bin/ninja -DCMAKE_TOOLCHAIN_FILE=/opt/android-sdk/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=android-23 -DANDROID_TOOLCHAIN=clang}
-- Check for working C compiler: /opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
-- Check for working C compiler: /opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -- broken
-- Configuring incomplete, errors occurred!
See also "/home/max/Documents/AndroidStudioProjects/HelloJNI1/app/.externalNativeBuild/cmake/arm8Release/arm64-v8a/CMakeFiles/CMakeOutput.log".
See also "/home/max/Documents/AndroidStudioProjects/HelloJNI1/app/.externalNativeBuild/cmake/arm8Release/arm64-v8a/CMakeFiles/CMakeError.log".
CMake Error at /opt/android-sdk/cmake/3.6.4111459/share/cmake-3.6/Modules/CMakeTestCCompiler.cmake:61 (message):
The C compiler
"/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: /home/max/Documents/AndroidStudioProjects/HelloJNI1/app/.externalNativeBuild/cmake/arm8Release/arm64-v8a/CMakeFiles/CMakeTmp
Run Build Command:"/opt/android-sdk/cmake/3.6.4111459/bin/ninja"
"cmTC_0053d"
[1/2] Building C object CMakeFiles/cmTC_0053d.dir/testCCompiler.c.o
FAILED:
/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
--target=aarch64-none-linux-android
--gcc-toolchain=/opt/android-sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64
--sysroot=/opt/android-sdk/ndk-bundle/sysroot -isystem
/opt/android-sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-android
-D__ANDROID_API__=23 -g -DANDROID -ffunction-sections -funwind-tables
-fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat
-Werror=format-security -fPIE -o
CMakeFiles/cmTC_0053d.dir/testCCompiler.c.o -c
/home/max/Documents/AndroidStudioProjects/HelloJNI1/app/.externalNativeBuild/cmake/arm8Release/arm64-v8a/CMakeFiles/CMakeTmp/testCCompiler.c
/opt/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang:
error while loading shared libraries: libncurses.so.5: cannot open shared
object file: No such file or directory
ninja: build stopped: subcommand failed.
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt
This Error drops mutliple times in the IDE
I'm using Arch-Linux 64x
Cmake.txt:
cmake_minimum_required(VERSION 3.4.1)
add_library(hello-jni SHARED
hello-jni.c)
# Include libraries needed for hello-jni lib
target_link_libraries(hello-jni
android
log)
Build -> Refresh Linked C++ Projects resolved this error for me.
I found this Solution Online and this worked, however there was no explanation on how it worked:
Remove the following block of code from you build.gradle file:
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
#rpurohit was nearly right, Clang isn't working properly. But to change the Compiler you need to change build.gradle, in my build.gradle it was Line 12:
apply plugin: 'com.android.application'
1 android {
2 compileSdkVersion 25
3 buildToolsVersion '25.0.2'
4 defaultConfig {
5 applicationId 'com.example.hellojni'
6 minSdkVersion 23
7 targetSdkVersion 25
8 versionCode 1
9 versionName "1.0"
10 externalNativeBuild {
11 cmake {
12 arguments '-DANDROID_TOOLCHAIN=clang' --> gcc
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
productFlavors {
arm7 {
// in the future, ndk.abiFilter might also work
ndk {
abiFilter 'armeabi-v7a'
}
}
arm8 {
ndk {
abiFilters 'arm64-v8a'
}
}
arm {
ndk {
abiFilter 'armeabi'
}
}
x86 {
ndk {
abiFilter 'x86'
}
}
x86_64 {
ndk {
abiFilter 'x86_64'
}
}
mips {
ndk {
abiFilters 'mips', 'mips64'
}
}
universal {
ndk {
abiFilters 'mips', 'mips64', 'x86', 'x86_64'
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.2.0'
compile 'com.android.support.constraint:constraint-layout:1.0.1'
}
I would recommend using GCC instead of clang for the time being because clang still does not contain all features. You can change your compiler by doing the following:
set(CMAKE_C_COMPILER /path-to-ndk/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-gcc)
However, the darwin-x86_64 directory only exists if you are on a Mac. If you are on another platform, just use the directory that exists under the prebuilt folder.
I encountered this problem because I set the wrong path of native-lib.cpp. After changing
add_library(native-lib SHARED native-lib.cpp)
to
add_library(native-lib SHARED src/main/jni/native-lib.cpp)
it worked again.
By the way, this is part of my project's structure.
CMakeLists.txt
src
|__main
|___jni
|___native-lib.cpp
In case previous answer doesn't work for you, as it happened to me, try to fix permissions in the bin folder of cmake and for ndk. In my case: C:\android-sdk\cmake\3.6.4111459\bin and c:\android-sdk\ndk-bundle
In my case Users group did had no permissions so Android Studio wasn't able to run cmake. Make sure it has Read and execution permissions.
This error sometimes occurs when you upgrade gradle or other dependencies.
a simple solution is Build > "Refresh linked C++ project" and after that rebuilding your project. everything goes right
I tried the solutions provided above but no luck. Then I changed the path of OpenCV_DIR which was set in the CMakeLists.txt file and it worked. My project was not pointing to the right path, which was causing the error. Make sure you have provided the right path in your CMakeLists.txt file.
For example :
set(OpenCV_DIR "...../OpenCV_Android/install/sdk/native/jni/abi-arm64-v8a")
I find this way can work:
not need delete below:
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
this is useful .and your project just less the ninja file .
you can fllow this way can build successful!
here is the result:
Make was unable to find a build program corresponding to "Ninja". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
you should install ninja
download ninja here ninja download file
get the ninja file
copy the ninja file to the /usrlocal/bin
build again .the project run successfull!!
Related
I am trying to build and run the existing Android NDK project with latest Gradle. But I am getting below error while running the application.
Build command failed.
Error while executing process D:\rapiscan\Android\Sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build D:\rapiscan\codebase\NGC\NextGenConsole\app\.externalNativeBuild\cmake\debug\x86 --target UiDataProvider}
[1/4] Building CXX object UiDataProvider/CMakeFiles/UiDataProvider.dir/UiCmdHandler.cpp.o
[2/4] Building CXX object UiDataProvider/CMakeFiles/UiDataProvider.dir/UiDataProvider.cpp.o
[3/4] Building CXX object UiDataProvider/CMakeFiles/UiDataProvider.dir/UiMessageGenerator.cpp.o
FAILED: D:\rapiscan\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=i686-none-linux-android23 --gcc-toolchain=D:/rapiscan/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64 -DUiDataProvider_EXPORTS -IUiDataProvider -ID:/rapiscan/codebase/NGC/NextGenConsole/malibu/UiDataProvider -ID:/rapiscan/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/include/arm-linux-androideabi -ID:/rapiscan/codebase/NGC/NextGenConsole/malibu/Common -pthread -O0 -fno-limit-debug-info -fPIC -std=gnu++14 -MD -MT UiDataProvider/CMakeFiles/UiDataProvider.dir/UiDataProvider.cpp.o -MF UiDataProvider\CMakeFiles\UiDataProvider.dir\UiDataProvider.cpp.o.d -o UiDataProvider/CMakeFiles/UiDataProvider.dir/UiDataProvider.cpp.o -c D:\rapiscan\codebase\NGC\NextGenConsole\malibu\UiDataProvider\UiDataProvider.cpp
In file included from D:\rapiscan\codebase\NGC\NextGenConsole\malibu\UiDataProvider\UiDataProvider.cpp:1:
D:/rapiscan/codebase/NGC/NextGenConsole/malibu/UiDataProvider/UiDataProvider.h:5:10: fatal error: 'string' file not found
`#include <string>`
1 error generated.
Below is the ndk configuration specified in app build.gradle
ndk {
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a','x86'
}
externalNativeBuild {
cmake {
arguments '-DCMAKE_BUILD_TYPE=Debug',"-DPROJECT_DIR:STRING=${mb_sdk_path}",'-DANDROID_PLATFORM=android-23', '-DANDROID_TOOLCHAIN=clang', '-DANDROID_ARM_NEON=TRUE', "-DPATH_TO_MALIBU:STRING=${mb_sdk_path}" ,"-DANDROID_STL=c++_static",
"-DTARGET_PLATFORM=Windows","-DUNIX=FALSE"
cppFlags "-std=c++14 -stdlib=libc++ -frtti -fexceptions"
}
}
}
and below is the build.gradle
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.1'
classpath 'com.novoda:bintray-release:0.9'
}
}
I had the same problem with last version of gradle and cmake in my project, but I detected that only occurs when the Build Variants is wrong, for example the target is debug-armeabi-v7a but you are in a release compiling, please review the right variant target.
My settings:
NDK 19.1.5304403
CMake 3.10.2
build.gradle:
defaultConfig {
...
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
...
externalNativeBuild {
cmake {
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
...
NOTE: sometimes too you should remove the hidden directory rm -rf app/.externalNativeBuild for it works
Using -stdlib=libc++ with CMake is either redundant or broken on every NDK version. What you want is -DANDROID_STL=c++_shared (or -DANDROID_STL=c++_static for the static library, or nothing at all for the static library on NDK r18+ since that's the default).
Passing -stdlib=libc++ may cause the compiler to look in the wrong location on older NDK releases, and is the default on r19+.
Background
I'm currently working on an Android project which contains a fair amount of native code. The native code is built for multiple ABIs. For various reasons, the native code has up until now been built using a custom Gradle task that invokes ndk-build.cmd.
Now I'm in the process of changing this to use externalNativeBuild for the NDK integration, and CMake lists instead of the old Android.mk files. It seems like the better supported/documented way of doing things.
Problem
One nice thing about the old ndk-build method was that it would build for multiple ABIs in parallel - e.g. an ARM version and an x86 version of the library could be built in parallel.
This is especially helpful in my case, because I am required to use a 3rd party tool during the linking phase which 1) takes a very long time (minutes) to finish, and 2) is mostly single-threaded. Hence, building the library for multiple ABIs in parallel helped shorten my build times a lot.
When building with CMake / Ninja I cannot replicate this behavior. Ninja is supposed to parallelize builds by default, and it may well be doing that for a given ABI (i.e. compiling multiple source files in parallel for the same ABI). But from what I can tell, it never starts building the library for another ABI until it has finished building for the current ABI.
Question
When using CMake / Ninja through externalNativeBuild, is there any way I can tell the build system that I want it to build my native code for multiple ABIs in parallel?
Example
A minimal example to demonstrate this is as simple as the "New project" template in Android Studio, i.e. something like:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib SHARED
src/main/cpp/native-lib.cpp )
app/build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.cmakemultiabis"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
ndk {
abiFilters 'armeabi-v7a', 'x86'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
And then building with e.g. gradlew assembleRelease will give you:
> Task :app:externalNativeBuildRelease
Build native-lib x86
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\release\obj\x86\libnative-lib.so
Build native-lib armeabi-v7a
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\release\obj\armeabi-v7a\libnative-lib.so
It may not be obvious from that output that the two libraries are built sequentially, but it does become obvious if you have something that takes a noticeable amount of time to link.
I have tried this both with the CMake / Ninja versions that you can download with the SDK Manager, as well as some newer versions (CMake 3.12.3, Ninja 1.8.2), and saw the same behavior in both cases.
I am developing simple ndk sample example using android ndk in android studio. While running my app studio shows below errors.
Build command failed.
Error while executing process D:\Sdk\cmake\3.6.4111459\bin\cmake.exe with
arguments {--build D:\Android Studio\Workspace\NDKSample\app\.externalNativeBuild\cmake\debug\arm64-v8a --target native-lib}
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.oFAILED: D:\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android --gcc-toolchain=D:/Sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64 --sysroot=D:/Sdk/ndk-bundle/sysroot -Dnative_lib_EXPORTS -isystem D:/Sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include -isystem D:/Sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/arm64-v8a/include -isystem D:/Sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include/backward -isystem D:/Sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -frtti -fexceptions -O0 -fno-limit-debug-info -fPIC -MD -MT CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o -MF CMakeFiles\native-lib.dir\src\main\cpp\native-lib.cpp.o.d -o CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o -c "D:\Android Studio\Workspace\NDKSample\app\src\main\cpp\native-lib.cpp"
error: error reading 'D:\Android Studio\Workspace\NDKSample\app\src\main\cpp\native-lib.cpp'
1 error generated.ninja: build stopped: subcommand failed.
I have search lot but not able to find proper answer that why I am asking here. I have also unintsall all the components and re-install on my studio still error is there.
Another thing If I change file extension to .C from .CPP whole project gets complied and even runs properly. I don't know why Its not working for .CPP file.
Components I am using.
Android Stuido - 3.1.3
gradle - 3.1.0
cmake - 3.6.4111459
Android ndk - 17.1.4828580
lldb -3.1
native-lib.cpp
#include <jni.h>#include <string>extern "C" JNIEXPORT jstringJNICALLJava_com_mastek_ndksample_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());}
build.gradle
apply plugin: 'com.android.application'android { compileSdkVersion 27
defaultConfig {
applicationId "com.example.ndksample"
minSdkVersion 15
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}}dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'}
Anyone know please help me to solve this problem. Thanks in advance.
NDK build fails miserably when the path to project files contains spaces. To fix your build, copy the project to path without spaces.
After lot of trials and help from github google guy I am able to solve. To resolve problem I have follow below steps.
1.go to project directory.
2.deleted .gradle ,app/.externalNativeBuild and app/build.
3.changed local.properties ndk path to external ndk-r16b.
4.Run through Android studio.
5.Finally apk is generate.
When you have
android {
defaultConfig {
ndk {
moduleName "yourlib"
stl "stlport_static"
ldLibs "log", "z", "m"
cFlags "-I/some/include/dir/"
}
...
}
...
}
in your build.gradle then Gradle will compile the files in src/main/jni/ and it will generate an Android.mk in build/ndk/debug/Android.mk.
However, in my case, I'm trying to compile some C++ files compiled against OpenCV.
I have this working when I manually create the Android.mk file and run the ndk-build command. But I want to do it via Gradle / Android Studio automatically.
When doing this manually, I include the libraries to link against. I do this, in the manually created Android.mk, with the line:
include /path/to/the/opencv/directory/sdk/native/jni/OpenCV.mk
However, in Android's Gradle plugin, I am unsure of how to add this 'include' directive in the generated Android.mk file.
Can anyone point me in the right Gradle-directive direction to add this line to the generate file? Thanks.
I've found that that the build process will pull everything in from below the ./src/main/jni folder. So, I've placed symlinks there to include and src folders elsewhere - the src files will be enumerated into the .mk file by the build process and the inc files will be scooped up by the compiler. Perhaps its a bit hacky:
android {
defaultConfig {
ndk {
moduleName "yourlib"
cFlags "-std=c99 -I${project.buildDir}/../src/main/jni/inc"
}
...
}
...
}
I also have different cFlags depending upon debug build. This seems to be valid gradle, but doesn't want to build with android-studio. It will build with the gradlew command tho:
android {
defaultConfig {
ndk {
moduleName "yourlib"
cFlags "-std=c99 -I${project.buildDir}/../src/main/jni/inc"
}
...
}
...
buildTypes {
release {
debuggable false
jniDebugBuild false
ndk {
moduleName "yourlib"
}
}
debug {
debuggable true
jniDebugBuild true
ndk {
moduleName "yourlib"
ldLibs "log"
cFlags "-g -D_DEBUG"
}
}
}
}
I hope it can help you (android-studio 0.8.6).
I'm trying to add native code to my app. I have everything in ../main/jni as it was in my Eclipse project. I have added ndk.dir=... to my local.properties. I haven't done anything else yet (I'm not sure what else is actually required, so if I've missed something let me know). When I try and build I get this error:
Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
/Users/me/android-ndk-r8e/ndk-build NDK_PROJECT_PATH=null
APP_BUILD_SCRIPT=/Users/me/Project/app/build/ndk/debug/Android.mk APP_PLATFORM=android-19
NDK_OUT=/Users/me/Project/app/build/ndk/debug/obj
NDK_LIBS_OUT=/Users/me/Project/app/build/ndk/debug/lib APP_ABI=all
Error Code:
2
Output:
make: *** No rule to make target `/Users/me/Project/webapp/build/ndk/debug//Users/me/Project/app/src/main/jni/jni_part.cpp',
needed by `/Users/me/Project/app/build/ndk/debug/obj/local/armeabi-v7a/objs/webapp//Users/me/Project/app/src/main/jni/jni_part.o'.
Stop.
What do I need to do?
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# OpenCV
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
include .../OpenCV-2.4.5-android-sdk/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := native_part
LOCAL_SRC_FILES := jni_part.cpp
LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
Application.mk:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-8
Gradle Build Tools 2.2.0+ - The closest the NDK has ever come to being called 'magic'
In trying to avoid experimental and frankly fed up with the NDK and all its hackery I am happy that 2.2.x of the Gradle Build Tools came out and now it just works. The key is the externalNativeBuild and pointing ndkBuild path argument at an Android.mk or change ndkBuild to cmake and point the path argument at a CMakeLists.txt build script.
android {
compileSdkVersion 19
buildToolsVersion "25.0.2"
defaultConfig {
minSdkVersion 19
targetSdkVersion 19
ndk {
abiFilters 'armeabi', 'armeabi-v7a', 'x86'
}
externalNativeBuild {
cmake {
cppFlags '-std=c++11'
arguments '-DANDROID_TOOLCHAIN=clang',
'-DANDROID_PLATFORM=android-19',
'-DANDROID_STL=gnustl_static',
'-DANDROID_ARM_NEON=TRUE',
'-DANDROID_CPP_FEATURES=exceptions rtti'
}
}
}
externalNativeBuild {
cmake {
path 'src/main/jni/CMakeLists.txt'
}
//ndkBuild {
// path 'src/main/jni/Android.mk'
//}
}
}
For much more detail check Google's page on adding native code.
After this is setup correctly you can ./gradlew installDebug and off you go. You will also need to be aware that the NDK is moving to clang since gcc is now deprecated in the Android NDK.
Android Studio Clean and Build Integration - DEPRECATED
The other answers do point out the correct way to prevent the automatic creation of Android.mk files, but they fail to go the extra step of integrating better with Android Studio. I have added the ability to actually clean and build from source without needing to go to the command-line. Your local.properties file will need to have ndk.dir=/path/to/ndk
apply plugin: 'com.android.application'
android {
compileSdkVersion 14
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "com.example.application"
minSdkVersion 14
targetSdkVersion 14
ndk {
moduleName "YourModuleName"
}
}
sourceSets.main {
jni.srcDirs = [] // This prevents the auto generation of Android.mk
jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project.
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
def ndkDir = android.ndkDirectory
commandLine "$ndkDir/ndk-build",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'-j', Runtime.runtime.availableProcessors(),
'all',
'NDK_DEBUG=1'
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
def ndkDir = android.ndkDirectory
commandLine "$ndkDir/ndk-build",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'clean'
}
clean.dependsOn 'cleanNative'
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
}
dependencies {
compile 'com.android.support:support-v4:20.0.0'
}
The src/main/jni directory assumes a standard layout of the project. It should be the relative from this build.gradle file location to the jni directory.
Gradle - for those having issues
Also check this Stack Overflow answer.
It is really important that your gradle version and general setup are correct. If you have an older project I highly recommend creating a new one with the latest Android Studio and see what Google considers the standard project. Also, use gradlew. This protects the developer from a gradle version mismatch. Finally, the gradle plugin must be configured correctly.
And you ask what is the latest version of the gradle plugin? Check the tools page and edit the version accordingly.
Final product - /build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
// Running 'gradle wrapper' will generate gradlew - Getting gradle wrapper working and using it will save you a lot of pain.
task wrapper(type: Wrapper) {
gradleVersion = '2.2'
}
// Look Google doesn't use Maven Central, they use jcenter now.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
Make sure gradle wrapper generates the gradlew file and gradle/wrapper subdirectory. This is a big gotcha.
ndkDirectory
This has come up a number of times, but android.ndkDirectory is the correct way to get the folder after 1.1. Migrating Gradle Projects to version 1.0.0. If you're using an experimental or ancient version of the plugin your mileage may vary.
gradle supports ndk compilation by generating another Android.mk file with absolute paths to your sources.
NDK supports absolute paths since r9 on OSX, r9c on Windows, so you need to upgrade your NDK to r9+.
You may run into other troubles as NDK support by gradle is preliminary. If so you can deactivate the ndk compilation from gradle by setting:
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
to be able to call ndk-build yourself and integrate libs from libs/.
btw, you have any issue compiling for x86 ? I see you haven't included it in your APP_ABI.
In my case, I'm on Windows and following the answer by Cameron above only works if you use the full name of the ndk-build which is ndk-build.cmd. I have to clean and rebuild the project, then restart the emulator before getting the app to work (Actually I imported the sample HelloJni from NDK, into Android Studio). However, make sure the path to NDK does not contain space.
Finally, my build.gradle is full listed as below:
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.example.hellojni"
minSdkVersion 4
targetSdkVersion 4
ndk {
moduleName "hello-jni"
}
testApplicationId "com.example.hellojni.tests"
testInstrumentationRunner "android.test.InstrumentationTestRunner"
}
sourceSets.main {
jni.srcDirs = [] // This prevents the auto generation of Android.mk
// sourceSets.main.jni.srcDirs = []
jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project.
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
def ndkDir = android.plugin.ndkFolder
commandLine "$ndkDir/ndk-build.cmd",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'-j', Runtime.runtime.availableProcessors(),
'all',
'NDK_DEBUG=1'
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
def ndkDir = android.plugin.ndkFolder
commandLine "$ndkDir/ndk-build.cmd",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'clean'
}
clean.dependsOn 'cleanNative'
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
}
dependencies {
compile 'com.android.support:support-v4:21.0.3'
}
Android Studio 2.2 came out with the ability to use ndk-build and cMake. Though, we had to wait til 2.2.3 for the Application.mk support. I've tried it, it works...though, my variables aren't showing up in the debugger. I can still query them via command line though.
You need to do something like this:
externalNativeBuild{
ndkBuild{
path "Android.mk"
}
}
defaultConfig {
externalNativeBuild{
ndkBuild {
arguments "NDK_APPLICATION_MK:=Application.mk"
cFlags "-DTEST_C_FLAG1" "-DTEST_C_FLAG2"
cppFlags "-DTEST_CPP_FLAG2" "-DTEST_CPP_FLAG2"
abiFilters "armeabi-v7a", "armeabi"
}
}
}
See http://tools.android.com/tech-docs/external-c-builds
NB: The extra nesting of externalNativeBuild inside defaultConfig was a breaking change introduced with Android Studio 2.2 Preview 5 (July 8, 2016). See the release notes at the above link.
My issue on OSX it was gradle version. Gradle was ignoring my Android.mk.
So, in order to override this option, and use my make instead, I have entered this line:
sourceSets.main.jni.srcDirs = []
inside of the android tag in build.gradle.
I have wasted lot of time on this!
In the module build.gradle, in the task field, I get an error unless I use:
def ndkDir = plugins.getPlugin('com.android.application').sdkHandler.getNdkFolder()
I see people using
def ndkDir = android.plugin.ndkFolder
and
def ndkDir = plugins.getPlugin('com.android.library').sdkHandler.getNdkFolder()
but neither of those worked until I changed it to the plugin I was actually importing.