13

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

所以,如果 android 构建系统不是过度侵入,我就不必问问题,但我似乎没有办法为 armv6 编译一个文件,为 arm7-neon 编译另一个文件。

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

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

忽略这些要求的任何部分都完全失去了问题的重点

4

6 回答 6

12

我最近发现了另一种解决 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)

现在,CFLAGS为 NEON 定义:

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.mkor 中Application.mk

modules-LOCALS += NEON_SRC_FILES

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

于 2012-09-02T09:18:12.287 回答
4

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

如果您有围绕内部函数使用#ifdef __ARM_NEON__的C 文件,您最好的选择是将这些文件放在共享库中 - 一个为 v6 编译,另一个为 neon 编译。

我通常直接从 Java 加载这样的“补充”库,这样主要的本机代码根本不关心这些变化。


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

安卓.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

主程序

#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;
}

霓虹灯添加.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);
}
于 2012-06-12T15:46:43.723 回答
2

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

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

您可以将您的 NEON 代码路径放在一个文件中,并使用如上所示的条件生成文件选择基于您所针对的 ABI 构建正确的文件

于 2012-03-27T01:11:03.880 回答
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,它将完全跳过它。

于 2011-10-06T19:32:57.720 回答
0

如果您正在寻找更简单的实现:

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

/* 
   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
}

在这里,check_for_neon()使用 NDK 的 cpufeatures 库。然后,在您的 Android.mk 文件中:

LOCAL_SRC_FILES := foo.c bar_better_on_neon.c
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
  # Compile the one file in NEON mode.
  LOCAL_SRC_FILES := $(subst bar_better_on_neon.c, bar_better_on_neon.c.neon,$(LOCAL_SRC_FILES))
  LOCAL_CFLAGS += -DHAVE_ARMV7=1
endif
于 2015-07-29T03:26:04.733 回答
-1

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

APP_ABI := armeabi armeabi-v7a
LOCAL_ARM_NEON := true

NDK 不会将 NEON 支持添加到 armeabi 库,因为它们是互斥的,只需添加这些行并像往常一样编译将生成两个单独的 so 文件。您将它们都包含在您的 apk 中它们导出到的目录结构中,如果支持,设备将自动加载霓虹灯。

于 2012-07-11T18:28:16.533 回答