Система сборки Android, сборки NEON и не-NEON - PullRequest
12 голосов
/ 06 октября 2011

Я хочу собрать свою библиотеку для armv6, и есть неоновый код, который я включаю во время выполнения, если устройство поддерживает его. Неоновый код использует неоновые встроенные функции, и чтобы иметь возможность его компилировать, я должен включить armeabi-v7a, но это влияет на обычный c-код (он ломается на некоторых бюджетных устройствах).

Итак, если система сборки Android не была чрезмерно навязчивой, мне не пришлось бы задавать вопросы, но, похоже, у меня нет возможности скомпилировать один файл для armv6 и другой файл для arm7-neon.

Кто-нибудь может дать какие-нибудь подсказки, если это выполнимо?

Редактировать
Прежде чем пытаться ответить и тратить впустую интернет-чернила, должно быть ясно, что это основные моменты:
1) сделать только ОДНУ либ.
2) make build, работающий на armv6 (до неоновых устройств, например, armeabi).
3) позволяет этой сборке также содержать код NEON (который может быть выполнен на основе обнаружения процессора во время выполнения; обнаружение процессора выходит за рамки вопроса).
4) NEON-код взят из файла c / cpp и написан с использованием неоновых встроенных функций.

Пропуск любой части этих требований полностью теряет смысл вопроса

Ответы [ 6 ]

12 голосов
/ 02 сентября 2012

Недавно я нашел другой способ обойти ограничения NDK.Мой случай не был связан с NEON, но для вас тот же хак мог бы выполнить эту работу.

Хитрость заключается в том, чтобы использовать существующий механизм «тегов» NDK, чтобы задать специальный CFLAGS для группы файлов.Вот как вы это делаете:

Сначала перечислите неоновые источники.Вы не можете использовать суффикс .neon, как описано в docs / CPU-ARM-NEON.html , потому что 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.mk или Application.mk:

modules-LOCALS += NEON_SRC_FILES

Примечание: Я не пробовал эту магию для NEON, она мне нужна для совершенно других целей.Возможно, вам потребуются некоторые изменения для достижения желаемых параметров компиляции для ваших файлов и для вашего проекта.Я использую NDK r.8b , и я не проверял, будет ли это работать на более ранних (или более поздних) версиях.

4 голосов
/ 12 июня 2012

Если вы поместите код NEON в отдельный модуль (статическая библиотека или общая библиотека), вы можете вручную настроить CFLAGS для этого модуля в вашем Android.mk по своему желанию.

Если у вас есть 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 голосов
/ 27 марта 2012

Используя эту ссылку http://www.kandroid.org/ndk/docs/CPU-ARM-NEON.html

Вы можете выборочно создавать определенные исходные файлы с поддержкой NEON, используя суффикс файла .neon. Надеюсь, вы сможете решить, относится ли это к выбору ABI ...

Возможно, вы сможете поместить свой путь к коду NEON в один файл, и с помощью условного файла make, как показано выше, выберите, чтобы создать правильный файл, на основе которого ABI вы нацеливаете

1 голос
/ 06 октября 2011

Этот фрагмент из документации, вероятно, поможет:

   # 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

Это компилирует mylib-neon только при использовании armeabi-v7a, даже если вы используете один и тот же файл Android.mk для различных ABI. Для armeabi v6 он будет полностью пропущен.

0 голосов
/ 29 июля 2015

Если вы ищете более простую реализацию:

Во-первых, убедитесь, что весь NEON-совместимый код условно скомпилирован только для ABI armeabi-v7a, и дополнительно будет выполняться, только если во время выполнения он выполняется наРеализация ARMv7, которая включает NEON:

/* 
   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() использует библиотеку cpufeatures NDK.Затем в вашем файле 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
0 голосов
/ 11 июля 2012

Да, в вашем файле Application.mk добавьте:

APP_ABI := armeabi armeabi-v7a
LOCAL_ARM_NEON := true

NDK не будет добавлять поддержку NEON для библиотек armeabi, поскольку они являются взаимоисключающими, просто добавляя эти строки и компилируя, как вы обычно делаете,два отдельных файла так.Вы включаете их оба в свой apk в структуру каталогов, в которую они были экспортированы, и устройство автоматически загрузит неоновый, если это поддерживается.

...