I am trying to use the png quantization library at pngquant.org/lib in my Android project using the NDK r10 (64bit) on OS X.
I am making progress in compiling the library. The problem I have now is that the size_t type cannot be resolved. I tried including the following folder:
LOCAL_C_INCLUDES := $(NDK_TOOLCHAIN)/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9/include
but that does not help.
I would be really interested in an empty working Android project with pngquant included.
Any help is really appreciated.
NB sorry for changing the question, but the original question I asked had some incorrect facts in it.
I don't have enough information to directly solve your specific problem, are you trying to use the standalone toolchain ?
When building for Android, since you have more than one architecture to target and the toolchain is a bit complex, it's better to use the ndk-build script from the NDK.
I've made a project here that you can integrate to your Android project directory: https://github.com/android-native-libraries/pngquant-android
The original library is using configure script but instead of extending these I've rewritten NDK Makefiles to directly compile all the lib sources, with the same cflags (openmp, sse...)
Android.mk:
LOCAL_PATH := $(call my-dir)
SRC_PATH := pngquant/lib
include $(CLEAR_VARS)
LOCAL_MODULE := imagequant
LOCAL_SRC_FILES := \
$(SRC_PATH)/blur.c \
$(SRC_PATH)/libimagequant.c \
$(SRC_PATH)/mediancut.c \
$(SRC_PATH)/mempool.c \
$(SRC_PATH)/nearest.c \
$(SRC_PATH)/pam.c \
$(SRC_PATH)/viter.c
LOCAL_C_INCLUDES := pngquant/lib
LOCAL_CFLAGS += -O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -Wall -std=c99 -fopenmp
LOCAL_LDFLAGS += -fopenmp
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_CFLAGS += -mtune=atom -msse -mfpmath=sse -mssse3 -DUSE_SSE=1
endif
include $(BUILD_SHARED_LIBRARY)
You can extend this Android.mk file to add your own native library with your sources, that are using libimagequant:
include $(CLEAR_VARS)
LOCAL_MODULE := yourlib
LOCAL_SRC_FILES := yoursources.c
LOCAL_C_INCLUDES := pngquant/lib
LOCAL_SHARED_LIBRARIES := imagequant
LOCAL_CFLAGS += -O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -Wall -std=c99 -fopenmp
LOCAL_LDFLAGS += -fopenmp
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_CFLAGS += -mtune=atom -msse -mfpmath=sse -mssse3 -DUSE_SSE=1
endif
include $(BUILD_SHARED_LIBRARY)
If you just want to use this library with default settings, I've made a simple Android library that may suit your purposes.
In your build.gradle:
dependencies {
compile 'com.ndahlquist:pngquant-android:0.2'
}
In your Android app:
File inputPngFile = getYourPng();
File outputPngFile = getOutputFile()
new LibPngQuant().pngQuantFile(inputFile, outputFile);
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.
am compiling android ndk project but couldn't get it successfully done. It says no such file or directory found for Log header file at main.cpp file. I'm new to android ndk please help.
here is my android.mk file.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := user
LOCAL_ARM_MODE := arm
# This is the target being built.
LOCAL_MODULE := libemu
# All of the source files that we will compile.
LOCAL_SRC_FILES := \
ticks.c \
main.cpp \
emulator.cpp
# All of the shared libraries we link against.
LOCAL_SHARED_LIBRARIES := \
libdl \
libnativehelper \
libutils
# Static libraries.
LOCAL_STATIC_LIBRARIES :=
# Also need the JNI headers.
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
# Special compiler flags.
LOCAL_CFLAGS += -O3 -fvisibility=hidden
# Don't prelink this library. For more efficient code, you may want
# to add this library to the prelink map and set this to true. However,
# it's difficult to do this for applications that are not supplied as
# part of a system image.
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
here is the log
"Compile++ arm : emu <= main.cpp
D:/EclipseWorkspace/NineTendo//jni/main.cpp:2:23: fatal error: utils/Log.h: No such file or directory
compilation terminated.
make: *** [D:/EclipseWorkspace/NineTendo//obj/local/armeabi/objs/emu/main.o] Error 1
any help would be much appreciated.
Thanks
This error started to show up in NDK version R9x. You need to declare the API version number in your Application.mk file. Here's how it looks to define a minimum API level of 8:
APP_PLATFORM := android-8
The Application.mk file should live alongside your Android.mk file in the JNI directory. Here's a sample from one of my projects:
APP_ABI := armeabi armeabi-v7a x86
APP_CFLAGS += -O2
LOCAL_ARM_MODE := arm
APP_PLATFORM := android-8
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.
I am trying to build an android application that calls into a C++ backend. This backend uses ZeroMQ for messaging. Per the android build page on the ZeroMQ guide, I have built a native toolchain of ndk version 6 and used that to (successfully) build ZeroMQ.
However, when I build my own .so with the JNI implementations, I can't seem to make everything load properly. Specifically, if I call System.LoadLibrary("zmq"), this completes successfully, but if I then call *System.LoadLibrary("my_lib")* I always get an UnsatisfiedLinkError complaining that:
Cannot load library reloc_library[1244]: 29 cannot locate zmq_msg_init'...
The libmy_lib.so has been generated several different ways, each with no success. After generating it, I always copies libmy_lib.so (as well as libzmq.so) to my android project's folder: libs/armeabi/.
# Compile all object files - this part was done for all options
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -fpic -c Client_Events.cpp \
Client Wrapper.cpp jni.cpp -I /opt/android-root/include/ -I /my/project/specific/stuff
# Option 1 - Don't link the lib in at all
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o
# Option 2 - Link ZeroMQ in statically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
libzmq.a libstdc++.a -Wl,--whole-archive
# Option 3 - Explicitly link ZeroMQ in dynamically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
-L /opt/android-root/lib/ -lzmq
With each of these options I tried both explicitly calling System.LoadLibrary("zmq") before loading my own library and not. Nothing varied the results. Using nm confirms that, at least in the case of option #2, the missing symbol *zmq_msg_init* is indeed present in libmy_lib.so.
Any ideas as to why it cannot find the ZeroMQ symbols that are linked in?
I just learnt how to compile a 2nd library and link it to my main library in android ndk. Let me see if I am of any use to you.
The following is how I create my 2nd library (In my case, I build bullet physics library and the irrlicht rendering engine as 2 separate libraries for my game).
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := HEADER FILES
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := SRC FILES
LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -ldl -llog
include $(BUILD_SHARED_LIBRARY)
Then copy your libxxxx.so (In my case, libbullet.so and libirrlicht.so) to your jni folder. And in your main library .mk file add the following.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for bullet)
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := libbullet.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for irrlicht)
LOCAL_MODULE := irrlicht
LOCAL_SRC_FILES := libirrlicht.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for bullet + includes for irrlicht + includes for main code)
LOCAL_SRC_FILES := main code src files
LOCAL_MODULE := gamescript
LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -lOpenSLES -landroid -ldl -llog
LOCAL_SHARED_LIBRARIES := bullet irrlicht
include $(BUILD_SHARED_LIBRARY)
And now, add all the libraries to your java code in right order.
System.loadLibrary("bullet");
System.loadLibrary("irrlicht");
System.loadLibrary("gamescript");