Kompilowanie z użyciem wtyczki Jack (AOSP 6.0–8.1)

Jack to domyślna linia narzędzi do kompilacji Androida w wersjach 6.0–8.1

Jack to łańcuch narzędzi na Androida, który skompilował kod bajtowy Androida w języku Java. Aby korzystać z Jacka, nie musisz nic robić inaczej – wystarczy użyć standardowych poleceń makefile do skompilowania drzewa lub projektu. Android 8.1 to ostatnia wersja wykorzystująca Jacka.

Informacje o Jacku

Jacek działa, jak widać na rys. 1.

Omówienie Jacka.

Rysunek 1. Omówienie Jacka.

Format biblioteki Jack

Jack ma własny format pliku .jack, który zawiera wstępnie skompilowany kod dex dla biblioteki, co pozwala na szybszą kompilację (pre-dex).

Jack library file contents.

Rysunek 2. Zawartość pliku biblioteki Jack.

Dżili

Jak widać na ilustracji poniżej, narzędzie Jill tłumaczy istniejące biblioteki .jar na nowy format.

Proces importowania istniejącej biblioteki „jar”.

Rysunek 3. Proces importowania istniejącej biblioteki .jar.

Serwer kompilacji Jack

Przy pierwszym użyciu Jack uruchamia na komputerze lokalny serwer kompilacji Jack. Ten serwer:

  • Przynosi to przyspieszenie, ponieważ nie trzeba uruchamiać nowej hostowanej JVM JRE, wczytywać kodu Jack, inicjować Jacka i rozgrzewać JIT przy każdej kompilacji. Zapewnia też bardzo krótki czas kompilacji podczas niewielkich kompilacji (na przykład w trybie przyrostowym).
  • Jest to tymczasowe rozwiązanie umożliwiające kontrolowanie liczby równoległych kompilacji Jack. Serwer zapobiega przeciążeniu komputera (problem z pamięcią lub dyskiem), ponieważ ogranicza liczbę równoległych kompilacji.

Serwer Jack wyłącza się po pewnym czasie bezczynności bez wykonywania kompilacji. Wykorzystuje on 2 porty TCP w interfejsie hosta lokalnego i nie jest dostępny zewnętrznie. Wszystkie parametry (np. liczba równoległych kompilacji, limit czasu, liczba portów) można zmienić, edytując plik $HOME/.jack.

$HOME/.jack

Plik $HOME/.jack zawiera te ustawienia zmiennych serwera Jack:

  • SERVER=true włącza funkcję serwera Jacka.
  • SERVER_PORT_SERVICE=8072 ustawia numer portu TCP serwera na potrzeby kompilacji.
  • SERVER_PORT_ADMIN=8073 ustawia numer portu TCP serwera do celów administracyjnych.
  • Element SERVER_COUNT=1 nie jest używany.
  • SERVER_NB_COMPILE=4 określa maksymalną liczbę dozwolonych kompilacji równoległych. SERVER_TIMEOUT=60 określa liczbę sekund bezczynności, przez które serwer musi czekać bez żadnej kompilacji, zanim się wyłączy. SERVER_LOG=${SERVER_LOG:=$SERVER_DIR/jack-$SERVER_PORT_SERVICE.log} ustawia plik, w którym są zapisywane logi serwera. Domyślnie tę zmienną można zastąpić za pomocą zmiennej środowiskowej.
  • JACK_VM_COMMAND=${JACK_VM_COMMAND:=java} ustawia domyślne polecenie używane do uruchamiania JVM na hoście. Domyślnie tę zmienną można zastąpić za pomocą zmiennej środowiskowej.

Rozwiązywanie problemów z kompilacjami Jack

Problem Działanie
Podczas kompilacji komputer przestaje odpowiadać lub kompilacja Jacka kończy się niepowodzeniem z powodu braku pamięci Zmniejsz liczbę jednoczesnych kompilacji Jacka, edytując $HOME/.jack i zmieniając SERVER_NB_COMPILE na niższą wartość.
Kompilacje nie działają, gdy nie można uruchomić serwera w tle Najbardziej prawdopodobną przyczyną jest to, że na komputerze są już używane porty TCP. Zmień raporty, edytując $HOME/.jack (zmienną SERVER_PORT_SERVICESERVER_PORT_ADMIN). Aby odblokować tę sytuację, wyłącz serwer kompilacji Jacka, edytując $HOME/.jack i zmieniając SERVER na false. Niestety spowalnia to kompilację i może wymagać uruchomienia make -j z kontrolą obciążenia (opcja -l z make).
Kompilacja zatrzymuje się bez postępu Aby rozwiązać ten problem, wyłącz serwer działający w tle, używając polecenia jack-admin kill-server, a następnie usuń katalogi tymczasowe znajdujące się w katalogu jack-$USER katalogu tymczasowego (/tmp lub $TMPDIR).

Znajdowanie pliku dziennika Jack

