Android build system, neon i non-Neon buduje

Chcę zbudować moją bibliotekę dla armv6, i jest jakiś kod neonowy, który włączam w czasie wykonywania, jeśli urządzenie GO obsługuje. Kod neon używa Neon intrinsics i aby móc go skompilować, muszę włączyć armeabi-v7a, ale to wpływa na zwykły kod c(staje się zepsuty na niektórych urządzeniach low-end).

Tak więc, jeśli system budowania Androida nie był zbyt natrętny, nie musiałbym zadawać pytań, ale wygląda na to, że nie ma sposobu, aby skompilować jeden plik dla armv6, a drugi dla arm7-neon

Czy ktoś może podać jakieś wskazówki, jeśli jest to wykonalne?

Edit
Zanim spróbujesz odpowiedzieć i marnować Internet-ink, powinno być jasne, że są to główne punkty:
1) zrób tylko jedną lib.
2) tworzy build, który działa na armv6(przed neonami, np. armeabi).
3) pozwól, aby ta kompilacja zawierała również kod NEON (który może być wykonany w oparciu o detekcję procesora w czasie wykonywania; Detekcja procesora jest poza zakresem pytanie).
4) kod NEON pochodzi z pliku c / cpp i jest napisany przy użyciu Neon intrinsics.

Pominięcie jakiejkolwiek części tych wymagań całkowicie traci punkt pytania

Author: demongolem, 2011-10-06

6 answers

Ostatnio znalazłem inny sposób na obejście ograniczeń NDK. Moja sprawa nie była związana z neonem, ale dla Ciebie ten sam hack mógłby to zrobić.

Sztuczka polega na użyciu istniejącego mechanizmu "tag" w NDK, aby określić specjalne CFLAGS dla kilku plików. Tak to się robi:

Najpierw wymień źródła neonowe. Nie można użyć przyrostka .neon, jak opisano w docs/CPU-ARM-NEON.html ponieważ build-binary.mk stwierdzi, że nie kierujesz armeabi-v7a. używam następującej techniki:

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)

Zdefiniuj CFLAGS dla neonu:

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

Na koniec dodaj następującą magiczną linię do swojego Android.mk:

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

Jeśli masz więcej niż jeden plik binarny do zbudowania, prawdopodobnie będziesz chciał, aby $(LOCAL_NEON_SRC_FILES) został zresetowany przez

include $(CLEAR_VARS)

W tym celu dodaj do swojego Android.mk lub do Application.mk:

modules-LOCALS += NEON_SRC_FILES

Uwaga: [29]} nie próbowałem tej magii dla neonu, potrzebowałem jej do zupełnie innych celów. Możesz potrzebować adaptacje w celu uzyskania pożądanych opcji kompilacji dla Twoich plików i dla Twojego projektu. Używam NDK r. 8b i nie sprawdzałem, czy to zadziała na wcześniejszych (czy późniejszych) wersjach.

 11
Author: Alex Cohn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-02 09:18:12

Jeśli umieścisz kod NEON w oddzielnym module (biblioteka statyczna lub biblioteka współdzielona), możesz ręcznie dostroić CFLAGS dla tego modułu w swoim Android.mk za twoje pragnienie.

Jeśli masz pliki C, które używają #ifdef __ARM_NEON__ wokół intrinsics, najlepszym wyborem będzie umieszczenie tych plików w bibliotekach współdzielonych - jedna skompilowana dla v6, druga dla neon.

Zwykle Ładuję takie" supplimentowe " biblioteki bezpośrednio z Javy, tak aby główny kod natywny w ogóle nie dbają o te zmiany.


Update: Oto prosty przykład wykorzystujący statyczną bibliotekę:

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);
}
 4
Author: Alex Cohn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-14 08:36:22

Używając tego linku http://www.kandroid.org/ndk/docs/CPU-ARM-NEON.html

Można selektywnie budować pewne pliki źródłowe z obsługą NEON za pomocą .Neon file sufiks. Mam nadzieję, że uda ci się ustalić, czy dotyczy to wyboru ABI...

Możesz umieścić ścieżkę kodu neonowego w jednym pliku i używając opcji make File conditional, jak pokazano powyżej Wybierz, aby zbudować poprawny plik na podstawie którego ABI kierujesz

 2
Author: yano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-27 01:11:03

Ten fragment z dokumentacji prawdopodobnie pomoże:

   # 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

To kompiluje tylko mylib-neon podczas używania armeabi-v7a, nawet jeśli używasz tego samego Android.mk plik dla różnych ABIs. Dla armeabi v6 pominie go całkowicie.

 1
Author: richq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-06 19:32:57

Jeśli szukasz prostszej implementacji:

Po pierwsze, upewnij się, że cały kod obsługujący NEON jest warunkowo kompilowany tylko dla ABI armeabi-v7a, a dodatkowo będzie wykonywany tylko wtedy, gdy jest uruchomiony na implementacji ARMv7, która zawiera 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
}

Tutaj check_for_neon() używa biblioteki cpufeatures NDK. Wtedy, w Twoim Android.mk plik:

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
Author: bleater,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-29 03:26:04

Tak, w Twoim Application.mk Dodaj plik:

APP_ABI := armeabi armeabi-v7a
LOCAL_ARM_NEON := true

NDK nie doda neonów do libs armeabi, ponieważ są one wzajemnie się wykluczające, po prostu dodanie tych linii i skompilowanie jak zwykle spowoduje powstanie dwóch oddzielnych plików so. Dołączasz je do swojego apk w strukturze katalogów, do których zostały wyeksportowane, a urządzenie automatycznie załaduje neon, jeśli jest obsługiwane.

 -1
Author: Justin Buser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-11 18:28:16