I'm trying to build a static library using a standalone toolchain for a project that has its own build process, which I then wrap with a C++ library and expose to Android (compiled with ndk-build). However, on the ndk-build step I receive the following error:
➜ jni /Users/chrisfosterelli/Library/Android/sdk/ndk-bundle/ndk-build
[arm64-v8a] Compile++ : wrapper <= wrapper.cpp
In file included from /Users/chrisfosterelli/workspace/android/jni/wrapper.cpp:9:
In file included from ../prebuild/include/valhalla/meili/universal_cost.h:7:
In file included from ../prebuild/include/valhalla/sif/dynamiccost.h:4:
In file included from ../prebuild/include/valhalla/baldr/directededge.h:5:
../prebuild/include/valhalla/baldr/graphconstants.h:432:11: warning: 21 enumeration values not handled in switch: 'kRoad', 'kRamp', 'kTurnChannel'... [-Wswitch]
switch (use) {
^
1 warning generated.
[arm64-v8a] SharedLibrary : libwrapper.so
/Users/chrisfosterelli/Library/Android/sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/lib/gcc/aarch64-linux-android/4.9.x/../../../../aarch64-linux-android/bin/ld: /Users/chrisfosterelli/workspace/android/jni/../prebuild/libvalhalla_meili.a(libvalhalla_meili_la-map_matcher_factory.o): Relocations in generic ELF (EM: 62)
[...above message repeated many times...]
/Users/chrisfosterelli/workspace/android/jni/../prebuild/libvalhalla_meili.a: error adding symbols: File in wrong format
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [/Users/chrisfosterelli/workspace/android/obj/local/arm64-v8a/libwrapper.so] Error 1
➜ jni ls /Users/chrisfosterelli/Library/Android/sdk/ndk-bundle/
This error indicates, as far as I can tell, that I'm trying to mix and match binaries compiled for different architectures. However, from what I can tell the library is the correct architecture:
root#eacbdb1c0e46:/meili/meili2/newtest# ar x libvalhalla_meili.a
root#eacbdb1c0e46:/meili/meili2/newtest# file libvalhalla_meili_la-map_matcher_factory.o
libvalhalla_meili_la-map_matcher_factory.o: ELF 64-bit LSB relocatable, ARM aarch64, version 1 (SYSV), not stripped
root#eacbdb1c0e46:/meili/meili2/newtest#
FWIW, these are my current Application.mk,
APP_STL := c++_static
APP_CPPFLAGS := -frtti -std=gnu++11 -D_GLIBCXX_USE_C99
APP_CPPFLAGS += -fexceptions
NDK_TOOLCHAIN_VERSION := clang
APP_LDFLAGS := -latomic
APP_PLATFORM := android-21
APP_ABI := arm64-v8a
and Android.mk,
LOCAL_PATH := $(call my-dir)
# static library info
include $(CLEAR_VARS)
LOCAL_MODULE := libvalhalla_meili
LOCAL_SRC_FILES := ../prebuild/libvalhalla_meili.a
LOCAL_EXPORT_C_INCLUDES := ../prebuild/include
include $(PREBUILT_STATIC_LIBRARY)
# wrapper info
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += ../prebuild/include
LOCAL_MODULE := wrapper
LOCAL_SRC_FILES := wrapper.cpp
LOCAL_STATIC_LIBRARIES := libvalhalla_meili
include $(BUILD_SHARED_LIBRARY)
Any ideas how to resolve this? I've tried a number of things but all of them lead to more (more obscure) errors, so I'm hoping someone here can point me in the correct direction!
I discovered the problem, but I wish I had a more insightful answer. Apparently the build process had created two library files. The one that I inspected was, of course, ARM64. However the one that I actually copied to the Android device was x86.
So, the error message was correct and so was the library file, but there was more than one file involved. If you're running into the same problem and pretty sure your library is ARM64, double check that's actually the same file that is being compiled into the ndk build!
Related
I am struggling with this problem since few weeks I hope someone can help me.
I have created a C function wrapper in my Android app that impements the JNI export. I have also created a second .so library in order to call my original library but here I have a problem when linking with ndk-build. This is my code:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_prebuilt_lib
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../jni/
LOCAL_SRC_FILES := ../jniLibs/$(TARGET_ARCH_ABI)/my_prebuilt_lib.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := myjni
LOCAL_SRC_FILES := wrapper.cpp
LOCAL_SHARED_LIBRARY += my_prebuilt_lib
include $(BUILD_SHARED_LIBRARY)
This is the command I am using to build myjni.so:
ndk-build NDK_PROJECT_PATH=./ NDK_APPLICATION_MK=./jni/Application.mk
And I get this error:
Android NDK: WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 in .//AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.
[armeabi-v7a] Install : my_prebuilt_lib.so => libs/armeabi-v7a/liblocSDK4d.so
[armeabi-v7a] Compile++ thumb: myjni <= wrapper.cpp
[armeabi-v7a] SharedLibrary : libmyjni.so
jni/wrapper.cpp:24: error: undefined reference to 'hex2int(char)'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
Looking into my_prebuilt_lib.so I can see the following declaration about the function I want to call:
00004c51 T hex2int(char)
Any suggestion?
I am trying to interface with an MSI SDR dongle, using an android app
This device is a clone of the SDRPlay SDR device, and is compatible with it's software and drivers
I am trying to interface with this using an OTG cable and android phone
The android drivers for this can be downloaded from here https://www.sdrplay.com/downloads/
It is in the Android tab under the API/HW – V2.11 (15TH NOV 2017) link (https://www.sdrplay.com/anddl.php)
A possible sample code for this driver can be found here: https://www.sdrplay.com/docs/AndroidIntegrationNote.pdf
Before making the full android program it says the library (libmir_sdr_api.a) should be built into an .so library file using ndk-build
I currently have Android's hello-jni sample project from here: https://github.com/android/ndk-samples/tree/android-mk/hello-jni
I have replaced the jni folder using the Android.mk file, libmir_sdr_api.a, mir_sdr.h, initialization-jni.cpp, demod-jni.cpp and demod-jni.h files mentioned in section 3 of the AndroidIntegrationNote.pdf file I linked above
When I execute ndk-build from the hello-jni project folder, I get he following error:
Android NDK: Found platform level in ./default.properties. Setting APP_PLATFORM to android-25.
Android NDK: android-25 is an alias for android-24. Adjusting APP_PLATFORM to match.
[arm64-v8a] Gdbserver : [aarch64-linux-android] libs/arm64-v8a/gdbserver
[arm64-v8a] Gdbsetup : libs/arm64-v8a/gdb.setup
[x86_64] Gdbserver : [x86_64-linux-android] libs/x86_64/gdbserver
[x86_64] Gdbsetup : libs/x86_64/gdb.setup
[armeabi-v7a] Gdbserver : [arm-linux-androideabi] libs/armeabi-v7a/gdbserver
[armeabi-v7a] Gdbsetup : libs/armeabi-v7a/gdb.setup
[x86] Gdbserver : [i686-linux-android] libs/x86/gdbserver
[x86] Gdbsetup : libs/x86/gdb.setup
make: *** No rule to make target 'jni/initialisation-jni.cpp', needed by 'obj/local/arm64-v8a/objs-debug/mirics-jni/initialisation-jni.o'. Stop.
I am used to compiling NDK code suing Android Studio and cmake so I am not sure what is going on here. I have not been able to link the .a file through cmake either so I thought of giving the driver manufacturer's sample code a try, but it not working either. Is the Android.mk file in pdf file linked earlier incomplete, or am I not building it correctly? These are the contents of the Android.mk file:
# $(call my-dir) returns the local directory which is the jni directory
LOCAL_PATH := $(call my-dir)
# libmir_sdr_api.a – this section creates a version of the Mirics API to be used below
include $(CLEAR_VARS)
LOCAL_MODULE := mir_sdr_api-prebuilt
LOCAL_SRC_FILES := libmir_sdr_api.a
LOCAL_EXPORT_C_INCLUDES := $(call my-dir)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
# mirics-jni – this section uses the jni C++ source code to build the dynamic library
LOCAL_MODULE := mirics-jni
LOCAL_SRC_FILES := initialisation-jni.cpp demod-jni.cpp
LOCAL_C_INCLUDES := $(call my-dir)
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib
LOCAL_STATIC_LIBRARIES := mir_sdr_api-prebuilt
include $(BUILD_SHARED_LIBRARY)
Regarding missing jni/initialisation-jni.cpp, you probably have the file jni/initialization-jni.cpp instead.
Also, unfortunately, the document is wrong. You can only use $(call my-dir) easily at the top of the file. Luckily, Android NDK adds the jni directory to includes path for you. Still, to be on the safe side, better write:
# $(call my-dir) returns the local directory which is the jni directory
LOCAL_PATH := $(call my-dir)
# libmir_sdr_api.a – this section creates a version of the Mirics API to be used below
include $(CLEAR_VARS)
LOCAL_MODULE := mir_sdr_api-prebuilt
LOCAL_SRC_FILES := libmir_sdr_api.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
# mirics-jni – this section uses the jni C++ source code to build the dynamic library
LOCAL_MODULE := mirics-jni
LOCAL_SRC_FILES := initialization-jni.cpp demod-jni.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib
LOCAL_STATIC_LIBRARIES := mir_sdr_api-prebuilt
include $(BUILD_SHARED_LIBRARY)
Finally, pay attention to your build process. You only have one kind of the libmir_sdr_api.a static library, it's built for a 32-bit ARM CPU. Therefore you cannot build your libmirics-jni.so for other architectures. Add
APP_ABIS = armeabi-v7a
to your Application.mk file, or specify
abifilters = armeabi-v7a
in your build.gradle, if you build your library in Android Studio.
I've set up a makefile for my game in SDL. The template of the Application.mk file included in SDL has three architectures:
APP_ABI := armeabi armeabi-v7a x86
Everything compiles just fine for armeabi, but for armeabi-v7a it fails. To me, it looks like compilation completes, but the linker has all obj files of two certain folders twice. While this does not happen for armeabi. The linker (ld) gives me an error of this kind:
/path/to/bin/ld: error: /path/to/myObjFile.obj: multiple definition of 'foo(int, int)'
/path/to/bin/ld: /path/to/myObjFile.obj: previous definition here
The path is exactly the same, so this makes me assume that the linker uses every file twice. A full example of such an error is here:
/Users/martijncourteaux/Development/android-ndk-r10c/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: /Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/obj/local/armeabi-v7a/objs/main//Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/jni/src/__/ThirdParty/Box2D/Collision/b2Distance.o: multiple definition of 'b2Distance(b2DistanceOutput*, b2SimplexCache*, b2DistanceInput const*)'
/Users/martijncourteaux/Development/android-ndk-r10c/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: /Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/obj/local/armeabi-v7a/objs/main//Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/jni/src/__/ThirdParty/Box2D/Collision/b2Distance.o: previous definition here
However, the object files that are linked double also generate this warning when I launch ndk-build:
/Users/martijncourteaux/Development/android-ndk-r10c/build/core/build-binary.mk:449: warning: ignoring old commands for target `/Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/obj/local/armeabi-v7a/objs/main//Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/jni/src/__/ThirdParty/Collision/b2Distance.o'
/Users/martijncourteaux/Development/android-ndk-r10c/build/core/build-binary.mk:449: warning: overriding commands for target `/Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/obj/local/armeabi-v7a/objs/main//Volumes/Stuff/Projects/GameDev/Gump/GumpAndroid/jni/src/__/ThirdParty/Collision/b2Distance.o'
Note that I have the impression that all these obj-files that have these multiple definition errors generate also generate this warning.
This is my Application.mk:
APP_STL := gnustl_static
APP_ABI := armeabi armeabi-v7a x86
NDK_TOOLCHAIN_VERSION := clang
APP_CPPFLAGS += -std=c++11
APP_PLATFORM := android-10
And here is my Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
SDL_PATH := ../SDL
THIRD_PARTY_FOLDER := $(LOCAL_PATH)/../ThirdParty
LOCAL_CPPFLAGS += -frtti
LOCAL_CPPFLAGS += -fexceptions
LOCAL_CPPFLAGS += -funwind-tables
PCH_FILE := $(LOCAL_PATH)/Gump/Gump-Prefix.pch
#PCH_FILE := Gump/Gump-Prefix.pch
LOCAL_CPPFLAGS += -include $(PCH_FILE)
#LOCAL_PCH := $(PCH_FILE)
#LOCAL_CPPFLAGS += -DPCH
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include \
$(LOCAL_PATH)/$(SDL_PATH)_mixer/ \
$(LOCAL_PATH)/$(SDL_PATH)_image/ \
$(LOCAL_PATH)/$(SDL_PATH)_net/ \
$(LOCAL_PATH)/../ThirdParty/ \
$(LOCAL_PATH)/Gump/
# Add your application source files here...
GUMP_SRC_FILES := $(wildcard $(LOCAL_PATH)/Gump/*.cpp)
THIRD_PARTY_SRC_FILES += $(wildcard $(THIRD_PARTY_FOLDER)/tinyxml2/tinyxml2.cpp)
THIRD_PARTY_SRC_FILES += $(wildcard $(THIRD_PARTY_FOLDER)/Box2D/*/*.cpp)
THIRD_PARTY_SRC_FILES += $(wildcard $(THIRD_PARTY_FOLDER)/Box2D/*/*/*.cpp)
THIRD_PARTY_SRC_FILES += $(wildcard $(THIRD_PARTY_FOLDER)/poly2tri/**/*.cc)
LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c $(THIRD_PARTY_SRC_FILES) $(GUMP_SRC_FILES)
LOCAL_SHARED_LIBRARIES := SDL2_image SDL2_mixer SDL2_net SDL2
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog
include $(BUILD_SHARED_LIBRARY)
My Guess (turns out false):
After writing this question and looking closely to provide you guys the most accurate information as possible about my problem, I noticed that the obj-files that are giving errors are those were I've used a wildcard on folder level as well. Eg: $(ROOT)/*/*.cpp. While these wildcards give no problem: $(ROOT)/Gump/*.cpp. I don't know for sure, but I guess that the wildcards work different on when linking for these different architectures...
Update:
I've tested it again not using wildcards for folders, and the same error about multiple definition appears.
Your list of files is appended every time a new ABI is being built. LOCAL_SRC_FILES is erased through include $(CLEAR_VARS); GUMP_SRC_FILES is redefined each time. But THIRD_PARTY_SRC_FILES only grows longer and longer. This has nothing to do with the wildcards, as you noticed. Simply add line
THIRD_PARTY_SRC_FILES :=
after include $(CLEAR_VARS), and your build will be fine.
Running ndk-build V=1 shows the build commands executed during the process. There I could see the .o files being linked twice. I'm not sure what the reason for that is. I guess it might have been due to the fact that the android makefile in the src/ folder used sources from his parent directory: ../ThirdParty/[morehere].
I fixed it by creating extra makefiles for these third party libraries, so now every library creates a shared library in a .so file. Which gets linked at compile-time. I think this is neater, because changing a makefile requires only that subproject to be recompiled.
I am getting the following errors when I try to perform an NDK build, can anyone help me please?
I did the setup instruction exactly like what are written in "Beginning Android C++ Game Development". every step except the 9th:
"Click the NativeActivity node in the Application Nodes window and click Add once more. Enter the Name as android.app.lib_name and the Value as the LOCAL_MODULE name, which can be found in the Android.mk file in the project’s jni folder."
Errors :
10:44:23 ** Incremental Build of configuration Default for project
HelloDroid ** "C:\ndk\ndk-build.cmd" all Android NDK:
WARNING:jni/Android.mk:HelloDroid-Test: non-system libraries in linker
flags: -lGLESv Android NDK: This is likely to result in
incorrect builds. Try using LOCAL_STATIC_LIBRARIES Android NDK:
or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of
the Android NDK: current module [armeabi] SharedLibrary :
libHelloDroid-Test.so
C:/ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe:
error: cannot find -lGLESv collect2: ld returned 1 exit status
make.exe: * [obj/local/armeabi/libHelloDroid-Test.so] Error 1
10:44:23 Build Finished (took 226ms)
I found the problem.
I just needed to edit the Android.mk
it now looks like this:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hellodroid
LOCAL_SRC_FILES := hellodroid.cpp
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2
LOCAL_STATIC_LIBRARIES := android_native_app_glue
include $(BUILD_SHARED_LIBRARY)
$(call import-module, android/native_app_glue)
As the error states, there is no lib GLESv.
Which version of OpenGL ES are you using, 1 or 2?
The linker flags are -lGLESv1_CM and -lGLESv2, respectively.
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.