Zrozumienie kompilacji 64-bitowych

System kompilacji obsługuje budowanie plików binarnych dla dwóch docelowych architektur procesora (64-bitowego i 32-bitowego) w tej samej kompilacji. Jest to znane jako kompilacja multilib .

W przypadku natywnych bibliotek statycznych i bibliotek współdzielonych system budowania konfiguruje reguły do ​​budowania plików binarnych dla obu architektur. Konfiguracja produktu ( PRODUCT_PACKAGES ) wraz z wykresem zależności określa, które pliki binarne są budowane i instalowane w obrazie systemu.

W przypadku plików wykonywalnych i aplikacji system kompilacji domyślnie kompiluje tylko wersję 64-bitową, ale można zastąpić to ustawienie za pomocą globalnej zmiennej BoardConfig.mk lub zmiennej o zakresie modułu.

Konfiguracja produktu

BoardConfig.mk zawiera następujące zmienne do konfiguracji drugiej architektury procesora i ABI:

  • TARGET_2ND_ARCH
  • TARGET_2ND_ARCH_VARIANT
  • TARGET_2ND_CPU_VARIANT
  • TARGET_2ND_CPU_ABI
  • TARGET_2ND_CPU_ABI2

Możesz zobaczyć przykład w build/target/board/generic_arm64/BoardConfig.mk .

W kompilacji multilib nazwy modułów w PRODUCT_PACKAGES obejmują zarówno 32-bitowe, jak i 64-bitowe pliki binarne, o ile są one zdefiniowane przez system kompilacji. W przypadku bibliotek pobieranych przez zależność biblioteka 32-bitowa jest instalowana tylko wtedy, gdy jest wymagana przez inną bibliotekę 32-bitową lub plik wykonywalny. To samo dotyczy bibliotek 64-bitowych.

Jednak nazwy modułów w wierszu polecenia make obejmują tylko wersję 64-bitową. Na przykład, po uruchomieniu lunch aosp_arm64-eng , make libc buduje tylko 64-bitową bibliotekę libc. Aby zbudować 32-bitową bibliotekę libc, musisz uruchomić make libc_32 .

Definicja modułu w Android.mk

Możesz użyć zmiennej LOCAL_MULTILIB , aby skonfigurować kompilację dla 32-bitowej/64-bitowej i zastąpić globalną zmienną TARGET_PREFER_32_BIT .

Ustaw LOCAL_MULTILIB na jedną z następujących wartości:

  • "both" buduje zarówno 32-bitowe, jak i 64-bitowe.
  • "32" buduje tylko 32 bity.
  • "64" kompiluje tylko 64 bity.
  • "first" kompiluje tylko pierwszą architekturę (32-bitową w urządzeniach 32-bitowych i 64-bitową w urządzeniach 64-bitowych).
  • "" to wartość domyślna. System budowania decyduje, którą architekturę zbudować na podstawie klasy modułu i innych zmiennych LOCAL_ , takich jak LOCAL_MODULE_TARGET_ARCH i LOCAL_32_BIT_ONLY .

Jeśli chcesz zbudować swój moduł dla konkretnych architektur, użyj następujących zmiennych:

  • LOCAL_MODULE_TARGET_ARCH
    Ustaw tę zmienną na listę architektur, takich jak arm x86 arm64 . Jeśli budowana architektura znajduje się na tej liście, bieżący moduł jest dołączany do systemu budowania.
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH
    Ta zmienna jest przeciwieństwem LOCAL_MODULE_TARGET_ARCH . Jeśli budowanej architektury nie ma na tej liście, bieżący moduł jest dołączany do systemu budowania.

Istnieją mniejsze warianty tych dwóch zmiennych:

  • LOCAL_MODULE_TARGET_ARCH_WARN
  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN

System kompilacji ostrzega, jeśli bieżący moduł zostanie pominięty z powodu wymienionych architektur.

Aby skonfigurować flagi kompilacji dla określonej architektury, użyj zmiennych LOCAL_ specyficznych dla architektury. Zmienna LOCAL_ specyficzna dla architektury to normalna zmienna LOCAL_ z przyrostkiem architektury, na przykład:

  • LOCAL_SRC_FILES_arm, LOCAL_SRC_FILES_x86,
  • LOCAL_CFLAGS_arm, LOCAL_CFLAGS_arm64,
  • LOCAL_LDFLAGS_arm, LOCAL_LDFLAGS_arm64,

