I have native source code written in C that I would like to run on my Android device (Nexus 7). I already successfully did lots of research and online tutorials on running native code on Android using Android NDK. I gained quite some knowledge on this.
However, the code that I have makes use of the complex functionalities of the standard math library, defined in complex.h. The NDK C library however does not seem to support the complex functionalities. Whenever I do an ndk-build on the project I get:
fatal error: complex.h: no such file or directory.
As a solution I thought of getting the standard math library (libm.a) from arm-linux-gnueabi and link it with my native source. Here is my Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := StandardC
LOCAL_SRC_FILES := libc.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := mathLib
LOCAL_SRC_FILES := libm.a
LOCAL_STATIC_LIBRARIES := StandardC
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ComplexOperations
LOCAL_SRC_FILES := libComplexOperations.a
LOCAL_STATIC_LIBRARIES := mathLib
LOCAL_C_INCLUDES += /usr/arm-linux-gnueabi/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := MySource
LOCAL_CFLAGS += -std=c99
LOCAL_SRC_FILES := com_samuel_test_ComplexOperationsLib.c
LOCAL_C_INCLUDES += /usr/arm-linux-gnueabi/include
LOCAL_STATIC_LIBRARIES := ComplexOperations
include $(BUILD_SHARED_LIBRARY)
I had to link the libc of the arm-linux-gnueabi-gcc as well as libm needs it.
The "ComplexOperations" module was statically compiled using arm-linux-gnueabi-gcc with compiler flags -march=armv7-a. This library makes use of complex.h.
This builds without any errors and warnings. But when I run the application and call
System.loadLibrary("MySource");
I get this error on logcat:
E/dalvikvm( 3932): dlopen("/data/app-lib/com.samuel.test-1/libMySource.so") failed: Cannot load library: soinfo_relocate(linker.cpp:975): cannot locate symbol ".LANCHOR2" referenced by "libMySource.so"...
On this error an UnsatisfiedLinkError exception is thrown which causes the application to crash if not handled.
Can somebody PLEAASEE help me out!! I've already tried figuring this out myself for days!! :(
As of Android-L(ollipop) the NDK now provides the complex.h header.
Download the latest NDK revision from https://developer.android.com/tools/sdk/ndk/index.html and complex.h can be found in /platforms/android-L/arch-arm/usr/include.
I added the following line to Android.mk, which seems to have fixed the problem.
LOCAL_C_INCLUDES += C:\Users\Sami\workspace\android-ndk-r8e\sources\cxx-stl\gnu-libstdc++\4.7\include\
Not sure which variable would replace the C:\Users\Sami\workspace\ part, so if anybody know, please do tell.
Edit:
Actually, that only removed the error for some reason, but it didn't fix the problem from what I noticed. On that note, C:\Users\Sami\workspace\android-ndk-r8e could have been replaced with $(NDK_ROOT).
I tried Crystax's NDK, but I kept getting the complex.h not being found error. All I did was simply copying complex.h and _mingw.h into my jni directory. Everything worked an it the code was tested on both x86 and ARM emulator.
It seems like your PATH is broken. Kindly refer to following posts to solve this issue.
Android NDK: how to include Android.mk into another Android.mk (hierarchical project structure)?
android ndk error "no such file or directory"?
SOLVED!
First of all I should've built my ComplexOperations sources with the toolchain provided by the Android NDK, as the documentation clearly states not to cross-compile with gnu compilers. So that was my first mistake.
That alone didn't yet solve my problem as I still got the complex.h not found error when I do an ndk-build. The Android NDK contains a VERY limited implementation of the Standard libc.
To solve this I used CrystaX NDK, an extended implementation of Android NDK. That solved everything!!
Related
Is Android Studio supposed to ignore values in Application.mk when building NDK applications?
I have changed my Application.mk as follows yet my project keeps building x86, mips etc. It should only be building armeabi-v7a
#APP_ABI := all
APP_ABI := armeabi-v7a
Build output - see the x86
I have noticed references to NDK_APP_ABI and NDK_DEFAULT_ABIS inside the setup-app.mk file. Are these supposed to override what is contained in Application.mk?
Are there variables that can be specified inside the build.gradle files that will propagate into the setup-app.mk file?
Where is the best place to find documentation on this? - Google documentation is very sparse at the moment.
Yes, the technical reason is that gradle specifies APP_ABI on the command line of ndk-build that it generates. And for gnu make, command line parameters override whatever is written in the Makefile.
Make has the override keyword which could help... Only that this will destroy the delicate structure of externalNativeBuild. If you want your ndkBuild to cooperate with Android Studio, keep your scripts as simple and clean as possible.
The gradle plugin uses abiFilters to tune the build. Actually, the official docs describe it pretty well.
my game is using cocos2dx 2.2.6 I have upgrade the NDK to the the NDKr12 beta1 and try to build my project then I get so many errors at the NdkModule folder and NDK complain that it doesn't found the output file in Ndk Module Path:
cocos2dx/platform/third_party/android/prebuilt/lib*/libs/arm64-v8a/file.a
what it that mean and how to fix it?
I manage to solve it by specific the target architectures at application.mk
by adding this line:
APP_ABI := armeabi armeabi-v7a x86
First of all I must say I'm new to Android NDK development.
I'm trying to compile a working engine (openGL and openCL based) with the NDK to use it in Android.
I have variables in the headers and cpp files defined to separate the OpenGL 3.0 code and the OpenGLES 2.0 one.
Anyways, in the Android.mk file I recursively add all the .cpp files in the folders and subfolders when compiling so no code differentiation is performed and the compilation fails.
How can I work around this?
(I'm using Eclipse Luna CDT + ADT in MAC OSX)
Ok, this is done via the Android.mk file adding the flags:
LOCAL_CFLAGS := -DANDROID_NDK
This defines the MACRO "ANDROID_NDK"
Then in the code use:
#ifdef ANDROID_NDK
...
and so on.
When I build my code, I see that $(NDK)\toolchains\arm-linux-androideabi-4.6 is being used although I have $(NDK)\toolchains\arm-linux-androideabi-4.8 available on my machine.
My understanding is that one should always use the latest androideabi so that the latest gcc compiler can be used. I am wondering why ndk-build is picking up an older version.
Here is my Application.mk for your reference:
APP_ABI := armeabi-v7a
APP_PLATFORM := android-16
APP_OPTIM := release
APP_STL := gnustl_static
APP_CPPFLAGS := -std=gnu++11
The value forAPP_PLATFORMneeds to be android-16 so that we can support Android OS version 4.1 and above. I wonder if androideabi is tied toAPP_PLATFORMvalue.
The issue is not the ABI, but rather the toolchain version.
You can control this in your Android.mk
From the documentation thereof:
NDK_TOOLCHAIN_VERSION
Define this variable to either 4.6, 4.7 or 4.8 to select version of the GCC compiler. 4.6 is the default
I am trying to compile one of the modules in my Android ndk project with g++ although the sources are all in C.
My eyes are irritated by the make system warnings:
`C:/NVPACK/android-ndk-r8d/build/core/build-binary.mk:348: warning: overriding commands for target 'obj/local/armeabi/objs/xxx/yyy.o'`
`C:/NVPACK/android-ndk-r8d/build/core/build-binary.mk:345: warning: ignoring old commands for target 'obj/local/armeabi/objs/xxx/yyy.o'`
And these warning pairs will be printed as much as there will be the source files and therefore the objects.
I've tried to declare LOCAL_SRC_FILES with all the different flavors.
`LOCAL_SRC_FILES :=
$(LOCAL_PATH)/Directory/source.c
$(notdir $(wildcard $(LOCAL_PATH)/*.c))
$(notdir $(wildcard $(LOCAL_PATH)/Directory/*.c))
$(addprefix DirectoryPrefix/,$(notdir $(wildcard $(LOCAL_PATH)/Directory/*.c)))`
And still the warning persists.
Make document says:
warning: overriding commands for target xxx''
warning: ignoring old commands for target xxx''
GNU make allows commands to be specified only once per target (except for double-colon rules). If you give commands for a target which already has been defined to have commands, this warning is issued and the second set of commands will overwrite the first set.
But I cannot understand how this is related at all.
After dealing with it seems like making a g++ compile theses C files makes this warning appear.
Therefore specifying this statement:
LOCAL_CPP_EXTENSION := .c
Which makes C files build with g++ is causing it. Because when compiling with gcc no warnings are printed.
Make sure that you have included clear vars:
include $(CLEAR_VARS)
And if building any other libraries that you include the correct build macro like
include $(BUILD_SHARED_LIBRARY)
I had run into this a day or two ago and it was while adding a new library I had forgotten to include one or the other (I think the CLEAR_VARS makes most sense.) So it was re-appending some values from the main library to the child library or vice versa.