Linking Android C-code and ARM Assembler - android

I have written an Android app. It uses a main C-code module and a linked-in C-code module. Now I want to replace the linked-in module with an ARM assembler module. Anyone have a simple example?

Here's an example of Android.mk file that will build sourcetree containing assembly. To see a complete example check the hello-neon sample distributed in the NDK package.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm # remove this if you want thumb mode
LOCAL_ARM_NEON := true # remove this if you want armv5 mode
LOCAL_CFLAGS := -std=c99 -pedantic -v
LOCAL_SRC_FILES := # list your C, C++ and assembly sources here.
# assembly source files ends with extension .S
# add .arm after the extension if you want to compile in armv5 mode (default is thumb)
# add .arm.neon to compile in armv7 mode
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := #the name of your shared library
include $(BUILD_SHARED_LIBRARY)

I wrote a tutorial to do exactly this.
http://www.eggwall.com/2011/09/android-arm-assembly-calling-assembly.html
ARM assembly in Android isn't difficult, but there are many moving pieces: you need an assembly source, a C stub, a Makefile, and Java stub "native" methods that call the underlying assembly code.
You could download the source code from the link above, and see how it works. Once you have one working example, it is easy to poke and make it fit your need.

I Saw the article by vikram I have an opinion that for beginners, it is better to build and run assembler code in Android using android source code.
e.g. you can create a module with the specification "BUILD_EXECUTABLE" in the Android.mk
You can have a main function inside the C code and have the assembler code built along with main.c
You can add such a module even under gingebread/frameworks/base/<mymodule>

Related

How to tell toolchain for a Device? In order to build native application in C

