How to build shared library from static libraries NDK - android

I have read similar questions to this but none of the answer provided worked.
I want to build a shared library for android to link with JNI,
all libraries on which it depends are static libraries.
I used this to build spatialite and sqlite for android :
https://github.com/geopaparazzi/libjsqlite-spatialite-android/wiki/spatialite-5.0.0.mk .
My makefile for the module looks like this :
include $(CLEAR_VARS)
LOCAL_MODULE := libosm_to_spatialite
LOCAL_C_INCLUDES := \
$(SQLITE_PATH) \
$(SPATIALITE_PATH) \
$(SPATIALITE_PATH)/src/headers \
$(SPATIALITE_PATH)/src/topology \
$(XML2_PATH)/include \
$(XML2_PATH)
LOCAL_SRC_FILES := \
spatialite_osm_overpass.c
LOCAL_STATIC_LIBRARIES := \
libxml2 \
sqlite \
spatialite
include $(BUILD_SHARED_LIBRARY)
The build stops because none of the included header files are found in spatialite_osm_overpass.c.
I have tried to add
APP_MODULES := sqlite spatialite xml2 in my Application.mk
but it doesn't work.
I have also tried to build this library as a static library by setting APP_MODULES != osm_to_spatialite but the .a is not generated.
can somebody check if my code is correct ?
alternatively, how can i generate a .a to link with JNI ?

Related

Why am I not getting static libraries while getting shared libraries built using ndk-build?

I am trying to generate rn-noise static libraries. So far, I am able to generate Shared Libraries. What I am unable to understand is why am I not getting static libraries? Please have a look:
Shared Library
Static Library
Now if I build Static libraries then I get the following things:
My Android.mk is as following:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= rnnoise
RNN_SOURCES := \
$(LOCAL_PATH)/rnnoise-master/src/celt_lpc.c \
$(LOCAL_PATH)/rnnoise-master/src/denoise.c \
$(LOCAL_PATH)/rnnoise-master/src/kiss_fft.c \
$(LOCAL_PATH)/rnnoise-master/src/pitch.c \
$(LOCAL_PATH)/rnnoise-master/src/rnn.c \
$(LOCAL_PATH)/rnnoise-master/src/rnn_data.c \
$(LOCAL_PATH)/rnnoise-master/src/rnn_reader.c \
LOCAL_SRC_FILES := $(RNN_SOURCES) \
com_example_rnnoise_Rnnoise.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/rnnoise-master/include/ \
$(LOCAL_PATH)/rnnoise-master/src/
include $(BUILD_STATIC_LIBRARY)
What is the solution to this problem? Any help will be appreciated.
Thanks.

Resolving Circular Dependency in Android makefile [duplicate]

This question already has an answer here:
Android NDK: how to link multiple 3rd party libraries
(1 answer)
Closed 5 years ago.
We are working on a project where we need to create a shared library from the static libraries. The issues we are facing is the static libraries contains a circular dependency. Following is the sample of my makefile:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Mylib1
LOCAL_SRC_FILES := lib/libMylib1.a
include $(PREBUILT_STATIC_LIBRARY)
....
....
....
LOCAL_MODULE := DisplayDriver
LOCAL_SRC_FILES := \
file1.c \
file2.c \
file3.c
LOCAL_STATIC_LIBRARIES := -Wl,--start-group \
Mylib1 \
Mylib2 \
Mylib3 \
Mylib4 \
-Wl,--end-group
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/examples \
LOCAL_CFLAGS := -x c -DHAVE_STDINT -DHAVE_SETENV -DNDEBUG -c
LOCAL_LDLIBS += -llog
APP_ABI := armeabi-v7a
include $(BUILD_SHARED_LIBRARY)
When I give the ndk-build V=1 I can see in the output that clearly -Wl,--start-group and -Wl,--end-group is removed from the compilation when it is going to create the shared library. So is there any other flags which is obvious and I am missing the same?
I am using NDK R9 on windows 7 64 bit.
It appears that -Wl,--start-group specified in LOCAL_STATIC_LIBRARIES is ignored.
There use to be LOCAL_GROUP_STATIC_LIBRARIES which would group static libraries with -Wl,--start-group and -Wl,--end-group when linking.
Now (ndk-10c) the only relevant variable is LOCAL_WHOLE_STATIC_LIBRARIES which uses the linker flag --whole-archive.
This is generally useful when there are circular dependencies between several static libraries. Note that when used to build a shared library, this will force all object files from your whole static libraries to be added to the final binary. This is not true when generating executables though.
Not exactly the same thing but may solve the dependency problem.
In my project, I've created a dedicated cpp file which explicitly references the problematic symbols.
auto i_reference_you =
{
(void *)MyClass::some_symbol,
(void *)some_other_symbol
};
This works for me because there are only a few symbols. It's nothing elegant but saves me from fighting the build system.

