20

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.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
KoVadim
  • 707
  • 1
  • 7
  • 22
  • If you give me "-", please explain "why". – KoVadim Sep 04 '12 at 09:43
  • You should probably explain what exactly you did that did not reproduce the results reported, among other sources, here on stackoverflow: http://stackoverflow.com/questions/9067172/integration-or-build-instructions-for-libjpeg-turbo-on-android – Alex Cohn Sep 04 '12 at 21:31
  • 1
    1) the link https://github.com/psquare/libtjpeg does not exists 2) this https://wiki.linaro.org/BenjaminGaignard/libjpeg-turboAndSkia is for replacing ant have to be compiled in android source tree. 3) Do you want to see a lot of errors line? – KoVadim Sep 05 '12 at 06:49
  • 1
    It's true that Benjamin's blog explains how to replace the built-in jpeg library with libjpeg-turbo in Android platform. But to build a standalone library, it's enough to download the sources (`git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android`) and run **ndk-build** in the **libjpeg-turbo** directory created by git. Here is my command line: `NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=armeabi-v7a`. This results in a shared lib, though. I will post the command line for a static lib as an answer – Alex Cohn Sep 06 '12 at 07:44
  • Looking to building it as a share lib and doing as @AlexCohn mentioned results in an error for me: `In file included from ./jccolor.c:118:0: ./jccolext.c:29:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'static' ./jccolext.c:86:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'static'` (and in a bunch of other lines as well) – Roberto Andrade May 05 '15 at 01:18
  • Fixed my own issue by upgrading ndk from `r8d` to `r10d` – Roberto Andrade May 05 '15 at 11:18
  • Did anyone manage to figure out how to compile the JNI portion of it as part of the NDK build so one may use the .java/.class bridge directly from Java classes? When I compile directly via ndk all I get is the `libjpeg.so` so wondering how the wrapper `turbo` so with the JNI mappings can be generated. – Roberto Andrade May 05 '15 at 11:20
  • 2
    As per the [comment](http://stackoverflow.com/questions/12260149/libjpeg-turbo-for-android/12296343?noredirect=1#comment48228616_12296343) from @AlexCohn, you can include the wrapper JNI interface in the build by adding the `turbojpeg-jni.c` to the list of files to build in `Android.mk`, this way you may use the Java classes they provide directly instead of having to create your own native code to invoke the lib. – Roberto Andrade May 05 '15 at 19:34

4 Answers4

33

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.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • When I use your command line, it produce error `Android.mk:11: Extraneous text after `ifeq' directive Android NDK: WARNING: Unsupported source file extensions in Android.mk for module jpeg Android NDK: turbojpeg-mapfile make: *** No rule to make target `obj/armeabi/libjpeg.a'. Stop.` If I use `ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk` - it work, produce `libjpeg.so` but don't produce libjpeg.a any idea? – KoVadim Sep 06 '12 at 12:01
  • 2
    Oh, yes. I forgot about line 11. There is a definite bug in the git. Split the line between **true)** and **LOCAL_CFLAGS**. You can ignore the warning. Regarding `libjpeg.a` - my fault, again. The target should be `obj/local/armeabi/libjpeg.a`. I have fixed my answer accordingly. – Alex Cohn Sep 06 '12 at 12:17
  • 10tx. Now it is compiled. The next task - combine it with my code. – KoVadim Sep 06 '12 at 12:33
  • The next task is often trickier. Good luck! FWIW, turbo has both legacy API and its own, which is considered more friendly. – Alex Cohn Sep 06 '12 at 12:35
  • Alex, do you have any idea how to build libjpegturbo for x86? Does android version of it have support for x86? – Royston Pinto Apr 10 '13 at 21:58
  • @RoystonPinto: no slightest idea – Alex Cohn Apr 11 '13 at 08:22
  • 1
    Alex, any updates on support for x86 and mips? 3 years later? – Asiimwe Dec 17 '13 at 22:48
  • @PaulAsiimwe.T: you will definitely find tha [detailed update](http://stackoverflow.com/a/20697814/192373) by [markmanca](http://stackoverflow.com/users/2939912/markmanca) extremely useful. – Alex Cohn Dec 26 '13 at 10:20
  • Alex,I tried what you did but I got a lot of error like `./asm/armv7//jdcolor-armv7.S:1042: Error: selected processor does not support ARM mode `vshrn.s32 D18,Q7,#8'`. I have no idea what is it. I use ndk-r9d and took a snapshot of the last git commit. I'm on windows 7 x64 with cygwin. – Seltymar Apr 30 '14 at 07:41
  • @Seltymar: which jpeg-turbo did you clone? – Alex Cohn Apr 30 '14 at 12:11
  • I used this one [libjepg](https://git.linaro.org/people/tom.gall/libjpeg-turbo/libjpeg-turbo.git/shortlog/refs/heads/android) last commit. I'm using the ndk for windows. – Seltymar May 02 '14 at 01:44
  • @Seltymar: you need an Android branch, e.g. `git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android`. There are some other android branches, but I haven't investigate the differences between them. – Alex Cohn May 03 '14 at 15:03
  • Thank you. `linaro-android` branch compiles without any problem. – Seltymar May 07 '14 at 01:01
  • can someone please tell me how to run ndk-build? can i do it in eclipse or do i need to install bash or something? thanks – steveh Jun 23 '14 at 01:23
  • @steveh: no, you don't need bash to run **ndk-build**. You do need to download **ndk**. On Windows, you can run **ndk-build** from the usual *Command Prompt* – Alex Cohn Jun 23 '14 at 05:56
  • i finally figured out how to build an use the library and wrote about it here http://stackoverflow.com/questions/24548952/android-how-to-use-libjpeg-turbo-library my problem now, is its no faster than the built in bitmap factory. i suspect i'm not getting the asm files. any ideas anyone? – steveh Jul 04 '14 at 10:35
  • It seems like it'd work but then I get some errors at the end of the build (any idea?): `In file included from ./jccolor.c:118:0: ./jccolext.c:29:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'static' ./jccolext.c:86:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'static' In file included from ./jccolor.c:130:0: In file included from ./jccolor.c:144:0: In file included from ./jccolor.c:158:0: In file included from ./jccolor.c:172:0: In file included from ./jccolor.c:186:0: In file included from ./jccolor.c:200:0:` – Roberto Andrade May 05 '15 at 00:55
  • @RobertoAndrade: maybe you took libjpeg-turbo *not from git.linaro.org/people/tomgall*? Because I just cloned the latest, and had no errors like yours. – Alex Cohn May 05 '15 at 09:12
  • 1
    just tried it again after upgrading my NDK from `r8d` to `r10d` and it worked, so I guess it's something with that older version of the ndk? – Roberto Andrade May 05 '15 at 10:33
  • @RobertoAndrade: more likely, something went wrong in your old NDK installation. As far as I can recall, **r8d** was OK. But nevermind, the good part is that it is now behind you! – Alex Cohn May 05 '15 at 10:57
  • Yeap. my only problem now is getting the JNI portion to compile. Anyone able to do that? – Roberto Andrade May 05 '15 at 14:49
  • 2
    @RobertoAndrade: in **Android.mk** add `LOCAL_SRC_FILES+=turbojpeg-jni.c` before the first `include $(BUILD_SHARED_LIBRARY)` – Alex Cohn May 05 '15 at 15:18
  • I added /n after ($(ARCH_ARM_HAVE_NEON),true) but still I cant compile with NDK build - Android NDK: WARNING: Unsupported source file extensions in Android.mk for module jpeg Android NDK: turbojpeg-mapfile any hints? – BoazGarty Sep 01 '16 at 12:26
8

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):

  1. 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.

  2. 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.

  3. 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

  4. 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.

  5. 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.

  6. 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:

  1. 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))))
    
  2. 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

  3. import-locals.mk:

    Add the following line below the LOCAL_CFLAGS and the LOCAL_CPPFLAGS line

    LOCAL_YASMFLAGS  := $(LOCAL_CFLAGS) $(strip $(LOCAL_YASMFLAGS))
    
  4. 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
    
  5. 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
    