Jeśli uruchomiono polecenie make z docelowym dystrybucją, plik dziennika Jacka znajduje się w folderze $ANDROID_BUILD_TOP/out/dist/logs/jack-server.log. W przeciwnym razie dziennik możesz znaleźć, uruchamiając jack-admin server-log. W przypadku możliwych do odtworzenia awarii wtyczki Jack możesz uzyskać bardziej szczegółowy dziennik, ustawiając tę zmienną:

export ANDROID_JACK_EXTRA_ARGS="--verbose debug --sanity-checks on -D sched.runner=single-threaded"

Użyj standardowych poleceń Makefile, aby skompilować drzewo (lub swój projekt) i dołączyć standardowe dane wyjściowe i błędy. Aby usunąć szczegółowe dzienniki kompilacji, uruchom:

unset ANDROID_JACK_EXTRA_ARGS

Ograniczenia typu Jack

Domyślnie serwer Jack może używać tylko jeden użytkownik na komputerze. Aby obsługiwać dodatkowych użytkowników, wybierz dla każdego z nich inny numer portu i odpowiednio dostosuj parametr SERVER_NB_COMPILE. Serwer Jack możesz też wyłączyć, ustawiając SERVER=false w $HOME/.jack. Kompilacja CTS działa wolno ze względu na bieżącą integrację z usługą vm-tests-tf. Narzędzia do manipulowania bajtowym kodem (np. JaCoCo) nie są obsługiwane.

Użyj gniazda

Jack obsługuje język programowania Java 1.7 i łączy funkcje dodatkowe opisane poniżej.

Pre-dex

Podczas generowania pliku biblioteki Jack obiekt .dex biblioteki jest generowany i zapisywany w pliku biblioteki .jack jako plik pre-dex. Podczas kompilacji Jacek wykorzystuje wstępnie zdefiniowany plik Dex z każdej biblioteki. Wszystkie biblioteki są wstępnie deksowane.

Biblioteki Jack z wersją wstępnego dex.

Rysunek 4. Biblioteki Jack z wersją wstępnego dex.

Jack nie używa ponownie biblioteki w formacie predex, jeśli w kompilacji użyto jej kurczenia, zaciemniania lub przepakowywania.

Kompilacja przyrostowa

Kompilacja przyrostowa oznacza, że ponownie kompilowane są tylko komponenty zmienione od ostatniej kompilacji (oraz ich zależności). Kompilacja przyrostowa może być znacznie szybsza niż pełna kompilacja, jeśli zmiany są ograniczone do zbioru komponentów.

Kompilacja przyrostowa jest domyślnie wyłączona (i automatycznie wyłącza się, gdy włączone jest zmniejszanie, zaciemnianie, przepakowywanie lub starsze wersje wielodeksowe). Aby włączyć kompilacje przyrostowe, dodaj ten wiersz do pliku Android.mk projektu, który chcesz kompilować przyrostowo:

LOCAL_JACK_ENABLED := incremental

Zmniejszanie i zaciemnianie

Jack korzysta z plików konfiguracyjnych ProGuard, które umożliwiają zmniejszanie i zaciemnianie kodu.

Typowe opcje to:

  • @
  • -include
  • -basedirectory
  • -injars
  • -outjars (obsługiwany tylko 1 wyjściowy plik XML)
  • -libraryjars
  • -keep
  • -keepclassmembers
  • -keepclasseswithmembers
  • -keepnames
  • -keepclassmembernames
  • -keepclasseswithmembernames
  • -printseeds

Dostępne są te opcje zmniejszania:

  • -dontshrink

Opcje zaciemniania kodu:

  • -dontobfuscate
  • -printmapping
  • -applymapping
  • -obfuscationdictionary
  • -classobfuscationdictionary
  • -packageobfuscationdictionary
  • -useuniqueclassmembernames
  • -dontusemixedcaseclassnames
  • -keeppackagenames
  • -flattenpackagehierarchy
  • -repackageclasses
  • -keepattributes
  • -adaptclassstrings

Opcje ignorowane:

  • -dontoptimize (Jack nie optymalizuje)
  • -dontpreverify (Jacek nie przeprowadza wstępnej weryfikacji)
  • -skipnonpubliclibraryclasses
  • -dontskipnonpubliclibraryclasses
  • -dontskipnonpubliclibraryclassmembers
  • -keepdirectories
  • -target
  • -forceprocessing
  • -printusage
  • -whyareyoukeeping
  • -optimizations
  • -optimizationpasses
  • -assumenosideeffects
  • -allowaccessmodification
  • -mergeinterfacesaggressively
  • -overloadaggressively
  • -microedition
  • -verbose
  • -dontnote
  • -dontwarn
  • -ignorewarnings
  • -printconfiguration
  • -dump

Przepakowanie

Jack używa plików konfiguracji jarjar do przepakowywania plików. Jack jest zgodny z regułami typu „reguła”, ale nie jest zgodny z regułami typu „zap” ani „keep”.

Obsługa MultiDex

Jack obsługuje wbudowaną i starsza wersję multidexu. Pliki .dex są ograniczone do 65 tys. metod, dlatego aplikacje korzystające z ponad 65 tys. metod należy podzielić na kilka plików .dex. Więcej informacji znajdziesz w artykule Włączanie multidex w przypadku aplikacji, które oferują ponad 64 tys. metod.