NDK compiling multiple libraries - android

I am using native code in my android app. Firstly I was only using one library. So everything worked fine. But now I have to integrate one more library into it. I've no idea what should be the ideal structure of the jni folder of my project (as in where to place the entire code, etc.). I found a work around. I created two folders inside jni .i.e library1 and library2. Again created a jni folder inside both the folders and placed respective code in the folders.
I got it to compile. Both .so files are being generated, but I am unable to use it in my application. I cant load the library using System.loadLibrary("library1.so"); Also tried providing full path. But failed
Also I have no idea what to write inside the parent jni folder's Android.mk file.
Current structure:
project_folder -> jni -> library1 -> jni -> "source code" an Android.mk is written here
project_folder -> jni -> library2 -> jni -> "source code" an Android.mk is written here
UPDATE #1 :
Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver
Gdbsetup : libs/armeabi/gdb.setup
make: *** No rule to make target `jni/zap/jni/zap/zap/error.c', needed by `obj/local/armeabi/objs-debug/zap/jni/zap/zap/error.o'. Stop.
I am not using Application.mk.
This is my Android.mk:
TOP_PATH := $(call my-dir)
# Build library 1
include $(CLEAR_VARS)
LOCAL_PATH := $(TOP_PATH)/zap
LOCAL_MODULE := zap
LOCAL_C_INCLUDES := $(LOCAL_PATH)/zap
LOCAL_SRC_FILES := $(LOCAL_PATH)/zap/error.c \
$(LOCAL_PATH)/zap/hello-jni.c \
$(LOCAL_PATH)/zap/zap.c \
$(LOCAL_PATH)/zap/zapd.c \
$(LOCAL_PATH)/zap/zaplib.c
include $(BUILD_SHARED_LIBRARY)

The best structure I've found is to use the jni/ folder for ndk-build makefiles only, and keep the source outside in their own folders. This is easy to add to existing projects without restructuring your tree under jni.
However, you do have to be careful about how you handle the LOCAL_PATH variable and use of $(call my-dir). Here's a working example:
MyProject/
library1/
source1.cpp
library2/
source2.cpp
jni/
Android.mk
Application.mk
Android.mk:
# TOP_PATH refers to the project root dir (MyProject)
TOP_PATH := $(call my-dir)/..
# Build library 1
include $(CLEAR_VARS)
LOCAL_PATH := $(TOP_PATH)/library1
LOCAL_MODULE := library1
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES := source1.cpp
include $(BUILD_SHARED_LIBRARY)
# Build library 2
include $(CLEAR_VARS)
LOCAL_PATH := $(TOP_PATH)/library2
LOCAL_MODULE := library2
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES := source2.cpp
include $(BUILD_SHARED_LIBRARY)
You can optionally split out the sections in Android.mk to their own makefiles.

I discovered that when compiling from the command line, I can include multiple libraries by running android update project twice, once with each library:
android update project -l ../SDK/library1/ --path . --name $name --target 23 --subprojects
android update project -l ../SDK/library2/ --path . --name $name --target 23 --subprojects
ant release

Related

How to include constraint layout library in an AOSP project