Fatal error, no such file or directory ( eclipse android )

I'm developing a cocos2d-x project, as its universal it works on android and iOS.
I recently added text to speech functionality using flite. In xcode all I do to use flite, is drag in the folder of the headers and c files into my xcode project, and then I can include its headers and use it. No problems there.
However in eclipse I can't get the compiler to see the files, and it keeps bombing out with the fatal error I mentioned. Specifically: fatal error: flite.h no such file or directory.
I've tried to include the folder in the includes section of eclipse under C/C++ general but no luck. I think this may have something to do with my android.mk file, guidance on how to set this up for this purpose would be greatly appreciated. On a side note, my project is set up so that my .cpp and .h files exist elsewhere on my computer and not in my actual project. Likewise for my flite source files. (I did try add them to my project however, out of desperation but the compiler still couldn't find them)
Thanks for your time.
PS: How does one refer to flite, is it a library/framework etc?
Edit
I tried to modify my Android.mk file, to locate the flite headers. My additions are indicated below
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := game_shared
LOCAL_MODULE_FILENAME := libgame
LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp \
../../Classes/CCLabelTTFExtension.cpp \
../../Classes/menuScene.cpp \
../../Classes/text_Parse.cpp \
../../Classes/FileTS.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes/
#my addition
LOCAL_C_INCLUDES += $(LOCAL_PATH)/flite/
dirs := $(shell /flite -type d)
cfilestemp1 := $(shell find /src -type d)
cfilestemp2 := $(shell find $(cfilestemp1) -name *.c)
cfilestemp3 := $(sort $(cfilestemp2))
cfiles := $(subst $(LOCAL_PATH)/,,$(cfilestemp3))
LOCAL_SRC_FILES += \
$(cfiles)
#end my addition
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static cocosdenshion_static cocos_extension_static
include $(BUILD_SHARED_LIBRARY)
$(call import-module,CocosDenshion/android) \
$(call import-module,cocos2dx) \
$(call import-module,extensions)
include $(CLEAR_VARS)
This got me closer, well, gave me different errors. Now the compiler complains of undefined references in my FileTS.cpp file, the file which is using flite in my project. (Note: My flite headers and source files are now added to my project in the jni folder)
The easiest way is to put all the source code into your Classes folder and list the cpp files in LOCAL_SRC_FILES like mainScene.cpp . this will make sure your library get build into your game object files.

Boost Android, ndk-build doesn't create .so / headers can't be found

