I have implemented a JNI android application. This application requires a few additional 'Shared Libs' to be packed as part of the APK. Using Ecplise, I have added these libs to the project's '/libs/armeabi' folder.
However, when launching the application (through the integrated debugger), my added 'Shared Libs' are removed from the 'armeabi' folder.
How can I prevent these additional libs from being removed?
How can I make sure the additional required SOs are packed in the APK?
You don't need to copy this libraries to libs folder yourself. This job should be done by the ndk-build.
These two steps should be enough:
Create mylibs (you can use any other name instead) folder on the root level of your project. And put your libraries into this folder.
For each library add the following lines before the include $(CLEAR_VARS) statement replacing mylib with you library name:
include $(CLEAR_VARS)
LOCAL_MODULE:=mylib
LOCAL_SRC_FILES:=../mylibs/libmylib.so
include $(PREBUILT_SHARED_LIBRARY)
(You might need slightly different path for LOCAL_SRC_FILES. It depends on your Eclipse configuration.)
One more note to add in this context is that the path to the external SharedLib MUST BE relative to the jni directory ( or to whatever spcified # LOCAL_PATH ), that is, "LOCAL_SRC_FILES := ../../../Android/ffmpeg/libavcodec/libavcodec.so" will work where the absolute path will not.
Related
I am trying to create an Android Studio wrapper around C code and am running into a problem with the NDK. Because the C code is from a 3rd party project, I am trying to not move the code location and have the project in a subdirectory of the repository and as such have to not use the build in call to the NDK and its autogenerated make file. The NDK call works correctly, but I get the following error:
make.exe: *** No rule to make target `C:/some_relative_path/jni/../../../../core.c', needed by `C:/some_relative_path/obj/local/armeabi/objs/my_module/C_/some_relative_path/jni/__/__/__/__/core.o'. Stop.
As you can see, the object path has been mangled such that : and .. have been turned into underscores.
I had to add a jni folder to my project and place the Android.mk and Application.mk files in it to satisfy the path appending of the NDK Gradle plugin. As a result the jni folder had no source files in it. Since I found several links on google talking about needing more than one source file, I added two dummy source files to the jni directory.
Among other things, my Android.mk file contains the following:
LOCAL_SRC_FILES := \
$(LOCAL_PATH)/NDKBug1.c \
$(LOCAL_PATH)/NDKBug2.c \
$(LOCAL_PATH)/../../../../core.c \
I'm looking to see if anyone can help me with either this path issue directly, or perhaps suggest an alternative way of setting things up.
The file names in LOCAL_SRC_FILES are supposed to be relative to the local directory, so you need to remove the $(LOCAL_PATH)/ prefix - then it should work.
I haven't heard about a bug requiring to have source files in the local dir though, so I think you can get rid of them.
I configure ndk with eclipse in order to build my c++ code automatically. But i have two external .so file inside libs folder. Everytime, eclipse will delete these external .so file automatically when build project. Is it possible to tell eclipse not delete these external file.
The solution is here.
To summarize (and complement):
Copy your external (e.g., libexternal.so) library (or libraries) to another folder inside your 'jni' folder; for example 'myproject/jni/prebuilt'.
Add the following block to your existing 'jni/Android.mk' (one block for each external library):
include $(CLEAR_VARS)
LOCAL_MODULE := libexternal
LOCAL_SRC_FILES := prebuilt/libexternal.so
include $(PREBUILT_SHARED_LIBRARY)
Add 'libexternal' to 'APP_MODULES' in your existing 'jni/Application.mk'. 'APP_MODULES' should already list your JNI module (e.g., 'myjnimodule'):
APP_MODULES := libexternal myjnimodule
Confirm that the following block exists in 'jni/Application.mk'. Use the appropriate target architecture(s):
APP_ABI := armeabi-v7a
The result is that, as part of the invocation to 'ndk-build', the external library is copied to your 'myproject/libs/armeabi-v7a' folder.
The solution given by John Doedoe led me to another possibility, specific to Eclipse (tested on Mars 1 version):
Right click on your project in the project explorer.
Go into properties.
Go into "C/C++ Build".
Go into the "Builder Settings" tab.
Uncheck "Use default build command".
In the "Build command" text box type your target, e.g.: ndk-build APP_ABI="armeabi-v7a"
Apply / Ok
This will avoid changing behavior on a build machine for instance.
I'm completely new to Java and Android dev but I'm trying to port a C/C++ project to an android phone just to do some testing. Here are some details. The project depends on the Openssl, GMP, and NTL libraries. I downloaded copies and put everything inside a the jni/ folder. So now the folder structure looks like this:
jni/
Android.mk
gmp/
Android.mk
...
ntl/
Android.mk
...
openssl/
Android.mk
...
myproject/
Android.mk
...
Every one of the subfolders that has .cpp, c. files has an Android.mk file. Now, my question is: very broadly, how should I go about structuring the contents of the Android.mk files? I was able to follow instructions online and compile Openssl (I produced all the .so files inside of it). How will the top-level Android.mk use these? Or does it now?
When we run ndk-build in the top directory of your project (the parent of the jni directory in your picture), we essentially run gnu make and include jni/Android.mk.
In your case, this top jni/Android.mk should only include all child .mk files:
include $(call all-subdir-makefiles)
The main file is jni/myproject/Android.mk, which refers to the binaries produced by others, like
LOCAL_SHARED_LIBRARIES += openssl
and so on. Note that the names are not the names of library files, but of the LOCAL_MODULE's that build them.
Often, it is easier to use static libraries. For example, you need to load all shared libraries from Java yourself, in the correct dependencies order.
main is an informal word here. I just want to say that this is the make file that causes its siblings to do their work, and do it in expected order. It does that because it refers to the binaries produced by the other make files, by specifying LOCAL_SHARD_LIBRARIES and LOCAL_STATIC_LIBRARIES.
It is important to understand that it is not enough to include all the make files in jni/Android.mk to cause them all do their work, and do it in expected order. I want to emphasize that the jni/Android.mk file is a service file, not the main, even though it sits on top of the directory hierarchy.
I am writing a make file for compiling jni code in Android.
I would like to be able to compile all cpp files that reside under specific folder, recursively.
How can i do that?
I tried playing with the wildcard command, but did not get to the result i need.
The Android make system has a gmake macro for handling this. Please see the documentation doc\ANDROID-MK.html in the NDK. Here is an extract:
all-subdir-makefiles
Returns a list of Android.mk located in all sub-directories of
the current 'my-dir' path. For example, consider the following
hierarchy:
sources/foo/Android.mk
sources/foo/lib1/Android.mk
sources/foo/lib2/Android.mk
If sources/foo/Android.mk contains the single line:
include $(call all-subdir-makefiles)
Then it will include automatically sources/foo/lib1/Android.mk and
sources/foo/lib2/Android.mk
This function can be used to provide deep-nested source directory
hierarchies to the build system. Note that by default, the NDK
will only look for files in sources/*/Android.mk
I have used ndk successfully to build & use a .so file in one project. I need to use this library in another project. I would rather not copy the source there, but just use the library.
Trying to copy & paste the whole libs/armeabi/libcommon.so to the project root does not work, I think because libs/armeabi is an android generated path.
So what would be the best way to do it?
I am using Eclipse-Galileo & ndk5.
There is a much simpler way to do all of this.
Let's say that your prebuilt library is called "libprebuilt.so"
In the project folder of the new project you want to only include the prebuilt library, do something like:
mkdir -p jni/libprebuilt
cp libprebuilt.so jni/libprebuilt
Then, just create a jni/libprebuilt/Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libprebuilt
LOCAL_SRC_FILES := libprebuilt.so
include $(PREBUILT_SHARED_LIBRARY)
Then when you do ndk-build, it will copy this library in to libs/armeabi/ ... that's all!
I figured out a way to do this, so posting it here in case someone else runs into it.
The code to be shared (including the Java JNI wrapper, native code, .so library), should be in a separate project. Convert this to a Library project by right-click on project name --> properties --> Android properties --> check mark "Is Library". This project cannot be executed now but can be referenced by other projects.
In the project which will use the shared object, add a reference to the Libarray project by right-click on project name --> properties --> Android properties --> Library/"Add". This should show up the Library project created in the previous step. Select it.
Now the .so can be referred to easily between different projects.
There is a package name inside all JNI (Java Native Interface) functions names (like JNIEXPORT void JNICALL Java_com_myapp_myclass_funct). So i guess you should rename these funkcions in library a recompile it. Or maybe use it as external package in your app.