Android构建系统,NEON和非NEON构建

时间:2011-10-06 19:21:34

标签: android android-ndk arm neon

我想为armv6构建我的库,并且如果设备支持它,我会在运行时启用一些霓虹灯代码。霓虹灯代码使用霓虹内在函数,为了能够编译它,我必须启用armeabi-v7a,但这会影响常规的c代码(在某些低端设备上它会被破坏)。

所以,如果android构建系统没有过多的干扰,我就不必提问了,但似乎我没办法为armv6编译一个文件而为arm7-neon编译另一个文件。

如果可行的话,有人可以提供任何线索吗?

修改
在尝试回复并浪费互联网墨水之前,应该清楚这些是要点:
  1)只制作一个lib。
  2)制作在armv6(pre-neon设备,例如armeabi)上运行的构建。
  3)允许此版本还包含NEON代码(可以基于运行时cpu检测执行; cpu检测不在问题范围内)。
  4) NEON代码来自c / cpp文件,使用neon intrinsics编写。

忽略这些要求的任何部分完全忽略了问题

6 个答案:

答案 0 :(得分:11)

我最近找到了另一种解决NDK限制的方法。我的案子与NEON无关,但对你而言,同样的黑客可以胜任这项工作。

诀窍是使用NDK的现有“标记”机制为一堆文件指定特殊CFLAGS。你就是这样做的:

首先,列出霓虹灯特定来源。您无法使用docs/CPU-ARM-NEON.html中所述的.neon后缀,因为build-binary.mk会发现您没有定位到armeabi-v7a。我使用以下技术:

LOCAL_NEON_SRC_FILES := imgproc/neon_utils.c \
                        videoproc/usingneon.cpp
LOCAL_SRC_FILES := main.c \
                   imgproc/img.c \
                   videoproc/video.cpp

LOCAL_SRC_FILES += $(LOCAL_NEON_SRC_FILES)

现在,为NEON定义CFLAGS

LOCAL_NEON_CFLAGS := -mfloat-abi=softfp -mfpu=neon -march=armv7

最后,将以下神奇的线条添加到Android.mk:

TARGET-process-src-files-tags += $(call add-src-files-target-cflags, $(LOCAL_NEON_SRC_FILES), $(LOCAL_NEON_CFLAGS))

如果您要构建多个二进制文件,则可能希望通过

重置$(LOCAL_NEON_SRC_FILES)
include $(CLEAR_VARS)

为此,请将以下内容添加到Android.mkApplication.mk

modules-LOCALS += NEON_SRC_FILES

注意:我没有为NEON尝试过这种魔法,我需要它用于完全不同的目的。您可能需要进行一些调整才能为文件和项目实现所需的编译选项。我正在使用 NDK r.8b ,我没有检查这是否适用于早期版本(或更高版本)。

答案 1 :(得分:4)

如果您将NEON代码放在单独的模块(静态库或共享库)中,您可以将 Android.mk 中该模块的 CFLAGS 手动调整为您的想。

如果您的C文件在内在函数周围使用 #ifdef __ARM_NEON __ ,那么您最好的选择是将这些文件放在共享库中 - 一个是针对v6编译的,另一个针对的是霓虹灯。

我通常直接从Java加载这样的“免费”库,因此主本机代码根本不关心这些更改。


更新:这是一个使用静态库的简单示例:

<强> Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := neon_utils
LOCAL_SRC_FILES := neon_add.c
LOCAL_CFLAGS += -mfloat-abi=softfp -mfpu=neon -march=armv7
include $(BUILD_STATIC_LIBRARY)

NDK_PATH:=$(call my-dir)/../..

include $(CLEAR_VARS)
LOCAL_MODULE    := test_conditional_load
LOCAL_C_INCLUDES := $(NDK_PATH)/sources/cpufeatures
LOCAL_SRC_FILES := main.c
LOCAL_STATIC_LIBRARIES  :=  neon_utils cpufeatures

include $(BUILD_EXECUTABLE)

include $(NDK_PATH)/sources/cpufeatures/Android.mk

<强>的main.c

#include <stdio.h>
#include <cpu-features.h>

void neon_add(int32_t * ptr);

int main()
{
    int32_t int32_4[] = {2,3,4,5};

    if (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON)
    {
        neon_add(int32_4);
        printf("neon\n");
    }
    else
    {
        printf("not neon\n");
    }
    printf("values = %d, %d, %d, %d\n", int32_4[0], int32_4[1], int32_4[2], int32_4[3]);
    return 0;
}

<强> neon_add.c

#include <arm_neon.h>

void neon_add(int32_t * ptr)
{
    int32x4_t vin = vld1q_s32(ptr);
    int32x4_t vout = vaddq_s32(vin, vin);
    vst1q_s32(ptr, vout);
}

答案 2 :(得分:2)

使用此链接 http://www.kandroid.org/ndk/docs/CPU-ARM-NEON.html

您可以使用.neon文件后缀选择性地构建具有NEON支持的某些源文件。 希望你能弄清楚这是否适用于ABI选择......

您可以将NEON代码路径放在一个文件中,并使用如上所示的条件生成文件选择根据您要定位的ABI构建正确的文件

答案 3 :(得分:1)

文档中的这段代码可能会有所帮助:

   # define a static library containing our NEON code
   ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
      include $(CLEAR_VARS)
      LOCAL_MODULE    := mylib-neon
      LOCAL_SRC_FILES := mylib-neon.c
      LOCAL_ARM_NEON  := true
      include $(BUILD_STATIC_LIBRARY)
   endif # TARGET_ARCH_ABI == armeabi-v7a

即使您对各种ABI使用相同的Android.mk文件,也只能在使用armeabi-v7a时编译mylib-neon。对于armeabi v6,它将完全跳过它。

答案 4 :(得分:0)

如果您正在寻找更简单的实施方式:

首先,确保所有支持NEON的代码仅针对ABI armeabi-v7a进行有条件编译,并且只有在运行时它才会在包含NEON的ARMv7实现上运行时执行:

this.linkbThread.TabIndex = 31;        //first
this.linkbThread.Text = "My URL";      //second

此处,/* bar_better_on_neon.c */ #ifdef HAVE_ARMV7 # include <arm_neon.h> # ifdef ANDROID # include "cpu-features.h" # endif #endif #ifdef HAVE_ARMV7 static int check_for_neon(void) { # ifdef ANDROID // Not all Android devices with ARMv7 are guaranteed to have NEON, so check. uint64_t features = android_getCpuFeatures(); return (features & ANDROID_CPU_ARM_FEATURE_ARMv7) && (features & ANDROID_CPU_ARM_FEATURE_NEON); # elif defined(__APPLE__) return 1; # else return 0; # endif } #endif void bar(void) { #ifdef HAVE_ARMV7 if (check_for_neon()) { /* here put neon code */ } else { #endif /* here put non-neon code */ #ifdef HAVE_ARMV7 } #endif } 使用NDK的cpufeatures库。然后,在您的Android.mk文件中:

check_for_neon()

答案 5 :(得分:-1)

是的,在您的Application.mk文件中添加:

APP_ABI := armeabi armeabi-v7a
LOCAL_ARM_NEON := true

NDK不会为armeabi libs添加NEON支持,因为它们是互斥的,只需添加这些行并按照通常的方式编译将生成两个单独的文件。您可以在apk中将它们包含在导出到的目录结构中,如果支持,设备将自动加载氖灯。