libjpeg-turbo for android

KoV*_*dim 16 android jpeg android-ndk libjpeg-turbo

我需要libjpeg-turbo for android ndk.有没有人设法将其编译为.a(静态)lib?我试过几次,但它只给了我很多错误.

Ale*_*ohn 31

安装Android NDK.以下说明用r8b验证,旧版本可能有问题,我不知道.

从Benjamin Gaignard 获取libjpeg-turbo的Android源代码:

git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android
Run Code Online (Sandbox Code Playgroud)

在由git创建的libjpeg-turbo目录中,编辑文件Android.mk:在第70行之后,添加以下内容:LOCAL_MODULE := libjpeg

ifeq ($(notdir $(MAKECMDGOALS)),libjpeg.a)
  LOCAL_SRC_FILES +=  $(libsimd_SOURCES_DIST)
  include $(BUILD_STATIC_LIBRARY)
  include $(CLEAR_VARS)
  LOCAL_MODULE := dummy
endif
Run Code Online (Sandbox Code Playgroud)

运行ndk-build:

ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk obj/local/armeabi/libjpeg.a
Run Code Online (Sandbox Code Playgroud)

利润!

PS:您可能需要armeabi-v7a版本:

ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=armeabi-v7a obj/local/armeabi-v7a/libjpeg.a
Run Code Online (Sandbox Code Playgroud)

或者为ARM编译,为了提高性能,添加到命令行:

LOCAL_ARM_MODE=arm
Run Code Online (Sandbox Code Playgroud)

如果您的目标具有NEON支持,请添加到命令行:

LOCAL_ARM_NEON=true ARCH_ARM_HAVE_NEON=true
Run Code Online (Sandbox Code Playgroud)

