I use some prebuilded so in the prebuild directory of an Android JNI project. The Android mk file for the prebuild libs are like this:
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuild
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
But each time when I run ndk-build -B, the so files generated in libs/armeabi changed. So I realized that ndk-build modified the so files rather than simplely copied them. This is annoying when I have to manage these so files with version control software like git, since it is hard to kown if the comitted version is consistent with the so in the prebuild directory. Can I keep them the same?
To check what exactly NDK does on your binary - run it with verbose output: ndk-build V=1. This will print all commands, that NDK does under the hood. Probably it strips debug info, non-exported entries in symbol table with strip.
Related
I'm trying to compile a native lib using ndk tools outside of any project.
I am using the following at the terminal:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_PLATFORM=android-9 V=1
I also have at the same directory of Android.mk an Application.mk
APP_BUILD_SCRIPT := $(call my-dir)/Android.mk
NDK_PROJECT_PATH := $(call my-dir)
APP_PLATFORM := android-9
APP_ABI := armeabi-v7a
I would like to use instead of passing those flags from the command line. The build system is ignoring my Application.mk though. What am I doing wrong? Or else might what I'm trying to do (compiling a library from outside of an app project) not be possible.
Compiling a library from outside of an application project is possible.
You just missed setting NDK_APPLICATION_MK to your Application.mk file.
ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk APP_BUILD_SCRIPT=Android.mk
A simpler way to do that is to put the make files(Android.mk, Application.mk) in a folder named jni/ that what the build system expects to find them. And you will just call ndk-build on the project root folder to build your library.
I'm currently implementing a custom Logging mechanism that I need to be accessible from both native and Java code. The fundamentals of the logging are implemented in C/C++ with a Java wrapper, and the two together are being built as an android Library Project.
The issue at hand is that while my Java code can access the Library project output, there doesn't seem to be a way for my native code to access the native .so or headers from the Library project. Is there an additional step I'm missing or is this just a limitation of the current ADT? More specifically, is there a makefile/eclipse configuration that will address the things I'm used to getting out of Library projects in general? (Build .so as needed, import rebuilt .so, import relevant headers for c/c++ compilation, etc.)
I don't think it's a limitation. We are supposed to declare native code dependencies in Android.mk and Application.mk
Worked out a way to get what I wanted - most of the information is (of course) in the NDK documentation, but what I was trying to do isn't 100% supported within the ADT. It should also be noted that I'm currently stuck developing in a windows environment, so much of this might be easier or unnecessary in Linux. The first key is the $(call import-module ...) macro. Within your library project, move the source files and the Android.mk folder into a named directory you can locate later. My Library project directory looked like this:
MyProject
> src
> res
v jni
- Application.mk
v MyLib
- source.cpp
- source.h
- Android.mk
I also had to edit my Application.mk to point to the project:
APP_PROJECT_PATH := <path-to-my-project>
APP_BUILD_SCRIPT := $(APP_PROJECT_PATH)/jni/MyProject/Android.mk
Annoyingly, this broke my Android.mk in ways unforseen until I added a ./ to my source files. Also you need to export your includes for linking:
LOCAL_SRC_FILES := ./source.cpp
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
Ensure that the system path variable NDK_MODULE_PATH is set to include your library's JNI directory, e.g. <path-to-my-project>/jni (Note: I had to restart eclipse after I did this).
In the receiving application's Android.mk file (the one you'd like to link natively to your app), import the module:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyNativeProject
LOCAL_SRC_FILES := source.cpp
LOCAL_CFLAGS := -DANDROID_NDK -g -std=c99
LOCAL_SHARED_LIBRARIES := MyLib
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
$(call import-module, IntelLog)
At this point everything built perfectly, but the APK packager didn't like the generated .so binary being included twice (once from the Library project's natural import process, and again from the import-module call). To solve this, clean the library and don't build it again! the import-module call will build the .so and import it into your project. (Obviously, if your project only requires the Java API, you would need that .so file to be built). Congratulations! you have a functional (if not straightforward) build process with a hybrid native/Java Library
I have an android application which uses jni and I'm trying to automate build process in Eclipse (using cdt plugin). I need to build my own static library, and I also need to use some precompiled libraries.
That means that I need to
a) build my own shared library (no problems here)
b) after build is complete, copy existing libraries into libs/armeabi folder (because this folder will be cleared during build process I must copy those files after every build)
I have some problems with b). What I'm trying to do is I'm inserting custom shell script (which works when executed as-is) after include $(BUILD_SHARED_LIBRARY) in Android.mk file. Unfortunately, this doesn't work, because apparently /libs/armeabi folder gets cleared only after Android.mk file is complete.
Is that true? Is there a way to insert post-build script into Android.mk? Is there any way I can execute bash script after jni code finished building but before whole build is complete (e.g. before java part is build and application starts executing?)? I though there must be some kind of "post-build" script in eclipse c/c++ project build settings, but there is no such thing.
Here's the complete Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_MODULE := player
LOCAL_SRC_FILES := player.c
include $(BUILD_SHARED_LIBRARY)
$(shell ./copy-libs.sh) #this script will get called, but the files will be erased right after
Well, it looks like there is an easier way to copy .so and .a libs without resorting to custom build scripts.
NDK supports prebuilt modules starting from ndk-r5, and they allow to copy .a or .so libraries into obj/lib folder during build process as needed.
Example and complete description are available in PREBUILTS.html file inside $NDK_INSTALLATION_FOLDER/docs/.
This question seems to have been asked a lot but all were trying to use eclipse to package the library inside the APK.
However, my requirement is to package the library inside the APK (which will later be loaded using System.loadLibrary() through Java) using the Android build system, i.e. i want to write an Android.mk file that does this job.
Requirement:
1. Prebuilt shared library: libTest.so
2. Write an Android.mk file that will package this to libs/armeabi-7 inside the apk.
I don't know much about the build system I am using but the compilation is done using "mm" command after exporting the required environment variables.
When I provide libTest for LOCAL_JNI_SHARED_LIBRARIES, it tries to find it inside its exported paths and fails to find it there and hence build fails.
Can anyone please give any pointers on writing an Android.mk file that will package my prebuild shared library into the APK?
In order to prebuild your native library you have to
Create jni folder in your project folder
Create libs folder in your project folder
Add Adnroid.mk make file to the jni folder, it should looks like
this:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := Test
LOCAL_SRC_FILES := Test.cpp
include $(BUILD_SHARED_LIBRARY)
Note 1: Test.cpp is the main library source file containing implementation of native methods. You can add more sources as a space separated list.
Note 2: Do not include headers, they are included automatically.
Note 3: If you need to enable C++ STL, then create another make file - Application.mk, add it to the jni folder and set APP_STL := stlport_static flag in it.
Then you will have to set up a builder. Refer to this article for how to do that:
After these steps, the builder will create your library in the libs folder which will be automatically packed into the apk when building the whole application.
Note: Your library name should be lowercase, it is a Linux convention. The "lib" prefix will be automatically added, so the final library name will be libtest.so.
Let's say there is one libxxx.so shared library under libs/armeabi/ of project which you want to pack into apk. There are 2 things you need to do in the Android.mk as below:
# 1. Copy .so to out/target/product/***/obj/lib
$(shell cp $(wildcard $(LOCAL_PATH)/libs/armeabi/*.so $(TARGET_OUT_INTERMEDIATE_LIBRARIES))
# 2. Make libxxx to be packed into apk
LOCAL_JNI_SHARED_LIBRARIES := libs/libxxxx
Then you can use apktool to unpack the built apk, you will find the libxxx.so will be located in libs/armeabi*/. It is indeed packed into the apk.
I had two LOCAL_JNI_SHARED_LIBRARIES that I wanted to build into my APK. I manage to do it by setting the following in my Android.mk:
LOCAL_MODULE_TAGS := samples
After re-compiling the module I was able to find both libraries inside the .apk under /lib/.
I'm trying to build a third party library which uses auto-generated
source code files.
In normal case, this kind of files is generated by gnu build tools.
My question is How can I tell the Android NDK build tools to generate and build this kind
of files.
Thanks in advance
The ndk-build tool is a thin wrapper script that calls GNU Make with some command line arguments. You can add any build rules to your Android.mk file that you like written in make, including generating source files.
If you have the generated file name in the LOCAL_SRC_FILES variable together with the rule to generate this file, make will figure it out. This is a minimal example Android.mk that copies "generated.in" to "generated.c" and then compiles it:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ndkexample
LOCAL_SRC_FILES := generated.c
$(LOCAL_PATH)/generated.c : $(LOCAL_PATH)/generated.in
echo "Generate file"
cp $< $#