Building cross platform sources with android.mk in NDK - android

I need to build some cross platform cpp files in my android mk file. These sources are not in sub directories of the jni directory.
Currently i have something like below, is there some way to avoid the long relative paths to describe where the source files are located? What is best practice here?
Thanks
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := host
LOCAL_SRC_FILES := ../../../../../Dev/common/host.c
include $(BUILD_STATIC_LIBRARY)

You can define your own variables in mk file:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
SRC_ROOT := ../../../../../Dev
LOCAL_MODULE := host
LOCAL_SRC_FILES := $(SRC_ROOT)/common/host.c
include $(BUILD_STATIC_LIBRARY)

Related

$(LOCAL_PATH) not returning the path to current directory correctly

I am using Android NDK to compile a shared library. I am using the latest build of Android Studio (Android Studio 15- #AI-141.2422023 ). In my cpp code, I am using a thirdparty shared library. When writing the Android.mk file, I have first created a PREBUILT_SHARED_LIBRARY with the following code.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := essentia
LOCAL_SRC_FILES := $(LOCAL_PATH)/../../../essentia-shared/lib/libessentia.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../essentia-shared/include/essentia
include $(PREBUILT_SHARED_LIBRARY)
The problem I am facing is that $(LOCAL_PATH) is behaving a bit weirdly. The path it is returning is
jni/jni/../../../essentia-shared/lib/libessentia.so
I have the following questions:
I am not sure, why there are two jni's appended at the front of the path. Also when I tried to print the value of LOCAL_PATH by using $(warning $(LOCAL_PATH)), it prints jni.
Shouldn't $(LOCAL_PATH) return the absolute path? This is even more confusing because at times I got the absolute path using $(LOCAL_PATH).
PS: I am using the terminal internal to Android Studio to run ndk-build
Edit 1: I run the ndk-build from src/main
$(call my-dir) from src/main for src/main/jni/Android.mk results in "jni". On the other hand, LOCAL_SRC_FILES are always treated relative to the LOCAL_PATH, which is "jni". That's how jni/jni appears for your .so.
On the other hand, all …_INCLUDES are treated relative to working directory, which in your case is src/main from where you launched ndk-build. Due to the delicate nature of current directory, it is a good practice to use absolute paths for all include paths.
So, this is the suggested rewrite of this part of your Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := app-lib
LOCAL_SRC_FILES := a.cpp b.cpp
LOCAL_SHARED_LIBRARIES := essentia
include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH += /../../../essentia-shared
include $(CLEAR_VARS)
LOCAL_MODULE := essentia
LOCAL_SRC_FILES := lib/libessentia.so
LOCAL_EXPORT_C_INCLUDES := $(abspath $(LOCAL_PATH)/include/essentia)
include $(PREBUILT_SHARED_LIBRARY)

Prebuilding different kind of static library in Android NDK

Is there any way that we can build different kind of static libraries (.a extension files) at once, that we created through our NDK ? I think you'll understand better when i shared the code.
Android.mk ->
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libzlib
LOCAL_SRC_FILES := libzlib.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libpng
LOCAL_SRC_FILES := libpng.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := callNDK
LOCAL_SRC_FILES := callNDK.c
LOCAL_STATIC_LIBRARIES := libpng libzlib
include $(BUILD_SHARED_LIBRARY)
The static libraries that I include, I copied from the /obj folder that I created with the BUILD_STATIC_LIBRARY. How can I prebuilt them all at once and include them ? Sorry for the bad English and thanks in advance !
I was able to find the answer with the variable, TARGET_ARCH_ABI. Adding LOCAL_SRC_FILES := ..\obj\local\$(TARGET_ARCH_ABI)\libzlib.a line on each prebuilt library fixed the problem. Basiclly, it chooses the appropriate library on each compile & install.

How do I make ndk-build create executable named like a library?

I want my native executable to be auto-populated to /data/data/.../lib/. For this it is to be named like lib*.so. But if I try to set this name, Android NDK complains:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libhello.so
LOCAL_SRC_FILES := hello.c
include $(BUILD_EXECUTABLE)
Android NDK: jni/Android.mk:hello.so: LOCAL_MODULE_FILENAME must not contain a file extension
A workaround: install with a name Android NDK wants, then rename after installation:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.c
include $(BUILD_EXECUTABLE)
all:
mv ${NDK_APP_DST_DIR}/hello ${NDK_APP_DST_DIR}/libhello.so
And your application can call the executable /data/data/<package>/lib/libhello.so without any preparatory steps.
You are trying to build an executable instead of a shared library. You want to change this:
include $(BUILD_EXECUTABLE)
to this:
include $(BUILD_SHARED_LIBRARY)

How to use ndk-build build the source files in different folders?

I know that to build so file, I should put the source file in /jni/ folder.
But how can I build separate so in different folders.
For example, the structure of my project:
/jni/Android.mk
/jni/submodule1/Android.mk
/jni/submodule1/sub1.c
/jni/submodule2/Android.mk
/jni/submodule2/sub2.c
I have tried to write this in Android.mk in the top level:
$(LOCAL_PATH) :=$(call all-makefiles-under)
then wrote make info in Android.mk in submodule
the error is:
ndk-build
make: *** No rule to make target `/home/../workspace/jni/sub.c', needed b
y `/home/../workspace/obj/local/armeabi/objs/submodule/sub.o'. Stop.
Can someone give me a solution? Thank you!
Update 1:
The code of Android.mk in submoudle:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := sub.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_MODULE := sub
LOCAL_LDLIBS := -ldl -llog
LOCAL_STATIC_LIBRARIES := libc
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := debug
include $(BUILD_EXECUTABLE)
SOLVED:
I should use ndk-build in the root directory, but not in jni directory. Thanks all of you!
You should try include $(call all-subdir-makefiles) rather then $(LOCAL_PATH) :=$(call all-makefiles-under) in main Android.mk and make folder under jni folder with there separate c files and Android.mk files
Have you tried something like:
LOCAL_PATH := $(call my-dir)
LOCAL_SRC_FILES := /submodule1/sub1.c

Linking dependent .so files with ndk-build for Android

I have created a .so file that exposes a native C call to Java via JNI. This works well and I can deploy the app onto my Android system if I just use system libraries in my C code. However, if I want to make calls to functions in other .so files, I cannot get my project to link correctly.
For example, say I have the "libotherso.so" file which contains APIs defined in C that I can call from the "MyJNILibrary.c" code I'm using to generate "libMyJNILibrary.so".
I tried to change my Android.mk file as follows:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyJNILibrary
LOCAL_SRC_FILES := MyJNILibrary.c
LOCAL_LDLIBS += -lotherso
include $(BUILD_SHARED_LIBRARY)
But when I call ndk-build on this, I get errors finding -lotherso. Where do I put the "libotherso.so" file so that ndk-build can pick it up?
Thanks for any help you can provide.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := otherso
LOCAL_SRC_FILES := ../lib/libotherso.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := MyJNILibrary
LOCAL_SRC_FILES := MyJNILibrary.c
LOCAL_SHARED_LIBRARIES := otherso
include $(BUILD_SHARED_LIBRARY)
Note that LOCAL_SRC_FILES is relative to your LOCAL_PATH.
Don't forget to load your dependency before your own JNI library:
static {
System.loadLibrary("otherso");
System.loadLibrary("MyJNILibrary");
}

Categories

Resources