UPDATE:把它与Android NDK R15和以后的工作中要删除所有引用libcutilsAndroid.mk.

  • 哦,是的.我忘记了第11行.在git中有一个明确的错误.拆分**true)**和**LOCAL_CFLAGS**之间的界限.您可以忽略该警告.关于`libjpeg.a` - 我的错,再次.目标应该是`obj/local/armeabi/libjpeg.a`.我已经相应地修正了我的答案. (2认同)
  • @RobertoAndrade:在**Android.mk**中添加`LOCAL_SRC_FILES + = turbojpeg-jni.c`在第一个`include $(BUILD_SHARED_LIBRARY)之前 (2认同)

小智 8

这个答案扩展了Alex Cohn的答案.让我开始,他完全赞同他.这个答案将允许您使用ARM(带或不带NEON)和x86的程序集构建libjpeg-turbo.还为MIPS提供兼容性,以便您可以成为一个好公民,并为Android NDK的r8e版本支持的所有平台构建您的应用程序.

我仍然是一个真正回答问题的相对新手,所以没有权限包含附件.所以我将不得不内联一堆代码.我也确定有更好的方法来做下面的点点滴滴,所以我愿意接受改进建议.

让这一切全部工作是在六个主要步骤中完成的(第二步有许多子步骤 - 每个步骤可以在主要的六个步骤之后找到):

  1. 通过git下载libjpeg-turbo库,其中包含一组Android代码和.mk文件.我用git从这里下载了它:

    git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android
    
    Run Code Online (Sandbox Code Playgroud)

    必须完全赞赏并感谢Tom Gall做了初步工作.

  2. 下载YASM(x86的汇编程序)并配置Android构建环境以支持它.在步骤6中我的Android.mk更改结束时,请参阅有关为我所包含的Android NDK配置YASM的说明集.支持x86要求您不要羞于调整NDK安装.

    我或许可以使用NASM编译器,但在调查NASM之前我已经远远超过了YASM路径,我将YASM路径完成了.

  3. 创建simd/jsmidcfg.inc文件.libjpeg-turbo库提供了simd/jsmidcfg.inc.h.它是指预处理器采用.h并将其转换为.inc.我确信有一种比我做的更好的方式.但由于时间压力,无法解决问题.相反,我手动运行一个Android附带的gcc来使用以下命令创建文件:

    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
    
    Run Code Online (Sandbox Code Playgroud)

    预处理器完成后,我不得不手动编辑文件,使其进入可用状态.我必须选择"; - jpeglib.h"上面的所有行并删除它们.

    接下来,我必须找到以_cpp_protection_开头的每个%定义,并复制每个%定义没有_cpp_protection_.例如,%define _cpp_protection_RGB_RED 0成了%define RGB_RED 0

  4. 对于ARM,我希望我的代码在具有它的硬件上动态支持NEON指令,并且在没有的硬件上回退到更简单的东西,我修改了simd/jsimd_arm.c来动态查询信息.在构建libjpeg-turbo时,我不想做出那样的选择.

    我添加了以下代码行:

    #ifdef ANDROID
    #include <cpufeatures/cpu-features.h>
    #endif
    
    Run Code Online (Sandbox Code Playgroud)

    #ifdef ANDROID
      uint64_t cpuFeatures = android_getCpuFeatures();
      if (cpuFeatures & ANDROID_CPU_ARM_FEATURE_NEON) {
         simd_support |= JSIMD_ARM_NEON;
      }
    #endif
    
    Run Code Online (Sandbox Code Playgroud)

    在init_simd()方法中.

  5. 启用MIPS.

    为了成为一个好公民,我想在MIPS上启用编译.虽然MIPS没有任何汇编代码,但代码至少应该编译和运行.为此,我将simd/jsimd_arm.c复制到simd/jsimd_mips.c.我编辑了文件,因此init_simd()set simd_support = 0; I也改变了所有jsimd_can_*()方法返回0.最后,我从所有其他方法中删除了实现.

  6. 因为我不仅仅对ARM的构建感兴趣,所以我更改了Application.mk文件以包含以下行:

    APP_ABI := all
    APP_OPTIM := release
    
    Run Code Online (Sandbox Code Playgroud)

    APP_OPTIM来自如何使用android-ndk优化本机代码(速度优化)

    在Android.mk中,我注释掉了"cjpeg"注释块及其下方的所有内容.要做一个块注释,我按照如何在makefile中添加多行注释的建议

    我接下来定制了Android.mk文件本身,以便我可以为所有当前支持的CPU(ARM,x86,MIPS)构建.这是我最终得到的(一些代码注释掉了,因为我想要一个静态库 - 也保留原始代码,这样我就可以看到改变了什么).您很可能必须更改(或删除)addprefix方法调用,因为下面的文件是为我的构建环境自定义的.但除此之外,它应该适合你.

.

##################################################
###                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)
Run Code Online (Sandbox Code Playgroud)

libjpeg-turbo附带的一些源代码是.asm格式.也就是说,需要使用NASM汇编程序进行编译.随着它的发布,Android NDK不支持它.

为了让.asm支持使用NDK,我遵循了这里提出的粗略轮廓:http://software.intel.com/en-us/articles/using-yasm-compiler-on-android-ndkbuild

以下是一组更详细的说明.在android-ndk-r8\build\core中,需要进行以下操作:

  1. build-binary.mk:

    all_source_extensions := .c .s .S $(LOCAL_CPP_EXTENSION) => all_source_extensions := .c .s .asm .S $(LOCAL_CPP_EXTENSION)

    对我来说,上面是228行.

    在以"#构建源文件到源文件"开头的行之后,您将看到几个foreach循环.像这样添加一个(我在第272行添加了它):

    $(foreach src,$(filter %.asm,$(LOCAL_SRC_FILES)), $(call compile-asm-source,$(src),$(call get-object-name,$(src))))
    
    Run Code Online (Sandbox Code Playgroud)
  2. definitions.mk:

    创建一个新的compile-asm-source以匹配我们在上面的new for循环中添加的新条目.我们还必须在make文件中添加一个新的定义.我添加了以下内容.它是用于构建.c文件的各种规则的组合和简化.当使用yasm需要这些更改时,我们需要一组不同的选项.

    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))
    
    Run Code Online (Sandbox Code Playgroud)

    搜索以'compile-s-source'开头的行.我在1491行找到了它.新的compile-asm-source可以直接在它下面.

    接下来,搜索以"get-object-name"开头的行.我在第1270行找到它.在内部for循环中添加".asm".将它与.c,.s和.S放在一起

  3. import-locals.mk:

    在LOCAL_CFLAGS和LOCAL_CPPFLAGS行下面添加以下行

    LOCAL_YASMFLAGS  := $(LOCAL_CFLAGS) $(strip $(LOCAL_YASMFLAGS))
    
    Run Code Online (Sandbox Code Playgroud)
  4. default-build-commands.mk:

    在文件中的任何位置添加以下行.我把它放在TARGET_CXX部分和TARGET_LD部分之上.

    TARGET_ASM       = $(TOOLCHAIN_PREFIX)yasm
    
    Run Code Online (Sandbox Code Playgroud)
  5. 下载yasm.exe并将其复制到构建文件夹:

    从这里下载YASM的副本:http://yasm.tortall.net/

    我有NDK的Win64版本,所以下载了YASM的Win64版本.如果您有NDS的Win32版本,请下载YASM的Win32版本.

    你应该得到.exe.将其作为yasm.exe复制到以下目录.如果您有任何其他工具链版本,请将其复制到这些目录:

    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
    
    Run Code Online (Sandbox Code Playgroud)

    然后,将文件再次复制到i686-linux-android-yasm.exe下面的目录中.如上所述,如果您有任何其他工具链版本,请将其复制到这些目录:

    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
    
    Run Code Online (Sandbox Code Playgroud)