Reputation: 4323
I've to add the native files .so, .mk, .sh, .cpp in my Project in Android Studio. In eclipse .so files are added in libs folder and other files in jni and obj folder and all working fine. But in Android studio As I've added .so files in jniLibs folder and made changes in .gradle file as below
ndk{
abiFilters 'armeabi', 'armeabi-v7a', 'x86'
}
sourceSets.main {
jniLibs.srcDir 'src/main/libs' //set libs as .so's location instead of jniLibs
jni.srcDirs = [] //disable automatic ndk-build call with auto-generated Android.mk
}
Below is the structure of my project and the files I need to add. There are jni and obj folder that contain the native code and I've to use that.
I've seen the links available but they are outdated and nothing worked. Any help is appreciated.
Log after after doing the below changes:
sourceSets.main {
jniLibs.srcDir 'src/main/libs' //set libs as .so's location instead of jniLibs
jni.srcDirs = [] //disable automatic ndk-build call with auto-generated Android.mk
}
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
Log:
Error while executing 'E:\Android_SDK\ndk-bundle\ndk-build.cmd' with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=E:\folder\sampleapp\app\src\main\jni\Android.mk NDK_APPLICATION_MK=E:\folder\sampleapp\app\src\main\jni\Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=1 APP_PLATFORM=android-16 NDK_OUT=E:/folder/app/build/intermediates/ndkBuild/debug/obj NDK_LIBS_OUT=E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n}
md "E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib\armeabi-v7a" >NUL 2>NUL || rem
copy /b/y "E:\Android_SDK\ndk-bundle\build\\..\prebuilt\android-arm\gdbserver\gdbserver" "E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib\armeabi-v7a\gdbserver" > NUL
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe [armeabi-v7a] "Gdbserver ": "[arm-linux-androideabi] E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdbserver"
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe [armeabi-v7a] "Gdbsetup ": "E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdb.setup"
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe "directory E:/Android_SDK/ndk-bundle/build//../platforms/android-16/arch-arm/usr/include E:/folder/app/src/main/jni E:/Android_SDK/ndk-bundle/build//../sources/cxx-stl/system" >> E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdb.setup
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe "set solib-search-path E:/folder/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a" > E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdb.setup
process_begin: CreateProcess(NULL, "", ...) failed.
make: *** No rule to make target `E:/folder/app/src/main/jni/SerialPort.c', needed by `E:/folder/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs-debug/serial_port/SerialPort.o'. Stop.
Build command failed.
Error:executing external native build for ndkBuild E:\folder\sampleapp\app\src\main\jni\Android.mk
Build command failed.
Error while executing 'E:\Android_SDK\ndk-bundle\ndk-build.cmd' with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=E:\folder\sampleapp\app\src\main\jni\Android.mk NDK_APPLICATION_MK=E:\folder\sampleapp\app\src\main\jni\Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=0 APP_PLATFORM=android-16 NDK_OUT=E:/folder/app/build/intermediates/ndkBuild/release/obj NDK_LIBS_OUT=E:\folder\sampleapp\app\build\intermediates\ndkBuild\release\lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n}
make: *** No rule to make target `E:/folder/app/src/main/jni/SerialPort.c', needed by `E:/folder/app/build/intermediates/ndkBuild/release/obj/local/armeabi-v7a/objs/serial_port/SerialPort.o'. Stop.
process_begin: CreateProcess(NULL, "", ...) failed.
Error:executing external native build for ndkBuild E:\folder\sampleapp\app\src\main\jni\Android.mk
Upvotes: 12
Views: 10652
Reputation: 645
For native development, you should have main/jni folder which is you should put your libraries and native sources inside it and build them in this folder. Before you should create two files, Android.mk and Application.mk. Android.mk is for building native libs (modules), adding flags and etc. You can build static and shared libraries in Android.mk. When you build your C sources, it creates static library (.a). But these libraries not for using in Java side. You can only use them for creating shared libraries (.so). For this, you should build your C++ sources, and if you want, you can add your static libraries to this.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
ifneq (,$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86 arm64-v8a x86_64))
LOCAL_MODULE := myLibrary
LOCAL_SHARED_LIBRARIES := cpufeatures opencv_imgproc opencv_core
LOCAL_C_INCLUDES := $(LOCAL_PATH)/c-files
LOCAL_SRC_FILES := $(LOCAL_PATH)/myJni.cpp
include $(BUILD_SHARED_LIBRARY)
--- 1st line returns main/jni path.
--- 2nd line clear all old LOCAL_*** variables.
--- 3th line build modules for each arch's which are declared there.
--- 4th line shows module name, when you build it, NDK automatically add lib and .so extensions to it (libmyLibrary.so).
--- 5th line adds other shared libraries, which you need their sources in your native sources.
--- 6th line adds C files to your module.
--- 7th line shows your C++ sources which you try to build.
--- 8th line is building command.
In Application.mk you can give commands something like, your project in release mode or debug mode. And you should give arch's in this file. For example APP_ABI := armeabi-v7a x86 arm64-v8a x86_64
and etc.
When you try to build libraries and use them in java side, you should do some operations.
1.Check your ndk path in local.properties file in project folder. It shows ndk-bundle path for building makefiles.
ndk.dir=/Users/../Library/Android/sdk/ndk-bundle
2.Check build scripts in gradle file. This script shows where shared libs should be located:
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
3.And show your makefile path to gradle.
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
I think my answer will help you for understanding some details. For addition, you can take a look these answers also.
Upvotes: 3
Reputation: 178
I think I've reproduced the error in Android Studio using a simple JNI project. The thing that triggered this specific error ("make: *** No target...") for me was having an incorrect path to one of the source files in Android.mk. (If the paths are correct, the build should succeed; if you leave a source file out completely, you'll get a linker error.) For example, if I specify an incorrect path to one of my sources, this error happens:
make: *** No rule to make target `/Users/afarm/AndroidStudioProjects/Mktest/app/src/main/cp/stringdep.cpp', needed by `/Users/afarm/AndroidStudioProjects/Mktest/app/build/intermediates/ndkBuild/debug/obj/local/armeabi/objs-debug/native-lib/src/main/cp/stringdep.o'. Stop.
which looks like the error you described above. Android.mk is not finding your SerialPort.c, so I would guess the path to SerialPort.c stored Android.mk is incorrect. Keep in mind that the paths stored in Android.mk are relative to the Android.mk file itself, not to the root directory.
Upvotes: 2
Reputation: 5788
First of all, make sure your source location, suites example. You have some issues. All native files should be in src/main/
../src/main
.........../jni # your cpp, header and mk files
.........../jniLibs # your folders with all libs
.........../java # other code
Then, make sure, you load your libs in static field before any Native usage, in Activity, Application, etc.
private static final String LIB_NAME = "libserial_port";
private static final String LIB_NAME_1 = "libzqcom";
static {
System.loadLibrary(LIB_NAME);
System.loadLibrary(LIB_NAME_1);
}
UPD 1:
Make sure you already installed Android NDK Source for Native Android project.
Upvotes: 9
Reputation: 178
Adding on to GensaGames' answer, if you have a .mk file you are using to build the native libraries, in order to add it to the build process you must specify the path to that file in the module-level build.gradle file, in the android{ } block:
externalNativeBuild {
ndkBuild {
path 'path/to/Android.mk'
}
}
As a note, the directory structure suggested by GensaGames isn't strictly necessary for Android Studio - you can put your .mk and .cpp files anywhere you like as long as you specify their directory in build.gradle or Android.mk.
Upvotes: 4