I have a shared library in C. I want to compile and run a test application on my android device.
As for as my understanding goes, here is what I think I have to do:
Cross compile the library for the arm device using its tool chain
Make an android.mk file and compile using NDK (I followed this link : build-cc-executables-for-android-using-ndk)
I modified the android.mk file to add a shared library,
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# give module name
LOCAL_MODULE := depend1
LOCAL_SRC_FILES := libdepend1.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
# give module name
LOCAL_MODULE := depend2
LOCAL_SRC_FILES := libdepend2.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
# give module name
LOCAL_MODULE := test
# list your C files to compile
LOCAL_SRC_FILES := test.c
# this option will build executables instead of building library
include $(BUILD_EXECUTABLE)
The project compiles. I get my executable in the libs folder.
On running the executable on android shell using adb I get the following error:
Init: Error opening /data/local/project/depend1.so: dlopen failed: could not load library "depend2.so" needed by "depend1.so"; caused by could not load library "libgcc_s.so.1" needed by "depend2.so"; caused by library "libgcc_s.so.1" not found
(NOTE: dlopen is part of my code)
It is not able find a library that is part of the toolchain, I didnt find this library in /system/lib of the device, which leads me to my first question - Am i using the right toolchain (the one I used is arm-none-linux-gnueabi)
Secondly am I building it correctly for android?
This library use Cmake or automake?
For Cmake you just need to properly confugure it (how to)
Example: cmake -DANDROID_NDK=path/to/ndk -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake --DANDROID_ABI=armeabi-v7a -DANDROID_PLATFORM=android-21 ..
For automake you should use prebuilt GCC toolchains (but GCC deprecated in NDK) or create new own standalone toolchain (how to)
This toolchains are 100% valid for cross-compiling for Android
If you still want use ndk-build you can read this link (I don't use it, so I can help further only with Cmake and automake)

how to compile with protocol buffer into .so file

I'm trying to use Google's Protocol buffer on a C++ project. I can build it just fine for say... an iOS framework target. However, I can't seem to get the compiler to find any of the google/protobuf files. I already have the static library file (not sure if this one works on my architecture? i used: https://gist.github.com/BennettSmith/9487468ae3375d0db0cc)
in the output of the proto file, let's say blah.pb.h, i have a reference to protobuf:
#include <google/protobuf/stubs/common.h>
the compiler can't find that ^ reference.
I've tried to ndk-build with something like this:
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf
LOCAL_SRC_FILES := src/lib/libprotobuf.a
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_SRC_FILES:=$(shell find src/lib -name '*.cpp')
LOCAL_MODULE := mymodule
LOCAL_C_INCLUDES += ./src/lib
LOCAL_STATIC_LIBRARIES := libprotobuf
include $(BUILD_SHARED_LIBRARY)
but it doesn't seem to help at all. what's going on? how do i include lib protobuf when i have the .a file? do i have to compile it from source?
turns out i have to multiple things:
i have to duplicate the entire protobuf include folder (the one with all the headers) to my project. and then include them in my LOCAL_EXPORT_C_INCLUDES
also, the command that i was using to do ndk-build is also not fully correct. it was missing a ton of stl stuff, like missing "string" or vector or map. so i used this instead:
ndk-build V=1 NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk APP_STL=stlport_static
NDK - Android Java with native (JNI) C++ code build issue

JNI Wrapping - functions not exported

I'm trying to wrap some functions of a c-library (OpenAL-MOB) in order to use them in my Android application.
I think that my functions aren't correctly exported.
Steps I've taken:
I've made a java class with the functions I would like to use in my Android application,
Created stubs by using javah and javac (I haven't changed any class names or package names after doing this),
Added the wrapper files to the Android.mk
Build an .so library (with ndk-build)
Copied the .so file to the libs/armeabi-folder of my android project
Loaded the library in my android code and called a native function -> unsatisfiedinkerror.
When I try to use the library in my android code, I am able to load the library, but it cannot find my wrapped functions.
System.loadLibrary("openal"); // Works
OpenAlConnector.init(); // My wrapped function throws an unsatisfiedlinkerror
I think that my functions aren't actually exported.
To add my wrapper functions, I've modified the Android.mk that was already present in the OpenAL-MOB project. I didn't get any errors during the build. The only thing I did, was adding 2 files (.c created by javah and a helper class) to the end of LOCAL_SRC_FILES.
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../include $(LOCAL_PATH)/../../OpenAL32/Include $(LOCAL_PATH)/../../mob/Include $(LOCAL_PATH)
LOCAL_MODULE := openal-static
LOCAL_SRC_FILES := ../../Alc/ALc.c ../../Alc/alcConfig.c ../../Alc/alcDedicated.c ../../Alc/alcEcho.c ../../Alc/alcModulator.c ../../Alc/alcReverb.c ../../Alc/alcRing.c ../../Alc/alcThread.c ../../Alc/ALu.c ../../Alc/backends/loopback.c ../../Alc/backends/null.c ../../Alc/backends/opensl.c ../../Alc/backends/wave.c ../../Alc/bs2b.c ../../Alc/helpers.c ../../Alc/hrtf.c ../../Alc/mixer.c ../../Alc/mixer_c.c ../../Alc/mixer_inc.c ../../Alc/mixer_neon.c ../../Alc/mixer_sse.c ../../Alc/panning.c ../../mob/alConfigMob.c ../../OpenAL32/alAuxEffectSlot.c ../../OpenAL32/alBuffer.c ../../OpenAL32/alEffect.c ../../OpenAL32/alError.c ../../OpenAL32/alExtension.c ../../OpenAL32/alFilter.c ../../OpenAL32/alListener.c ../../OpenAL32/alSource.c ../../OpenAL32/alState.c ../../OpenAL32/alThunk.c openalwrapper.c org_vansina_openal_OpenAlConnector.c
# set the platform flags
ifeq ($(APP_ABI),x86)
LOCAL_CFLAGS += -D HAVE_SSE
else
LOCAL_CFLAGS += -D HAVE_NEON -mfloat-abi=softfp -mfpu=neon -marm
endif
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := openal
LOCAL_STATIC_LIBRARIES := openal-static
include $(BUILD_SHARED_LIBRARY)
I've used NM to see which functions were exported (nm.exe -D libopenal.so). This was the result:
00002004 A __bss_start
U __cxa_atexit
U __cxa_finalize
00002004 A _edata
00002004 A _end
I'm not sure if I'm correct, but it seems that my functions are missing.
Does anyone have an idea what I can do or check? Is there a problem in my .mk file?
I'm try to wrap this library for some days now and I'm getting quite desparate. Any help is very much appreciated!
Edit:
I believe that it has something to do with building the library as a static first and then as a shared library. It seems that all the symbols get lost if I create a shared lib like that. Can someone give me additional info about this?

How to build multiple projects in the correct dependency order with Android NDK?

I have a series of existing libraries which I need to re-use in an Android application. The layout is similar to:
\Libraries\libOne
\Libraries\libTwo [Static library]
\Libraries\libThree
\Applications\MyApplication\ [Application]
libTwo depends on libOne, and libThree depends on libTwo. How can I get the build system to build all of the libraries in the correct order? I'm trying to use Eclipse, but if necessary I can use the command line.
All of these libraries will eventually be referenced by a Java application (and use JNI to interact with them). Any clues on how I setup the Android.mk / Application.mk files?
I've tried using BUILD_STATIC_LIBRARY for libTwo, but it doesn't actually output any files! I was expecting a libTwo.a file, but nothing gets compiled or built.
Do I write one Android.mk in the application? Or an Android.mk for each project?
OK, now I see your edit, and this makes it possible to answer the specific question.
You must have at least one Android.mk file for your application if you want to use Android NDK to build your native library/ies. This is not a requirement, though. It is OK to build it though Cmake, or a "standalone toolchain" with "traditional" makefiles, or with a MS Visual Studio plugin, or any other way. It is the result that matters. The result is a shared object built with a compatible compiler for a bionic runtime.
It makes goode sense to put the library in ${project_root}/libs/armeabi/ directory (for ARM v6 compatible devices, other subdirectories for x86, MIPS, arm v7a) to allow the APK builder pack it correctly, to allow app installer to unpack the correct version (compatible with the device processor) into /data/data/${package_name}/lib directory on the device, and finally to be able to use System.loadLibrary(short_name) to use it from Java. But it is also quite possible to pack the so file differently, unpack it manually, and load it from any place on the device file system (provided your app has permission to write and read this file).
But if we filter out exotic cases, it is much more comfortable to have an Android.mk in the ${project_root}/jni directory. In terms of ndk-build command, each library is a separate MODULE, but all three may be defined in one Android.mk file. On the other hand, if your libraries are isolated (e.g. come from separate 3rd parties), you will probably prefer to create three Android.mk files. Luckily, ndk-build is nothing but a wrapper around gnu make, and the simple include statement in Android.mk works as in any other makefiles.
In summary, your case is probably covered by a simple Applications/MyApplication/ [Application]/jni/Android.mk file:
include ../../Libraries/libOne/Android.mk
include ../../Libraries/libTwo/Android.mk
include ../../Libraries/libThree/Android.mk
I don't know what dependency you have between libOne and libTwo, but for libOne the file Libraries/libOne/Android.mk will look like
LOCAL_PATH = $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libOne
LOCAL_SRC_FILES := first.c
include $(BUILD_STATIC_LIBRARY)
and Libraries/libThree/Android.mk
LOCAL_PATH = $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libThree
LOCAL_SRC_FILES := third.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libOne $(LOCAL_PATH)/../libTwo
LOCAL_STATIC_LIBRARIES := libOne libTwo
include $(BUILD_SHARED_LIBRARY)
You should run ndk-build from Applications/MyApplication/ [Application] directory - either from command prompt, or through Eclipse ADT plugin.
update the same may be expressed by one Android.mk file in jni directory:
LOCAL_PATH = ../../Libraries/libOne
include $(CLEAR_VARS)
LOCAL_MODULE := libOne
LOCAL_SRC_FILES := first.c
include $(BUILD_STATIC_LIBRARY)
LOCAL_PATH = ../../Libraries/libThree
include $(CLEAR_VARS)
LOCAL_MODULE := libThree
LOCAL_SRC_FILES := third.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libOne $(LOCAL_PATH)/../libTwo
LOCAL_STATIC_LIBRARIES := libOne libTwo
include $(BUILD_SHARED_LIBRARY)
There is an android section in the projects' properties, where you can edit the library dependencies. It can only be used, if libOne libTwo and libThree are marked as libraries, in their properties panel.

Linking FFTW into an Android NDK application

I am currently writing a genre classification application as my final year project in Computer Engineering. I initially wrote the feature extraction code (implementing FFTW) in C and now I need to implement it on Android via the NDK.
This is my first NDK project so I'm still getting the hang of things but I have compiled the FFTW3 library for Android according to this guide. I didn't do the very last step because I didn't think it was right for what I need.
My question is how do I, after the compile step, use the library in the main NDK application that calls on it? Do I everything normally in Application.mk just with LOCAL_STATIC_LIBRARIES set to the libfftw3.a that I just compiled? And then I don't need to have any -lfftw3 linker flags like I normally would right?
You can use prebuit FFTW library (no matter how did you build it).
Or you can build FFTW in Android.mk makefile with the whole project.
Android.mk content will be:
# Prebuilt FFTW library
include $(CLEAR_VARS)
LOCAL_MODULE := fftw
include $(PREBUILT_STATIC_LIBRARY)
# or
# Build FFTW library
include $(CLEAR_VARS)
LOCAL_MODULE := fftw
# TODO put your static libs build flags
include path_to_fftw_sources/$(LOCAL_MODULE).mk
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := YourProject
# TODO put your shared lib build flags
include path_to_your_project/$(LOCAL_MODULE).mk
LOCAL_STATIC_LIBRARIES += fftw
include $(BUILD_SHARED_LIBRARY)
I have written path_to_fftw_sources/$(LOCAL_MODULE).mk for building fftw static library and path_to_your_project/$(LOCAL_MODULE).mk for building your shared library. It is often better to put LOCAL_SRC_FILES and LOCAL_C_INCLUDES to the separate .mk file.
You can read more about Android.mk file in docs/ANDROID-MK.html document in your NDK distribution.

Categories

Resources