我想为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编写。
忽略这些要求的任何部分完全忽略了问题
答案 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.mk
或Application.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中将它们包含在导出到的目录结构中,如果支持,设备将自动加载氖灯。