I have an existing android application that I'd like to build inside AOSP (android source tree) using Android.mk. The app uses constraint layout which is not included in AOSP source tree (AFAIK).
How can I satisfy this dependency? Other support libs are included such as recyclerview, v4 etc but not contraint layout.
Should I download the lib aar and if yes , how do I add/include it?
Or should I get the source (where to download?) and build it somewhere in the source tree?
Thanks in advance for any help.
There are several ways to resolve your issue.
1. Add a prebuilt .apk
You don't have to put your source code to the AOSP tree.
You can just add your .apk file, put it either in packages/apps/YourApp, or vendor/yourname/packages/apps/YourApp, or even your_dir_name/packages/apps/YourApp, and create an Android.mk file for build system to determine your application.
Android.mk will look like:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := YourApplication # your .apk name
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)
Pros: you can build your project with gradle.
2. Add source code to AOSP
If you still want to place your source code to packages/apps and build it there, you can put a ConstrainsLayout to your project's libs/ directory and add to your Android.mk something like:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# List of static libraries to include in the package
LOCAL_STATIC_JAVA_LIBRARIES := constraint-layout
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK
LOCAL_PACKAGE_NAME := YourApplication
# Tell it to build an APK
include $(BUILD_PACKAGE)
In case you will not get it work (I haven't met this issue, but he did):
LOCAL_STATIC_JAVA_LIBRARIES := libconstraint-layout
include $(BUILD_PACKAGE)
Other stuff, and finally
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libconstraint-layout:libs/constraint-layout.aar
Cons: You will have to build your code either with make by mma or mm -B, or to have a gradle as your second build system for development. The second option will work, but to establish a full build and to have your .apk built in out/ directory you will have to build it with make.
3. Adding a ConstraintLayout
In case you want to have several applications, which use a constraint layout, you can add it as a new library module as precompiled .aar.
Can be somewhere in 'vendor/yourname/libs' or 'your_dir_name/libs' respectively.
It is similar to adding a prebuilt .apk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := constraint-layout
LOCAL_SRC_FILES := $(LOCAL_MODULE).aar
LOCAL_MODULE_SUFFIX := .aar
include $(BUILD_PREBUILT)
After that, in your application's Android.mk you will have to add:
LOCAL_STATIC_JAVA_LIBRARIES := constraint-layout
Alternatively, you can add a ConstraintLayout's .aar to the prebuilds/ as it eventually will be there someday.
There is a good topic about Android.mk: https://wladimir-tm4pda.github.io/porting/build_cookbook.html
https://stackoverflow.com/a/46414919/9237859 is right, except LOCAL_STATIC_JAVA_AAR_LIBRARIES should be used instead of LOCAL_STATIC_JAVA_LIBRARIES, since constraint-layout is a aar file.
From Android 9.0, there is no need of adding .aar and .jar separately in the project for constraint-layout. We can use constraint-layout library built in to AOSP.
We need to add one extra line in Android.mk:
LOCAL_USE_AAPT2 := true
Then, we need to add:
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
--extra-packages android.support.constraint
LOCAL_STATIC_ANDROID_LIBRARIES += android-support-constraint-layout
LOCAL_STATIC_JAVA_LIBRARIES += android-support-constraint-layout-solver
For more detailed answer: How to use constraint-layout during AOSP build without including external .aar and .jar
This can be done as follows:
Download constraint-layout.aar and constraint-layout-solve.jar and put these files in lib folder.
Add the following to your Android.mk file
LOCAL_STATIC_JAVA_AAR_LIBRARIES += constraint-layout
LOCAL_STATIC_JAVA_LIBRARIES += constraint-layout-solver
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := constraint-layout:libs/constraint-layout.aar
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := constraint-layput-solver:libs/constraint-layout-solver.jar

How to generate a shared library temporary and pack it into a APK package

I have a android app called "ABC" which needs to pack a jni shared library called "libxxx-jni.so". So the source tree is likes as below:
ABC
+- Android.mk
+- java
+- res
+- jni
+- Android.mk
+- xxx.cpp
The Android.mk of ABC app is:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PACKAGE_NAME := ABC
LOCAL_SRC_FILES := $(call all-java-files-under, java)
LOCAL_RESOURCE_DIR += \
$(LOCAL_PATH)/res
LOCAL_JNI_SHARED_LIBRARIES := libxxx-jni
include $(BUILD_PACKAGE)
# Also build sub-targets under this one: the shared library.
include $(call all-makefiles-under, $(LOCAL_PATH))
And the Android.mk of jni library xxx is:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libxxx-jni
LOCAL_SRC_FILES := xxx.cpp
LOCAL_SHARED_LIBRARIES := \
libutils \
libcutils
LOCAL_LDLIBS += -llog
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
include $(BUILD_SHARED_LIBRARY)
I put these source code in android aosp source tree, and use android build environment to build whole system.
My problem is I need to pack the libxxx-jni.so into my Settings apk. Currently, after build completed, I see the libxxx-jni.so is located at /system/lib. In APK's lib sub-folder, I only see a link to the /system/lib/libxxx-jni.c.
That's not my expectation. I want to pack the so in my APK's lib sub-folder, not just a link. And I don't want to the libxxx-jni.so is appeared in /system/lib.
I didn't use IDE (eclipse or android studio), and I only use Android.mk in aosp source tree.
How should I modify these Android.mk to meet my expectation? Thanks.
Add this to Android.mk:
LOCAL_MODULE_TAGS := samples
There's several ways to achieve bundling of JNI .so's in the apk when using AOSP, basically all listed in the build system:
a) make TARGET_BUILD_APPS become true: one way to do this is by building your app via tapas instead of lunch: . build/envsetup.sh; lunch <yourlunchtarget>; m <yourapp> becomes . build/envsetup.sh; tapas <yourapp> [arm|x86|arm64|x86_64] [eng|userdebug|user]; make.
b) set LOCAL_COMPRESSED_MODULE to true.
c) set LOCAL_MODULE_TAGS to samples or tests as noted by huisinro. Not sure about the side effects and if your app is not a sample or a test this feels semantically wrong.

How to compile Cmake file with Android.mk?