I've been trying to link boost into my android application following these instructions:
Include Boost C++ library in android
which seems to be pretty concise and sensible. Unfortunately, after days of trying I can't see what I'm doing wrong, as the end result is that ndk-build returns "No such file or Directory" regarding the boost headers I try to include.
After building the boost libraries I needed, I copied them in proj.android/jni/boost/include and proj.android/jni/boost/lib. I then created a directory in jni called boost-build, where I created an Android.mk to handle define the module to link to the libboost_serialization static library (which is the only boost library I'm interested in).
LOCAL_PATH:= $(call my-dir)
# serialization
include $(CLEAR_VARS)
# I'm not sure this is necessary / helpful, but I've tried without it, as well
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include/boost-1_49 \
# EDIT: replaced previous line from this, at Igor's correction: $(LOCAL_PATH)/../include/boost-1_49/boost \
$(LOCAL_PATH)/../include/boost-1_49/boost/archive \
$(LOCAL_PATH)/../include/boost-1_49/boost/serialization
LOCAL_MODULE:= boost_serialization
LOCAL_SRC_FILES:= ../lib/libboost_serialization-gcc-mt-1_49.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/boost-build-includes
include $(PREBUILT_STATIC_LIBRARY)
The android project makefile, proj.android/jni/Android.m:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LDFLAGS= -L$(NDK_ROOT)/sources/crystax/libs/armeabi-v7a/4.6.3 -Lcrystax
LOCAL_CPPFLAGS += -fexceptions
LOCAL_CPPFLAGS += -frtti
LOCAL_MODULE := game_shared
LOCAL_MODULE_FILENAME := libgame
LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp \
../../Classes/TitleScene.cpp \
../../Classes/GameSettings.cpp \
../../Classes/Cutscene.cpp \
../../Classes/HighScoreTable.cpp \
../../Classes/MaskNode.cpp \
../../Classes/MenuResponder.cpp \
../../Classes/HudElementBg.cpp \
../../Classes/OHRCharSelectMenu.cpp \
../../Classes/OHRDifficultySelectMenu.cpp \
../../Classes/Types.cpp \
../../Classes/OHRMainMenu.cpp
# I've tried with / without this variable, as well, with the same result
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \
$(LOCAL_PATH)/../include/boost-1_49 \
# EDIT: replaced previous line from this, at Igor's correction: $(LOCAL_PATH)/../include/boost-1_49/boost \
$(LOCAL_PATH)/../boost/include/boost-1_49/boost/archive \
$(LOCAL_PATH)/../boost/include/boost-1_49/boost/serialization
LOCAL_WHOLE_STATIC_LIBRARIES := boost_serialization cocos2dx_static cocosdenshion_static cocos_extension_static
include $(BUILD_SHARED_LIBRARY)
$(call import-module,CocosDenshion/android) \
$(call import-module,boost-build) \
$(call import-module,cocos2dx)
Now, when I run ndk-build to compile my source, I get the following error:
Compile++ thumb : game_shared <= main.cpp
Compile++ thumb : game_shared <= AppDelegate.cpp
In file included from jni/../../Classes/MapUtils.h:2:0,
from jni/../../Classes/Types.h:3,
from jni/../../Classes/menuresponder.h:2,
from jni/../../Classes/OHRMainMenu.h:2,
from jni/../../Classes/TitleScene.h:10,
from jni/../../Classes/AppDelegate.cpp:6:
jni/../../Classes/BoostUtils.h:2:36: fatal error: boost/archive/tmpdir.hpp: No such file or directory
(BoostUtils.h being a header that simply includes a bunch of serialization-related headers)
#include <boost/archive/tmpdir.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/assume_abstract.hpp>
Now, exactly once tonight, running this generated a bunch of .so's and .a's, include libbost_serialization.so, in proj.android/obj/local. I have not been able to get that to be generated since, despite deleting the /obj directory. Also odd is that, despite what's suggested by the link at the top of this post, a /libs directory is not being created when ndk-build is run. However, I'm not 100% sure that .so even needs to be generated.
So, for the life of me I can't identify the problem here. Any solutions or direction would be much, much appreciated.
Lesson learned: LOCAL_C_INCLUDES actually is a necessary variable, and make sure it's pointing to the right place. In my case, it was just an errant '../' and including the contents of 'boost/', rather than the directory containing boost.
(Also, sleep more, rather than spend hours glancing over these issues.)

libjpeg-turbo for android

I need libjpeg-turbo for android ndk. Did anyone managed to compile it as .a (static) lib?
I have tried a few times, but it gave me a lot of errors only.
Install Android NDK. Following instructions were verified with r8b, older versions may have problems, I don't know.
Get the Android sources for libjpeg-turbo from Benjamin Gaignard:
git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android
In the libjpeg-turbo directory created by git, edit file Android.mk: after line 70, LOCAL_MODULE := libjpeg, add the following:
ifeq ($(notdir $(MAKECMDGOALS)),libjpeg.a)
LOCAL_SRC_FILES += $(libsimd_SOURCES_DIST)
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := dummy
endif
Run ndk-build:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk obj/local/armeabi/libjpeg.a
Profit!
PS: You may want the armeabi-v7a version:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=armeabi-v7a obj/local/armeabi-v7a/libjpeg.a
Or compile for ARM, to improve performance, add to command line:
LOCAL_ARM_MODE=arm
If your target has NEON support, add to command line:
LOCAL_ARM_NEON=true ARCH_ARM_HAVE_NEON=true
UPDATE: to get it work with Android NDK r15 and later, remove all references to libcutils from Android.mk.
This answer expands on Alex Cohn's answer. Full credit goes to him for getting me started. This answer will allow you to build libjpeg-turbo with assembly for ARM (with or without NEON) as well as x86. Compatibility is also provided for MIPS so that you can be a good citizen and build your app for all of the platforms that the r8e version of the Android NDK supports.
I still a relative newbie to actually answering questions, so don't have permissions to include attachments. So I'm going to have to inline a bunch of code. I'm also sure there are better ways to do bits and pieces of the below, so am open to suggestions for improvement.
Getting this all to work was done in six main steps (step two has many sub-steps -- each of which can be found after the main six steps):
Download via git the libjpeg-turbo library containing a set of code and .mk files for Android. I downloaded it from here with git:
git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android
Full credit and thanks must be given to Tom Gall for doing the initial work.
Download YASM (an assembler for x86) and configure the Android build environment to support it. See the set of instructions on configuring YASM for the Android NDK that I am including below the horizontal rule at the end of my Android.mk changes in step 6. Supporting x86 requires that you aren't shy about tweaking the NDK install.
I perhaps could have used the NASM compiler, but was far enough down the YASM path before investigating NASM that I brought the YASM path to completion.
Create the simd/jsmidcfg.inc file. The libjpeg-turbo library provides simd/jsmidcfg.inc.h. It is meant for the pre-processor to take the .h and convert it to a .inc. I'm sure there is a better way for it to happen than what I did. But couldn't get it sorted out due to time pressures. Instead, I manually ran one the gcc that came with Android to create the file using the following command:
C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.4.3\prebuilt\windows-x86_64\bin\i686-linux-android-gcc.exe -E C:\development\thirdparty\libjpeg-turbo\libjpeg-turbo-android-1.2.0\simd\jsimdcfg.inc.h -o C:\development\thirdparty\libjpeg-turbo\libjpeg-turbo-android1.2.0\simd\jsimdcfg.inc
After the pre-processor completed, I had to hand-edit the file to get it into a usable state. I had to select all of the lines above "; -- jpeglib.h" and delete them.
Next, I had to find each of the %defines that started with _cpp_protection_ and duplicate each of those %defines WITHOUT the _cpp_protection_. For example, %define _cpp_protection_RGB_RED 0 became %define RGB_RED 0
For ARM, I wanted my code to dynamically support NEON instructions on hardware that had it, and to fallback to something simpler on hardware that didn't, I modified simd/jsimd_arm.c to dynamically query for the information. I didn't want to have to make that choice when building libjpeg-turbo.
I added the following lines of code:
#ifdef ANDROID
#include <cpufeatures/cpu-features.h>
#endif
and
#ifdef ANDROID
uint64_t cpuFeatures = android_getCpuFeatures();
if (cpuFeatures & ANDROID_CPU_ARM_FEATURE_NEON) {
simd_support |= JSIMD_ARM_NEON;
}
#endif
within the init_simd() method.
Enabling MIPS.
To be a good citizen, I wanted to enable compilation on MIPS. While there isn't any assembler code for MIPS, the code should at least compile and run. To do that, I copied simd/jsimd_arm.c to simd/jsimd_mips.c. I edited the file so that init_simd() set simd_support = 0; I also changed all of the jsimd_can_*() methods to return 0. Finally, I removed the implementation from all of the other methods.
Because I was interested in more than just a build for ARM, I changed the Application.mk file to include the following lines:
APP_ABI := all
APP_OPTIM := release
The APP_OPTIM comes from How to optimize a native code with android-ndk (Speed Optimization)
Within Android.mk, I commented out everything from the "cjpeg" comment block and below. To do a block comment, I followed the advice of How to add multi line comments in makefiles
I next customized the Android.mk file itself so that I could build for all currently supported CPUs (ARM, x86, MIPS). Here is what I ended up with (some code commented out because I wanted a static library -- also to leave the original code in place so I can see what changed). You will most likely have to change (or remove) the addprefix method calls because the file below is customized for my build environment. But other than that, it should work for you.
.
##################################################
### simd ###
##################################################
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#ifeq ($(ARCH_ARM_HAVE_NEON),true)
#LOCAL_CFLAGS += -D__ARM_HAVE_NEON
#endif
# From autoconf-generated Makefile
EXTRA_DIST = simd/nasm_lt.sh simd/jcclrmmx.asm simd/jcclrss2.asm simd/jdclrmmx.asm simd/jdclrss2.asm \
simd/jdmrgmmx.asm simd/jdmrgss2.asm simd/jcclrss2-64.asm simd/jdclrss2-64.asm \
simd/jdmrgss2-64.asm simd/CMakeLists.txt
#libsimd_SOURCES_DIST = simd/jsimd_arm_neon.S \
simd/jsimd_arm.c
libsimd_SOURCES_DIST :=
ifeq ($(TARGET_ARCH),arm)
libsimd_SOURCES_DIST := simd/jsimd_arm_neon.S \
simd/jsimd_arm.c
endif
ifeq ($(TARGET_ARCH),x86)
#libsimd_SOURCES_DIST := simd/jsimd_mips.c
# List of assembly files needed is derived from content within simd/CMakelists.txt
# The Intel Atom supports x86 32-bit assembly. So take those files and leave the
# 64-bit behind.
libsimd_SOURCES_DIST := simd/jsimd_i386.c \
simd/jsimdcpu.asm simd/jccolmmx.asm simd/jcgrammx.asm simd/jdcolmmx.asm simd/jcsammmx.asm simd/jdsammmx.asm \
simd/jdmermmx.asm simd/jcqntmmx.asm simd/jfmmxfst.asm simd/jfmmxint.asm simd/jimmxred.asm simd/jimmxint.asm simd/jimmxfst.asm simd/jcqnt3dn.asm \
simd/jf3dnflt.asm simd/ji3dnflt.asm simd/jcqntsse.asm simd/jfsseflt.asm simd/jisseflt.asm simd/jccolss2.asm simd/jcgrass2.asm simd/jdcolss2.asm \
simd/jcsamss2.asm simd/jdsamss2.asm simd/jdmerss2.asm simd/jcqnts2i.asm simd/jfss2fst.asm simd/jfss2int.asm simd/jiss2red.asm simd/jiss2int.asm \
simd/jiss2fst.asm simd/jcqnts2f.asm simd/jiss2flt.asm
endif
ifeq ($(TARGET_ARCH),mips)
libsimd_SOURCES_DIST := simd/jsimd_mips.c
endif
#LOCAL_SRC_FILES := $(libsimd_SOURCES_DIST)
#LOCAL_SRC_FILES := $(addprefix ../../libjpeg-turbo-android-1.2.0/,$(LOCAL_SRC_FILES))
LOCAL_C_INCLUDES := $(LOCAL_PATH)/simd \
$(LOCAL_PATH)/android
LOCAL_C_INCLUDES := simd android
#LOCAL_C_INCLUDES := $(addprefix ../../libjpeg-turbo-android-1.2.0/,$(LOCAL_C_INCLUDES))
#AM_CFLAGS := -march=armv7-a -mfpu=neon
#AM_CCASFLAGS := -march=armv7-a -mfpu=neon
#LOCAL_MODULE_TAGS := debug
#LOCAL_MODULE := libsimd
#include $(BUILD_STATIC_LIBRARY)
######################################################
### libjpeg.so ##
######################################################
#include $(CLEAR_VARS)
# From autoconf-generated Makefile
libjpeg_SOURCES_DIST = jcapimin.c jcapistd.c jccoefct.c jccolor.c \
jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c \
jcomapi.c jcparam.c jcphuff.c jcprepct.c jcsample.c jctrans.c \
jdapimin.c jdapistd.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c \
jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c \
jdmerge.c jdphuff.c jdpostct.c jdsample.c jdtrans.c jerror.c \
jfdctflt.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c \
jidctred.c jquant1.c jquant2.c jutils.c jmemmgr.c jmemnobs.c \
jaricom.c jcarith.c jdarith.c \
turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c #\
turbojpeg-mapfile
LOCAL_SRC_FILES:= $(libjpeg_SOURCES_DIST) $(libsimd_SOURCES_DIST)
#LOCAL_SRC_FILES:= $(libjpeg_SOURCES_DIST)
LOCAL_SRC_FILES := $(addprefix ../../../libjpeg-turbo-android-1.2.0/,$(LOCAL_SRC_FILES))
#LOCAL_SHARED_LIBRARIES := libcutils
#LOCAL_STATIC_LIBRARIES := libsimd
#LOCAL_C_INCLUDES := $(LOCAL_PATH)
# Include C:/development/android/ide/android-ndk-r8e-windows-x86_64/sources/android
# instead of the lower-level cpufeatures because of how I had to include
# cpu-features.h. It appears as if there is a naming conflict, so I had to
# change how the file was included to avoid naming conflicts.
LOCAL_C_INCLUDES := $(addprefix ../../../libjpeg-turbo-android-1.2.0/,$(LOCAL_C_INCLUDES)) \
C:/development/thirdparty/libjpeg-turbo/libjpeg-turbo-android-1.2.0 \
C:/development/android/ide/android-ndk-r8e-windows-x86_64/sources/android
#LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES)) ./
#LOCAL_C_INCLUDES := $(addprefix $(LOCAL_PATH),$(LOCAL_C_INCLUDES)) $(LOCAL_PATH)../../../libjpeg-turbo-android-1.2.0/
LOCAL_CFLAGS := -DAVOID_TABLES -O3 -fstrict-aliasing -fprefetch-loop-arrays -DANDROID \
-DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_CFLAGS += -DJPEG_LIB_VERSION=80 # I need version 8 because of some of the methods I depend on
LOCAL_YASMFLAGS := -P../../libjpeg-turbo-android-1.2.0/simd/jsimdcfg.inc
#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_STATIC_LIBRARY)
#LOCAL_MODULE_TAGS := debug
#LOCAL_MODULE := libjpeg
LOCAL_MODULE := jpeg-turbo
#include $(BUILD_SHARED_LIBRARY)
#LOCAL_STATIC_LIBRARIES := cpufeatures
include $(BUILD_STATIC_LIBRARY)
# We reference android/cpufeatures in the Android.mk file of our main app, so
# we don't need to do anything here.
#$(call import-module,android/cpufeatures)
Some of the source code that ships with libjpeg-turbo is in .asm format. That is, it needs to be compiled with the NASM assembler. As it ships, the Android NDK doesn't have support for it.
To get .asm support working with NDK, I followed the rough outline presented here: http://software.intel.com/en-us/articles/using-yasm-compiler-on-android-ndkbuild
Here are a set of more detailed instructions. Within android-ndk-r8\build\core, the following things need to occur:
build-binary.mk:
all_source_extensions := .c .s .S $(LOCAL_CPP_EXTENSION) => all_source_extensions := .c .s .asm .S $(LOCAL_CPP_EXTENSION)
For me, the above was on line 228.
After the line that starts with: "# Build the sources to object files" you will see several foreach loops. Add one like this (I added it on line 272):
$(foreach src,$(filter %.asm,$(LOCAL_SRC_FILES)), $(call compile-asm-source,$(src),$(call get-object-name,$(src))))
definitions.mk:
Create a new compile-asm-source to match the new entry we added within the new for loop above. We also have to add a new define within the make file. I added the following. It is a combination and simplification of the various rules used to build .c files. We need a different set of options when using yasm that necessitate these changes.
define ev-compile-asm-source
_SRC:=$$(LOCAL_PATH)/$(1)
_OBJ:=$$(LOCAL_OBJS_DIR)/$(2)
_FLAGS := -f elf -DELF -DPIC $$(LOCAL_YASMFLAGS)
_TEXT := "Compile $$(call get-src-file-text,$1)"
_CC := $$(NDK_CCACHE) $$(TARGET_ASM)
$$(_OBJ): PRIVATE_SRC := $$(_SRC)
$$(_OBJ): PRIVATE_OBJ := $$(_OBJ)
$$(_OBJ): PRIVATE_DEPS := $$(call host-path,$$(_OBJ).d)
$$(_OBJ): PRIVATE_MODULE := $$(LOCAL_MODULE)
$$(_OBJ): PRIVATE_TEXT := "$$(_TEXT)"
$$(_OBJ): PRIVATE_CC := $$(_CC)
$$(_OBJ): PRIVATE_CFLAGS := $$(_FLAGS)
ifeq ($$(LOCAL_SHORT_COMMANDS),true)
_OPTIONS_LISTFILE := $$(_OBJ).cflags
$$(_OBJ): $$(call generate-list-file,$$(_FLAGS),$$(_OPTIONS_LISTFILE))
$$(_OBJ): PRIVATE_CFLAGS := #$$(call host-path,$$(_OPTIONS_LISTFILE))
$$(_OBJ): $$(_OPTIONS_LISTFILE)
endif
$$(call generate-file-dir,$$(_OBJ))
$$(_OBJ): $$(_SRC) $$(LOCAL_MAKEFILE) $$(NDK_APP_APPLICATION_MK) $$(NDK_DEPENDENCIES_CONVERTER)
#$$(HOST_ECHO) "$$(PRIVATE_TEXT) : $$(PRIVATE_MODULE) <= $$(notdir $$(PRIVATE_SRC))"
$$(hide) $$(PRIVATE_CC) $$(PRIVATE_CFLAGS) $$(call host-path,$$(PRIVATE_SRC)) -o $$(call host-path,$$(PRIVATE_OBJ)) \
$$(call cmd-convert-deps,$$(PRIVATE_DEPS))
endef
compile-asm-source = $(eval $(call ev-compile-asm-source,$1,$2))
Search for the line that starts with 'compile-s-source'. I found it at line 1491. The new compile-asm-source can go right below that.
Next, search for the line that starts with "get-object-name". I found it at line 1270. Add ".asm" to the inner for-loop. Put it together with the .c, .s, and .S
import-locals.mk:
Add the following line below the LOCAL_CFLAGS and the LOCAL_CPPFLAGS line
LOCAL_YASMFLAGS := $(LOCAL_CFLAGS) $(strip $(LOCAL_YASMFLAGS))
default-build-commands.mk:
Add the following line anywhere in the file. I put mine under the TARGET_CXX section and above the TARGET_LD section.
TARGET_ASM = $(TOOLCHAIN_PREFIX)yasm
Download and copy yasm.exe to the build folders:
Download a copy of YASM from here: http://yasm.tortall.net/
I have the Win64 version of the NDK, so downloaded the Win64 version of YASM. If you have the Win32 version of the NDS, download th Win32 version of YASM.
You should just get the .exe. Copy it to the following directories as yasm.exe. If you have any other toolchain versions, copy it to those directories as well:
C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.4.3\prebuilt\windows-x86_64\i686-linux-android\bin
C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.6\prebuilt\windows-x86_64\i686-linux-android\bin
C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.7\prebuilt\windows-x86_64\i686-linux-android\bin
Then, copy the file again to the directories below as i686-linux-android-yasm.exe. And as above, if you have any other toolchain versions, copy it to those directories as well:
C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.4.3\prebuilt\windows-x86_64\bin
C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.6\prebuilt\windows-x86_64\bin
C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.7\prebuilt\windows-x86_64\bin
Thanks Alex Cohn and answered Dec for share;
This answer expands on Alex Cohn's answer & answered Dec's answer;
I'm use jpeg turbo 1.3.9, ndk-r9d, about yasm.exe, the ndk-r9d is contained, on after did answered Dec's step 3, I had one error in simd/jsimdext.inc line:182 "%define EXTN(name) _ %+ name ; foo() -> _foo"; change it to "%define EXTN(name) name"; then ok, this problem had fixed;
this is my Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CFLAGS += -D__ARM_HAVE_NEON
#ifeq ($(ARCH_ARM_HAVE_NEON),true)
#LOCAL_CFLAGS += -D__ARM_HAVE_NEON
#endif
# From autoconf-generated Makefile
EXTRA_DIST = nasm_lt.sh CMakeLists.txt \
jccolext-mmx.asm jcgryext-mmx.asm jdcolext-mmx.asm jdmrgext-mmx.asm \
jccolext-sse2.asm jcgryext-sse2.asm jdcolext-sse2.asm jdmrgext-sse2.asm \
jccolext-sse2-64.asm jcgryext-sse2-64.asm jdcolext-sse2-64.asm \
jdmrgext-sse2-64.asm
ifeq ($(TARGET_ARCH),arm)
libsimd_SOURCES_DIST := simd/jsimd_arm_neon.S \
simd/jsimd_arm.c
AM_CFLAGS := -march=armv7-a -mfpu=neon
AM_CCASFLAGS := -march=armv7-a -mfpu=neon
endif
ifeq ($(TARGET_ARCH),x86)
# List of assembly files needed is derived from content within simd/CMakelists.txt
# The Intel Atom supports x86 32-bit assembly. So take those files and leave the
# 64-bit behind.
#libsimd_SOURCES_DIST := simd/jsimd_i386.c \
simd/jsimdcpu.asm \
simd/jfdctflt-3dn.asm \
simd/jidctflt-3dn.asm \
simd/jquant-3dn.asm \
simd/jccolor-mmx.asm \
simd/jcgray-mmx.asm \
simd/jcsample-mmx.asm \
simd/jdcolor-mmx.asm \
simd/jdmerge-mmx.asm \
simd/jdsample-mmx.asm \
simd/jfdctfst-mmx.asm \
simd/jfdctint-mmx.asm \
simd/jidctfst-mmx.asm \
simd/jidctint-mmx.asm \
simd/jidctred-mmx.asm \
simd/jquant-mmx.asm \
simd/jfdctflt-sse.asm \
simd/jidctflt-sse.asm \
simd/jquant-sse.asm \
simd/jccolor-sse2.asm \
simd/jcgray-sse2.asm \
simd/jcsample-sse2.asm \
simd/jdcolor-sse2.asm \
simd/jdmerge-sse2.asm \
simd/jdsample-sse2.asm \
simd/jfdctfst-sse2.asm \
simd/jfdctint-sse2.asm \
simd/jidctflt-sse2.asm \
simd/jidctfst-sse2.asm \
simd/jidctint-sse2.asm \
simd/jidctred-sse2.asm \
simd/jquantf-sse2.asm \
simd/jquanti-sse2.asm
libsimd_SOURCES_DIST := simd/jsimd_i386.c simd/jsimd.h simd/jsimdcfg.inc.h simd/jsimdext.inc \
simd/jcolsamp.inc simd/jdct.inc simd/jsimdcpu.asm \
simd/jfdctflt-3dn.asm simd/jidctflt-3dn.asm simd/jquant-3dn.asm \
simd/jccolor-mmx.asm simd/jcgray-mmx.asm simd/jcsample-mmx.asm \
simd/jdcolor-mmx.asm simd/jdmerge-mmx.asm simd/jdsample-mmx.asm \
simd/jfdctfst-mmx.asm simd/jfdctint-mmx.asm simd/jidctfst-mmx.asm \
simd/jidctint-mmx.asm simd/jidctred-mmx.asm simd/jquant-mmx.asm \
simd/jfdctflt-sse.asm simd/jidctflt-sse.asm simd/jquant-sse.asm \
simd/jccolor-sse2.asm simd/jcgray-sse2.asm simd/jcsample-sse2.asm \
simd/jdcolor-sse2.asm simd/jdmerge-sse2.asm simd/jdsample-sse2.asm \
simd/jfdctfst-sse2.asm simd/jfdctint-sse2.asm simd/jidctflt-sse2.asm \
simd/jidctfst-sse2.asm simd/jidctint-sse2.asm simd/jidctred-sse2.asm \
simd/jquantf-sse2.asm simd/jquanti-sse2.asm
endif
ifeq ($(TARGET_ARCH),mips)
libsimd_SOURCES_DIST := simd/jsimd_mips.c
endif
LOCAL_C_INCLUDES := $(LOCAL_PATH)/simd \
$(LOCAL_PATH)/android
LOCAL_SRC_FILES:= $(libsimd_SOURCES_DIST)
LOCAL_CFLAGS := -DAVOID_TABLES -O3 -fstrict-aliasing -fprefetch-loop-arrays -DANDROID \
-DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_CFLAGS += -DJPEG_LIB_VERSION=80 # I need version 8 because of some of the methods I depend on
$(warning "libsimd")
LOCAL_MODULE := libsimd
LOCAL_MODULE_FILENAME := libsimd
include $(BUILD_STATIC_LIBRARY)
######################################################
### libjpeg.so ##
######################################################
#include $(CLEAR_VARS)
# From autoconf-generated Makefile
libjpeg_SOURCES_DIST = jcapimin.c jcapistd.c jccoefct.c jccolor.c \
jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c \
jcomapi.c jcparam.c jcphuff.c jcprepct.c jcsample.c jctrans.c \
jdapimin.c jdapistd.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c \
jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c \
jdmerge.c jdphuff.c jdpostct.c jdsample.c jdtrans.c jerror.c \
jfdctflt.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c \
jidctred.c jquant1.c jquant2.c jutils.c jmemmgr.c jmemnobs.c \
jaricom.c jcarith.c jdarith.c \
turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c \
turbojpeg-mapfile
LOCAL_SRC_FILES:= $(libjpeg_SOURCES_DIST)
LOCAL_SHARED_LIBRARIES += libcutils
LOCAL_STATIC_LIBRARIES += libsimd
LOCAL_C_INCLUDES := $(LOCAL_PATH)
$(warning "libjpeg")
LOCAL_CFLAGS := -DAVOID_TABLES -O3 -fstrict-aliasing -fprefetch-loop-arrays -DANDROID \
-DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_CFLAGS += -DJPEG_LIB_VERSION=80 # I need version 8 because of some of the methods I depend on
#D:\android-ndk-r9d\toolchains\x86-4.8\prebuilt\windows-x86_64\bin\i686-linux-android-gcc.exe -E D:\WORKSPACE\MINE\libjpeg_turbo_1.3.9_multi_platform\jni\simd\jsimdcfg.inc.h -o D:\WORKSPACE\MINE\libjpeg_turbo_1.3.9_multi_platform\jni\simd\jsimdcfg.inc
LOCAL_MODULE := libjpeg
LOCAL_MODULE_FILENAME:=libjpeg
LOCAL_STATIC_LIBRARIES += cpufeatures
include $(BUILD_STATIC_LIBRARY)
For anyone trying to build the official repo version, I had success using the patch attached here: libjpeg-turbo cross-compile to Android fails.
Then, depending on whether you're compiling for 32-bit or 64-bit:
export CFLAGS="-DSIZEOF_SIZE_T=4"
or
export CFLAGS="-DSIZEOF_SIZE_T=4"
And run cmake with -DWITH_SIMD=FALSE -DCMAKE_TOOLCHAIN_FILE=your_toolchain_file.
Of course, I'm aware that disabling SIMD is not ideal, but at least I managed to get a build I can start using. Hopefully, the buildsystem's NEON SIMD support will get fixed, in the future. Using ./configure also failed to build the correct SIMD for ARM.
Incidentally, I wish folks would contribute fixes to the main repo, rather than simply forking it. It's been 2 years since the last change to the repo cited in alex-cohn's answer.

Categories

Resources