I've found some serious difficulties in getting a working .so library to develop an Android app with Android NDK and intel TBB.
Basically I've downoaded version 4.4 Update 4 bundle for Android and followed the steps there (kind of, since the docs are not correct...).
Problem is that I can only get x86 and x86_64 .so libraries when compiling, since there are no armeabi-XXX or mips folders with the necessary .so in there.
Using the suggested command ./ndk-build.cmd tbb target=android arch=arm does not produce anything, in fact it tells me
/workspace/tbb44_20160413oss/lib/android/mips/libtbb.so library not found. Copy mips version of library to /home/filippo/workspace/tbb44_20160413oss/lib/android/mips folder to enable its build.
and the same for the other missing directories.
Threfore using only ./ndk-build.cmd tbb target=android gives me a cuople of dirs: x86 and x86_64 which I can use in Android Studio, and work with the emulator.
The result is taht I can properly test my apps on an emulator but cannot make it work into my personal device.
What am I missing here?
Application.mk
APP_ABI := x86 x86_64 // if I choose all, of course it won't find the .so for the other architectures
APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti
APP_STL := gnustl_shared
Android.mk
LOCAL_PATH := $(call my-dir)
#
# TBB
#
include $(CLEAR_VARS)
LOCAL_MODULE := libtbb
LOCAL_SRC_FILES := $(LOCAL_PATH)/$(TARGET_ARCH_ABI)/libtbb.so
include $(PREBUILT_SHARED_LIBRARY)
#
# Main module
#
include $(CLEAR_VARS)
LOCAL_MODULE := myndkapp
LOCAL_SHARED_LIBRARY := libtbb
include $(BUILD_SHARED_LIBRARY)
Thanks.
As you can see in 'jni/Application.mk' you can use targets 'ia32', 'intel64', 'arm' and 'arm64'.
Also it looks like you trying to build on Windows platform, so you should add a tbb_os=windows to your make command like this:
C:\TEMP\tbb44_20160413oss\src>ndk-build.cmd tbb tbbmalloc target=android arch=arm tbb_os=windows
Related
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)
I'm trying to build a jni project which generates a shared library using the Android-ndk.
I'm going to code a some part in assembly language as needed, so I configured the project as the following.
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_test
LOCAL_SRC_FILES := Test.cpp MyAsm.s
LOCAL_CFLAGS :=
include $(BUILD_SHARED_LIBRARY)
Application.mk:
APP_ABI := armeabi-v7a
APP_STL := stlport_static
Test.cpp:
...
MyAsmFunc();
...
MyAsm.s:
.text
.align 2
.global MyAsmFunc
MyAsmFunc:
...
tbb [PC,R1]
...
cbnz R1,loc_51ACE
...
When I was compiling the project, I've got the following error msg.
MyAsm.s:224: Error: selected processor does not support ARM mode `tbb [PC,R1]'
MyAsm.s:882: Error: selected processor does not support ARM mode `cbnz R1,loc_51ACE'
My question is how to build the project successful. Help me, please.
Thanks in advance.
According to this page,
These 16-bit Thumb instructions are available in ARMv6T2 and above.
There are no ARM or 32-bit Thumb versions of these instructions.
You're compiling for ARMv7-A, so the first part is fine. However, it's trying to interpret the instructions as ARM rather than THUMB/THUMB2. Add .thumb / .thumb_func directives to your assembly source file to set THUMB mode. See also the GNU as docs.
I have a problem getting the native debugging support to work for my Eclipse project under Windows for Android.
Google unfortunately didn't help after more than 1 day of research.
I am pretty much a beginner with eclipse, so the solution might be easy because I do also some non-standard things I guess.
My android project is already functioning and running fine on my devices (Acer Iconia A500 Android 3.2.1, HTC Incredible S Android 4.0.4 etc.).
I created the project with the ADT Plugin Wizard and then added native support by using the project context menu entry added by ADT.
I then added the java files I already had (previously I used to compile with CMake and the Android stand-alone toolchain, though I never tried to remote debug this way). I created a new package for that "com.x.y" where I dropped them on to (I don't want to reveal the real package name as the project will be part of a commercial product).
Then I added my Sources by dragging them into the jni folder. The sources are not located inside the jni folder but are linked to a location "../../" below the project (Its part of a cross platform application so I can reuse the source files accross different toolchains).
I also link against 4 static libraries that will be shipped with the product by adjusting the Android.mk the following way:
LOCAL_PATH := $(call my-dir)
MY_PATH := $(LOCAL_PATH)
LOCAL_PATH := $(MY_SDK)/lib/Android/armeabi-v7aD
include $(CLEAR_VARS)
LOCAL_MODULE := A
LOCAL_SRC_FILES := libA.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := B
LOCAL_SRC_FILES := libB.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := C
LOCAL_SRC_FILES := libC.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := D
LOCAL_SRC_FILES := libD.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(my_SDK)/include/
LOCAL_PATH := $(MY_PATH)/../../..
LOCAL_CFLAGS += -Wno-format -DANDROID -fno-rtti -fno-exceptions #And many other flags If they are important I will post them later, too
LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions
LOCAL_MODULE := MY_PROJECT
LOCAL_SRC_FILES := Android/Main.cpp # Some other sources..
LOCAL_LDLIBS := -lstdc++ -lEGL -lGLESv2 -llog -Wl,--allow-multiple-definition -Wl,--no-undefined
LOCAL_STATIC_LIBRARIES := A B C D
include $(BUILD_SHARED_LIBRARY)
I also have a Application.mk:
APP_ABI := armeabi-v7a
APP_PLATFORM := android-9
APP_STL := stlport_static
APP_CFLAGS += -fno-rtti -fno-exceptions
Then I added under Debug Configurations a new "Android Native Application" launching the default Activity and using
Debugger "${NdkGdb}"
Command File "${NdkProject}\libs\${NdkCompatAbi}\gdb.setup"
Shared Libraries (Added automatically) ${NdkProject}/obj/local/$NdkCompatAbi}/
The rest is also added automatically and I think should work this way.
One thing that I think is odd is that I get the console Output
[2013-03-08 10:50:36 - Unable to launch cygpath. Is Cygwin on the path?] java.io.IOException: Cannot run program "cygpath": CreateProcess error=2, The system cannot find the file specified
But I can build the project fine this way and later I don't get any warnings trying to attach gdb (I am using Msys, I also have cygwin installed so I don't know why Eclipse is complaining here).
When I launch the application, it starts up on the device and then I get the following Console output([Android Native Application] gdb):
(no debugging symbols found)
Error while mapping shared library sections:
/system/bin/linker: No such file or directory.
Error while mapping shared library sections:
libstdc++.so: No such file or directory.
... And alot more of that type
(no debugging symbols found)
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
warning: shared library handler failed to enable breakpoint
No line 219 in file "jni/../../../MySourceFile.cpp".
I definitely build with NDK_DEBUG=1, my static .a Libraries are build with -g
AndroidManifest.xml has an entry android:debuggable="true".
When I run "sh /ndk-gdb --verbose" in the eclipse project directory (using Msys) I get the following output:
Android NDK installation path: /c/SDK/android-ndk-r7
Using default adb command: /c/SDK/android-sdks/platform-tools/adb.exe
ADB version found: Android Debug Bridge version 1.0.31
Using final ADB command: '/c/SDK/android-sdks/platform-tools/adb.exe'
Using auto-detected project path: .
Found package name: com.x.y
ABIs targetted by application: armeabi-v7a
Device API Level: 13
Device CPU ABIs: armeabi-v7a armeabi
Compatible device ABI: armeabi-v7a
Found debuggable flag: true
ERROR: Non-debuggable application installed on the target device.
Please re-install the debuggable version!
I really want to have native debugging support for this project. So I really appreciate any help.
Is it true that I have to use cygwin? I don't get any reasonable error message for that while trying to attach the debugger.
Trying to run ndk-gdb and getting this error:
Android NDK installation path: /Library/AndroidSDK/ndk/
Using specific adb command: /Library/AndroidSDK/platform-tools/adb
ADB version found: Android Debug Bridge version 1.0.31
Using ADB flags:
Using auto-detected project path: .
Found package name: com.dev.project
jni/Android.mk:18: * Android NDK: Aborting. . Stop.
ABIs targetted by application: Android NDK:
Device API Level: 17
Device CPU ABIs: armeabi-v7a armeabi
ERROR: The device does not support the application's targetted CPU ABIs!
Device supports: armeabi-v7a armeabi
Package supports: Android NDK:
The 18th line in the jni/Android.mk is an import module call.
What does that mean and how to remedy it?
App is debuggable as per ndk documentation. I'm using Mac.
I can build and run the App, so build script should be fine.
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libgl2jni
LOCAL_CFLAGS := -Werror -Wall -g
LOCAL_CPPFLAGS := -std=c++11
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../src $(LOCAL_PATH)/../../include $(LOCAL_PATH)/../../../boost
NDK_MODULE_PATH := $(LOCAL_PATH)/../../lib/ndk
LOCAL_SRC_FILES := $(subst $(LOCAL_PATH)/,,$(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/../../src/*/*.cpp))
LOCAL_LDLIBS := -llog -lGLESv2
LOCAL_STATIC_LIBRARIES := freetype
include $(BUILD_SHARED_LIBRARY)
$(call import-module,otherlib) #commenting this line launches the ndk-gdb, but ndk-build fails
Application.mk
APP_STL := gnustl_static
#remove for release?
APP_ABI := armeabi armeabi-v7a
APP_OPTIM := debug
I had the same problem. I'm quite sure it is a bug in the core/build-local.mk script. At least the error message is not meaningful.
I fixed doing this:
export NDK_MODULE_PATH=path_to_look_for_modules
Where path_to_look_for_modules should be the parent directory of your module declared in the Android.mk. That is, if you have /myproject/mylibs/otherlib export the path /myproject/mylibs
If you have several paths, as usual:
export NDK_MODULE_PATH=path1:path2:path3
If you are building an Android app and have some ndk code you may be able to solve this problem by adding/modifying your Application.mk (usually in the jni directory) with the following line:
# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi armeabi-v7a x86 mips
#APP_ABI := armeabi
APP_PLATFORM := android-10
I mean the APP_ABI line. This is specifying the target processors to compile the ndk code for. I am assuming from the error message that you are testing on a device that has a different cpu type than the ones you built the app for.
Useful information about third party libraries
Possible issue with makefile or environment
export NDK_PROJECT_PATH=[Path]
where [Path] is the parent of "jni" directory, which in turn contains your NDK code.
You "might" face this issue if your NDK code (jni directory) is located separately from your Android java code.
A common solution to this problem is to include this line in your Application.mk.
APP_ABI := armeabi-v7a
Replace armeabi-v7a by the appropriate API as per the Device supports line. This will ensure that your application is built for the correct platform, and that ndk-gdb can find it.
For example let build static library called "some".
LibSome Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := some
LOCAL_SRC_FILES := some.c
include $(BUILD_STATIC_LIBRARY)
LibSome Application.mk
APP_MODULES := somelib
APP_OPTIM := release
And get armeabi version of our lib in LibSome/obj/local/armeabi/libsome.a
So now we need to drop our lib to mainProject jni folder and use it
MainProject Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := some
LOCAL_SRC_FILES := libsome.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/some
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := mainProject
LOCAL_SRC_FILES := mainProject.c
LOCAL_STATIC_LIBRARIES := some
include $(BUILD_SHARED_LIBRARY)
But there are different ABI like mips, x86, armeabi-v7a and we can get all supported versions of somelib by current ndk just adding
APP_ABI:= all
to SomeLib Application.mk, so we get LibSome/obj/local/armeabi-v7a/libsome.a, LibSome/obj/local/x86/libsome.a etc
Main question - do i really need to think about different ABI and create project for every supported ABI like mainProjectx86, mainProjectMIPS with different ABI builded libs?
And secondary questions are:
If i build project for armeabi ABI (default) how many devices will be cut out? Can armeabi-v7a ABI device run armeabi ABI app?
If there is a way to have one project with different set of pre-builded libs? So if you build mainProject for ameabi-v7a it will use armeabi-v7a libs and so on?
Ok, So firstly, if your are using standard C calls without any architecture specific assembly language embedded, it's safe to use APP_ABI := all. This will allow gcc to create libs for all architectures and your app will have no problems running.
if however, you are using something specific to ARM, e.g. NEON architecture calls for optimized math or Intel x86 SSE3 calls for optimized math, then APP_ABI := all may not be a good idea. This might lead to runtime errors which are very difficult to understand. Then you may be required to maintain different projects for different architectures.
Coming to secondary question:
1. Most of the latest devices are armeabi-v7a, so only the older devices will be cut out. Also parallel x86 and MIPS devices will also be cut out. But since most flagships like Samsung, HTC and Sony ship with ARM, your app will be reachable to a big percentage.
Not much clue on the second one for now.
All ARM devices run armeabi. The older and slower ones use ARMv6, and cannot use armeabi-v7a libraries. But it is possible to mix armeabi and ameabi-v7a shared libraries in one application. This may come useful if you have a huge native library which you don't want to ship in two copies, and also some very specific function that is a performance bottleneck which may be vastly accelerated with NEON optimizations. So, in the end you have the following structure in your project folder:
libs/
armeabi/
libhuge.so
libslow.so
armeabi-v7a/
libfast.so