I need to generate ARM structure shared library for a sampleCPP project.
Sample projects contains:
CMakeLists.txt
some.cpp (s)
Some.h (s)
some.tab.cpp.make (S)
some.tab.hpp.cmake (s)
Now, I want to create a shared library for a different Android project. I tried to compile with [Android-Cmake][1]but it is generating X86 Architecture library not ARM.
Please let me know if there is another way to do it. Also can i run X86 on Android Platform for all version?
Edit :
Here is my Android.mk:
LOCAL_PATH := $(call my-dir)/../ //Path is according JNI Folder
SRC_TOP_DIR := $(LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := smileParse
LOCAL_CFLAGS := -DANDROID
LOCAL_SRC_FILES := main.cpp test.cpp smamain.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include $(LOCAL_PATH)/
Create a folder called JNI in your project:
Create or Edit Android.mk in JNI folder, set include and library path,
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := some.cpp
include $(BUILD_SHARED_LIBRARY)
Declare a java wrapper class, declare a native function:
public class JWrapperSomeClass {
public native void Demo(int para);
}
use javah command to generate the function signature for your C++ method wrapper:
javah -jni -classpath bin/classes/ -d jni com.example.Your.Package.Class
Edit the code in C++
Go to your project folder, run command:
$ANDROID_NDK/ndk-build
where $ANDROID_NDK is the folder where you installed android NDK
That is pretty much it. For more details, you might read NDK or JNI documentation.

Fatal error, no such file or directory ( eclipse android )

I'm developing a cocos2d-x project, as its universal it works on android and iOS.
I recently added text to speech functionality using flite. In xcode all I do to use flite, is drag in the folder of the headers and c files into my xcode project, and then I can include its headers and use it. No problems there.
However in eclipse I can't get the compiler to see the files, and it keeps bombing out with the fatal error I mentioned. Specifically: fatal error: flite.h no such file or directory.
I've tried to include the folder in the includes section of eclipse under C/C++ general but no luck. I think this may have something to do with my android.mk file, guidance on how to set this up for this purpose would be greatly appreciated. On a side note, my project is set up so that my .cpp and .h files exist elsewhere on my computer and not in my actual project. Likewise for my flite source files. (I did try add them to my project however, out of desperation but the compiler still couldn't find them)
Thanks for your time.
PS: How does one refer to flite, is it a library/framework etc?
Edit
I tried to modify my Android.mk file, to locate the flite headers. My additions are indicated below
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := game_shared
LOCAL_MODULE_FILENAME := libgame
LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp \
../../Classes/CCLabelTTFExtension.cpp \
../../Classes/menuScene.cpp \
../../Classes/text_Parse.cpp \
../../Classes/FileTS.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes/
#my addition
LOCAL_C_INCLUDES += $(LOCAL_PATH)/flite/
dirs := $(shell /flite -type d)
cfilestemp1 := $(shell find /src -type d)
cfilestemp2 := $(shell find $(cfilestemp1) -name *.c)
cfilestemp3 := $(sort $(cfilestemp2))
cfiles := $(subst $(LOCAL_PATH)/,,$(cfilestemp3))
LOCAL_SRC_FILES += \
$(cfiles)
#end my addition
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static cocosdenshion_static cocos_extension_static
include $(BUILD_SHARED_LIBRARY)
$(call import-module,CocosDenshion/android) \
$(call import-module,cocos2dx) \
$(call import-module,extensions)
include $(CLEAR_VARS)
This got me closer, well, gave me different errors. Now the compiler complains of undefined references in my FileTS.cpp file, the file which is using flite in my project. (Note: My flite headers and source files are now added to my project in the jni folder)
The easiest way is to put all the source code into your Classes folder and list the cpp files in LOCAL_SRC_FILES like mainScene.cpp . this will make sure your library get build into your game object files.

Loading shared libs using Android.mk

How can I specify shared libraries to load in the Android.mk when compiling with ndk-build ?
Edit: This is my Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := lib-crypto
LOCAL_SRC_FILES := libcrypto.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := tema1
LOCAL_SRC_FILES := tema1.c
LOCAL_SHARED_LIBRARIES := lib-crypto
LOCAL_C_INCLUDES := /home/aleksei/openSSL0.9.8/include
include $(BUILD_EXECUTABLE)
libcrypto.so is the library that I have built for android. I want to make a program using it. Now it gives me this error:
Install : libcrypto.so => libs/armeabi/libcrypto.so
Executable : tema1
./obj/local/armeabi/libcrypto.so: undefined reference to `dladdr'
collect2: ld returned 1 exit status
make: *** [obj/local/armeabi/tema1] Error 1
PREBUILT_SHARED_LIBRARY
Points to a build script used to specify a prebuilt shared library.
Unlike BUILD_SHARED_LIBRARY and BUILD_STATIC_LIBRARY, the value
of LOCAL_SRC_FILES must be a single path to a prebuilt shared
library (e.g. foo/libfoo.so), instead of a source file.
You can reference the prebuilt library in another module using
the LOCAL_PREBUILTS variable (see docs/PREBUILTS.html for more
information).
read more from http://source-android.frandroid.com/ndk/docs/ANDROID-MK.html
Show me what you have done till yet and where you facing problem.?
I had the same problem. To fix it, I did the following:
In the same directory as your Android.mk file, create a file named Application.mk
Add the following line of code into Application.mk:
"APP_PLATFORM := android-8"
If you already have an Application.mk file, just add the code in step 2 to the existing file. Now call ndk-build and see if it links. ndk-build may be compiling with an old version of libdl which does not have dladdr(). The code in step 2 will cause ndk-build to use an updated libdl which has dladdr().

Categories

Resources