Community
  • 1
  • 1
markmanca
  • 163
  • 1
  • 5
  • Thanks for sharing! People seem to be looking for these updates! – Alex Cohn Dec 26 '13 at 10:26
  • And you're a "newbie"? Thanks alot – Asiimwe Dec 29 '13 at 20:26
  • I am trying to follow the steps mentioned above. I assume steps 2&3 are for x-86, step 4 is for arm and step 5 is for MIPS. Please correct me if this is wrong. I am interested only in ARM for now. When I cloned the git repo and try to make changes in Step 4, I do not see cpufeatures directory. I only see a cpu-features.h file under directory named 'machine'. Can you please advise? – rajaramyadhav Aug 18 '14 at 23:44
  • If you have a working version somewhere, I would love to take a look at it. I was able to get libjpegturbo working with Alex Kohn's version. However I am looking to do dynamic NEON detection as well. – rajaramyadhav Aug 18 '14 at 23:46
2

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)
Mr. Xian
  • 33
  • 4
  • Is this Android.mk for x86? I tried using this Android.mk you provide and performing the following command: ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=x86 obj/local/x86/libjpeg.a and it worked but I am not sure if this is correct as the answer below @markmanca is far more complex. – Iker Jamardo Zugaza Oct 24 '15 at 22:00
0

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.

Droid Coder
  • 381
  • 2
  • 10