I'm trying to build and link freeimage to an android project. I'm close but I'm tripping up on some linker errors from that library.
I'm using this repo: https://github.com/jamcar23/FreeImage-Android/blob/master/jni/freeimage/Android.mk
Freeimage uses the internal NDK library 'cpufeatures' to use xeon chipset features. In the project's 'android.mk', there's a reference to the cpufeatures library:
LOCAL_STATIC_LIBRARIES := cpufeatures
and my library, which statically links to this one, also includes cpufeatures in its LOCAL_STATIC_LIBRARIES statement in that project's android.mk:
LOCAL_STATIC_LIBRARIES := tinyxml freetype2 bullet freeimage cpufeatures
also in my android.mk, I link freeimage like this:
#####FREEIMAGE_LIBRARY_DECLARATION##########
include $(CLEAR_VARS)
LOCAL_PATH = $(TPLIBROOT)/FreeImage-Android
LOCAL_MODULE := freeimage
LOCAL_EXPORT_C_INCLUDES := include
LOCAL_SRC_FILES := obj/local/$(TARGET_ARCH_ABI)/libFreeImage.a
include $(PREBUILT_STATIC_LIBRARY)
###############################################
which, taking note of a previous question I had about the NDK, should take care of specific architectures (I've build freeimage using all available architectures)
freeimage .a and .so libraries appear to build fine but on linking to my library when building the .so, I get this error:
[armeabi-v7a] SharedLibrary : libAnthracite.so
jni/freeimage/Source/LibWebP/./src/dsp/dsp.cpu.c:108: error: undefined reference to 'android_getCpuFamily'
jni/freeimage/Source/LibWebP/./src/dsp/dsp.cpu.c:109: error: undefined reference to 'android_getCpuFeatures'
jni/freeimage/Source/LibWebP/./src/dsp/dsp.dec.c:745: error: undefined reference to 'VP8DspInitNEON'
which is odd as both libraries do link cpufeatures, so it really ought to be there.
I'm declaring
APP_PLATFORM := android-14
APP_STL := gnustl_static
in the application.mk files for both projects.
Also, I've tried placing 'LOCAL_STATIC_LIBRARIES' in different positions in the files and linking libraries in different orders, although that's just guesswork.
Does anybody know what might be causing these linker errors?
Please follow the official guide to add cpu-features. TL;NR: add $(call import-module,android/cpufeatures) to your Android.mk.
I finally got it to work by ensuring that all of my 'application.mk' files for all four of the third party libraries I was using shared a common base file that looks like this:
APP_PLATFORM := android-15
APP_STL := c++_static
APP_ABI := all
APP_OPTIM := release
APP_SHORT_COMMANDS := true
Which makes keeping them in line easier, ensuring they're all built against the same libraries.
Also, I changed the STL implementation from 'gnustl_static' to 'c++_static'
Related
I have an Android project written in C++ and have a problem in linking phase. The code is put in some static libraries which should be linked together.
I have found a lot of questions and answers on the net about this topic and most of them suggest to put my libraries to LOCAL_STATIC_LIBRARIES in the Android.mk file. But, if I do this, I found the content of LOCAL_STATIC_LIBRARIES is simply ignored: my libraries are not linked, and adding any dummy text here does not generate any error or warning message.
I tried it this way:
LOCAL_STATIC_LIBRARIES := MyLib.a
or with full path:
LOCAL_STATIC_LIBRARIES := $(LOCAL_PATH)/MyLib.a
none of them worked.
If I put my static libraries to LOCAL_LDLIBS then it is linked, but I got a warning message about non-system libraries are used, and probably the build will be wrong.
The content of my Android.mk file is:
LOCAL_LDLIBS := $(LOCAL_PATH)/MyLib.a ...
and I got this message:
Android NDK: WARNING:jni/Android.mk:myapp: non-system libraries in linker flags: jni/MyLib.a
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
I could not find how to use LOCAL_STATIC_LIBRARIES right way, please help me!
I have android-ndk-r9 and android-sdk_r22.2.1 on a OpenSuSE x86 and using target=android-18
See JBL's answer here.
The LOCAL_STATIC_LIBRARIES variable does not work that way. First you need a section that defines the library you want to include:
include $(CLEAR_VARS)
LOCAL_PATH = .
LOCAL_MODULE := curl
LOCAL_EXPORT_C_INCLUDES := ../curl/include
LOCAL_SRC_FILES := ../curl/lib/libcurl.a
include $(PREBUILT_STATIC_LIBRARY)
THEN, you can include it using
include $(CLEAR_VARS)
LOCAL_MODULE = mylib
CFLAGS = ...
...
LOCAL_STATIC_LIBRARIES = curl
include $(BUILD_STATIC_LIBRARY)
Most probably the problem lies in that you are giving the extension of the library:
LOCAL_STATIC_LIBRARIES := MyLib.a
I think, it should be written as:
LOCAL_STATIC_LIBRARIES := MyLib
How can I specify shared libraries to load in the Android.mk when compiling with ndk-build ?
Edit: This is my Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := lib-crypto
LOCAL_SRC_FILES := libcrypto.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := tema1
LOCAL_SRC_FILES := tema1.c
LOCAL_SHARED_LIBRARIES := lib-crypto
LOCAL_C_INCLUDES := /home/aleksei/openSSL0.9.8/include
include $(BUILD_EXECUTABLE)
libcrypto.so is the library that I have built for android. I want to make a program using it. Now it gives me this error:
Install : libcrypto.so => libs/armeabi/libcrypto.so
Executable : tema1
./obj/local/armeabi/libcrypto.so: undefined reference to `dladdr'
collect2: ld returned 1 exit status
make: *** [obj/local/armeabi/tema1] Error 1
PREBUILT_SHARED_LIBRARY
Points to a build script used to specify a prebuilt shared library.
Unlike BUILD_SHARED_LIBRARY and BUILD_STATIC_LIBRARY, the value
of LOCAL_SRC_FILES must be a single path to a prebuilt shared
library (e.g. foo/libfoo.so), instead of a source file.
You can reference the prebuilt library in another module using
the LOCAL_PREBUILTS variable (see docs/PREBUILTS.html for more
information).
read more from http://source-android.frandroid.com/ndk/docs/ANDROID-MK.html
Show me what you have done till yet and where you facing problem.?
I had the same problem. To fix it, I did the following:
In the same directory as your Android.mk file, create a file named Application.mk
Add the following line of code into Application.mk:
"APP_PLATFORM := android-8"
If you already have an Application.mk file, just add the code in step 2 to the existing file. Now call ndk-build and see if it links. ndk-build may be compiling with an old version of libdl which does not have dladdr(). The code in step 2 will cause ndk-build to use an updated libdl which has dladdr().
I have a program I am porting that links together multiple libraries when creating the executable. I have built all those libraries using the stand alone toolchain and using the standalone toolchain I am able to create an executable that works on an android device. So, it seems like the libraries I have built are functional. Now I am trying to incorporate those libraries with an app. So, in my android.mk I have something like this:
LOCAL_PATH := $(call my-dir)
ROOT_PATH := $(LOCAL_PATH)
include $(call all-subdir-makefiles)
include $(CLEAR_VARS)
LOCAL_PATH = $(ROOT_PATH)
LOCAL_MODULE := test-libs
LOCAL_STATIC_LIBRARIES := staticA
LOCAL_SHARED_LIBRARIES := sharedA sharedB sharedC sharedD
LOCAL_SRC_FILES := test-libs.c
include $(BUILD_SHARED_LIBRARY)
For each of the libraries, I have a Android.mk like this
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sharedA
LOCAL_SRC_FILES := sharedA.so
include $(PREBUILT_SHARED_LIBRARY)
When I then build my project (in eclipse), I get this:
C:/ndk/android-ndk-r7b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.4.3/libgcc.a(unwind-arm.o): In function `__gnu_unwind_pr_common':
/cygdrive/c/ndk/android-ndk-r7b/build/core/build-binary.mk:314: recipe for target `obj/local/armeabi/libtest-libs.so' failed
/tmp/ndk-digit/src/build/../gcc/gcc-4.4.3/libgcc/../gcc/config/arm/unwind-arm.c:1237: undefined reference to `__cxa_call_unexpected'
Any thoughts on what is going wrong?
Also, the static library and one of the shared libraries have no dependencies on anything and if I only include them all is cool. One of my shared libraries only had a dependency on the static library. If I only include those, but when I include the others, which have dependencies on other shared libraries, this problem occurs.
Update 1: Ok it appears to be because the APP_STL setting in my Application.mk was being ignored. All I have in my Application.mk is:
APP_STL := gnustl_shared
If I copy over the libgnustl_shared.so and treat it like another prebuilt shared lib, my problem is gone. Any idea why the APP_STL is not working properly. Note, I could have screwed something up. I just upgraded to using 7b. Using gnustl_shared used to work for me with other apps. Rolling back to 7 doesn't fix it. I think I have messed something up in Eclipse. I use Eclipse (windows) with sequoyah.
It looks like the linker is giving you an error. What you should do is the following:
Add a LOCAL_LDLIBS under your LOCAL_MODULE := test-libs. Here you need to include all the libraries you link against when you compile your pre-compiled libraries. So for example:
LOCAL_LDLIBS := -lgnustl_shared -lgcc -llog -landroid -lstdc++
Basically you need to identify what library contains the function __cxa_call_unexpected. A quick google shows that it's probably in libstdc++. Make sure that you also link with this library when creating your pre-compiled libraries.
I'm thinking it might have something to do with exceptions support.
Are you using exceptions in your code and if so are you compiling with a runtime library that supports exceptions? (and compiling with exceptions on)?.
There is more on this in the CPLUSPLUS-SUPPORT and STANDALONE-TOOLCHAIN files in the ndk docs.
I've observed a similar problem when one of my projects which contains only C source files (*.c) references another project that contains a c++ file(*.cpp). Application.mk files for both projects had APP_STL := gnustl_shared in them. The ndk version is ndk7e.
The solution was adding an empty C++ file (dummy.cpp) to the project that contained only .c files. Supposedly ndk understood that this project should be linked against the gnustl_shared and the build succeeded.
I compiled Sox et al with NDK. So, I have all Android-friendly shared libs.
I made a simple test file which calls a sox function.
NDK build tells me:
undefined reference to `sox_open_read'
sox_open_read is defined in sox.h. I know it's finding sox.h because it gives me a warning about that file:
In file included from (...)/sox/sox.h:19
So maybe it wants to find sox_open_read in the actual libsox.so. Well, I've tried about a 100 different ways to tell it where the sox shared lib is e.g.
LOCAL_SHARED_LIBRARY := sox
LOCAL_LDLIBS := -L$(LOCAL_PATH_FULL)/jni/libs/libsox.so
However, It will work if I specify Sox as a static library:
#LOCAL_SHARED_LIBRARY := sox
LOCAL_STATIC_LIBRARIES := sox
LOCAL_LDLIBS := -L$(LOCAL_PATH_FULL)/jni/libs/libsox.so
It's my understanding that I don't want to staticly link to the sox lib - I want to dynamically link to it.
You should define libsox.so as a prebuilt library. Create a makefile as the following and put your prebuilt libsox.so in the same directory with this makefile. After that, you can use libsox same as you've rebuilt it. Don't forget to include this makefile into your build.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libsox
LOCAL_SRC_FILES := libsox.so
include $(PREBUILT_SHARED_LIBRARY)
I'm trying to compile a static library to use on Android but I can't figure out how to compile it. The library uses standard libraries (stdio.h etc...) and libxml2.
I am trying to compile using arm-eabi-gcc but I get the following error:
/cygdrive/c/android-ndk-r4/build/platforms/android-8/arch-x86/usr/include/asm/posix_types.h:15:28: error: posix_types_64.h: No such file or directory
How do I get this to work?
As I understand it, the correct method is to use ndk-build and not invoking the compiler directly.
In Android.mk you need to specify a module for each static library you want to compile, and then specify that your shared library should use it.
Example of a modified Android.mk file of the hello-jni sample project:
LOCAL_PATH := $(call my-dir)
# Define vars for library that will be build statically.
include $(CLEAR_VARS)
LOCAL_MODULE := <module_name>
LOCAL_C_INCLUDES := <header_files_path>
LOCAL_SRC_FILES := <list_of_src_files>
# Optional compiler flags.
LOCAL_LDLIBS = -lz -lm
LOCAL_CFLAGS = -Wall -pedantic -std=c99 -g
include $(BUILD_STATIC_LIBRARY)
# First lib, which will be built statically.
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_STATIC_LIBRARIES := <module_name>
LOCAL_C_INCLUDES := <header_files_path>
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
If you want control over which modules to compile when you run ndk-build you can create create a Application.mk file (in the same directory as Android.mk) and list all the modules as in the following example:
APP_MODULES := <module_name_1> <module_name_2> ... <module_name_n>
In response to
Can you generate a static library (.a file) without a shared library
that uses it?
(which really should have been its own question), the answer is yes.
By default, the NDK will only build executables and shared libraries (with their dependencies of course). You can, however, force the NDK to build a standalone static library by explicitly referencing it in your Application.mk.
Assuming your static library module is LOCAL_MODULE := libXYZ, add the following line to Application.mk (creating the file in the same folder as your Android.mk if it doesn't exist):
APP_MODULES := XYZ
Note the the APP_MODULES value does not include the lib prefix included in your static library module name.
Alternatively, if you don't want to create an Application.mk, you can specify the value on the command line: ndk-build APP_MODULES=XYZ
A cool trick: if you have an Android.mk file, you can change the build type from:
include $(BUILD_SHARED_LIBRARY)
to
include $(BUILD_STATIC_LIBRARY)
and .a libraries will be output to the obj/ folder into their respective architectures when you ndk-build the library.