Te zmienne są stosowane tylko wtedy, gdy plik binarny jest obecnie budowany dla tej architektury.

Czasami łatwiej jest ustawić flagi na podstawie tego, czy plik binarny jest obecnie budowany dla wersji 32-bitowej czy 64-bitowej. Użyj zmiennej LOCAL_ z sufiksem _32 lub _64 , na przykład:

  • LOCAL_SRC_FILES_32, LOCAL_SRC_FILES_64,
  • LOCAL_CFLAGS_32, LOCAL_CFLAGS_64,
  • LOCAL_LDFLAGS_32, LOCAL_LDFLAGS_64,

Instalowanie ścieżki

Wcześniej można było użyć LOCAL_MODULE_PATH do zainstalowania biblioteki w lokalizacji innej niż domyślna. Na przykład LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw .

W kompilacji multilib użyj zamiast tego LOCAL_MODULE_RELATIVE_PATH :

LOCAL_MODULE_RELATIVE_PATH := hw

W tym formacie zarówno biblioteki 64-bitowe, jak i 32-bitowe są instalowane we właściwym miejscu.

Jeśli tworzysz plik wykonywalny zarówno w wersji 32-, jak i 64-bitowej, użyj jednej z następujących zmiennych, aby odróżnić ścieżkę instalacji:

  • LOCAL_MODULE_STEM_32, LOCAL_MODULE_STEM_64
    Określa nazwę zainstalowanego pliku.
  • LOCAL_MODULE_PATH_32, LOCAL_MODULE_PATH_64
    Określa ścieżkę instalacji.

Wygenerowane źródła

W kompilacji multilib, jeśli generujesz pliki źródłowe do $(local-intermediates-dir) (lub $(intermediates-dir-for) z jawnymi zmiennymi), nie działa to niezawodnie. Dzieje się tak, ponieważ pośrednie źródła generowane są wymagane przez kompilacje 32-bitowe i 64-bitowe, ale $(local-intermediates-dir) wskazuje tylko na jeden z dwóch katalogów pośrednich.

System budowania udostępnia dedykowany, przyjazny dla multilib, katalog pośredni do generowania źródeł. Możesz wywołać $(local-generated-sources-dir) lub $(generated-sources-dir-for) , aby uzyskać ścieżkę katalogu. Ich zastosowania są podobne do $(local-intermediates-dir) i $(intermediates-dir-for) .

Jeśli plik źródłowy jest generowany w tym dedykowanym katalogu i pobierany przez LOCAL_GENERATED_SOURCES , jest on skompilowany zarówno w wersji 32-bitowej, jak i 64-bitowej w kompilacji multilib.

Prefabrykowane

W kompilacji multilib nie można użyć TARGET_ARCH (lub razem z TARGET_2ND_ARCH ), aby poinformować system kompilacji o architekturze wstępnie skompilowanych celów binarnych. Zamiast tego użyj zmiennych LOCAL_ LOCAL_MODULE_TARGET_ARCH lub LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH .

Dzięki tym zmiennym system kompilacji może wybrać odpowiedni 32-bitowy wstępnie skompilowany plik binarny, nawet jeśli działa na 64-bitowej kompilacji multilib.

Jeśli chcesz użyć wybranej architektury do obliczenia ścieżki źródłowej dla wstępnie skompilowanego pliku binarnego, wywołaj $(get-prebuilt-src-arch) .

Generowanie plików ODEX

W przypadku urządzeń 64-bitowych domyślnie generujemy zarówno 32-bitowe, jak i 64-bitowe pliki ODEX dla obrazu rozruchowego i dowolnych bibliotek Java. W przypadku pakietów APK domyślnie generujemy ODEX tylko dla podstawowej architektury 64-bitowej. Jeśli aplikacja zostanie uruchomiona zarówno w procesach 32-bitowych, jak i 64-bitowych, użyj LOCAL_MULTILIB := both , aby upewnić się, że generowane są zarówno 32-bitowe, jak i 64-bitowe pliki ODEX. Jeśli aplikacja ma jakiekolwiek 32-bitowe lub 64-bitowe biblioteki JNI, ta flaga informuje również system kompilacji, aby je uwzględnić.