Skorzystaj z informacji zawartych na tej stronie, aby utworzyć pliki makefile dla swojego urządzenia i produktu.
Każdy nowy moduł systemu Android musi mieć plik konfiguracyjny, aby kierować system kompilacji z metadanymi modułu, zależnościami czasu kompilacji i instrukcjami pakowania. Android korzysta z systemu kompilacji Soong . Zobacz Budowanie systemu Android , aby uzyskać więcej informacji o systemie kompilacji Androida.
Zrozumienie warstw kompilacji
Hierarchia kompilacji obejmuje warstwy abstrakcji, które odpowiadają fizycznej budowie urządzenia. Warstwy te są opisane w poniższej tabeli. Każda warstwa odnosi się do warstwy nad nią w relacji jeden-do-wielu. Na przykład architektura może mieć więcej niż jedną tablicę, a każda tablica może mieć więcej niż jeden produkt. Możesz zdefiniować element w danej warstwie jako specjalizację elementu w tej samej warstwie, co eliminuje kopiowanie i ułatwia konserwację.
Warstwa | Przykład | Opis |
---|---|---|
Produkt | myProduct, myProduct_eu, myProduct_eu_fr, j2, sdk | Warstwa produktu definiuje specyfikację funkcji produktu wysyłkowego, taką jak moduły do zbudowania, obsługiwane języki i konfiguracja dla różnych lokalizacji. Innymi słowy jest to nazwa całego produktu. Zmienne specyficzne dla produktu są zdefiniowane w plikach makefile definicji produktu. Produkt może dziedziczyć z innych definicji produktów, co upraszcza konserwację. Typową metodą jest utworzenie produktu podstawowego zawierającego funkcje, które mają zastosowanie do wszystkich produktów, a następnie utworzenie wariantów produktu na podstawie tego produktu podstawowego. Na przykład dwa produkty, które różnią się tylko radiotelefonami (CDMA w porównaniu z GSM), mogą dziedziczyć z tego samego produktu podstawowego, który nie definiuje radia. |
Tablica/urządzenie | marlin, niebieska linia, koral | Warstwa płyty/urządzenia reprezentuje fizyczną warstwę tworzywa sztucznego na urządzeniu (tj. wzór przemysłowy urządzenia). Ta warstwa reprezentuje również sam schemat produktu. Należą do nich urządzenia peryferyjne na płycie i ich konfiguracja. Użyte nazwy są jedynie kodami dla różnych konfiguracji płyty/urządzenia. |
Łuk | ramię, x86, ramię 64, x86_64 | Warstwa architektury opisuje konfigurację procesora i binarny interfejs aplikacji (ABI) działający na płycie. |
Korzystanie z wariantów kompilacji
Podczas kompilowania dla konkretnego produktu warto mieć niewielkie różnice w ostatecznej kompilacji wydania. W definicji modułu moduł może określać tagi z LOCAL_MODULE_TAGS
, które mogą mieć jedną lub więcej wartości optional
(domyślnie), debug
i eng
.
Jeśli moduł nie określa tagu (przez LOCAL_MODULE_TAGS
), jego tag jest domyślnie optional
. Opcjonalny moduł jest instalowany tylko wtedy, gdy jest to wymagane przez konfigurację produktu z PRODUCT_PACKAGES
.
Są to obecnie zdefiniowane warianty kompilacji.
Wariant | Opis |
---|---|
eng | To jest domyślny smak.
|
user | Wariant miał być bitami ostatecznego wydania.
|
userdebug | Tak samo jak user , z tymi wyjątkami:
|
Wytyczne dotyczące debugowania użytkowników
Uruchamianie kompilacji userdebug podczas testowania pomaga deweloperom urządzeń zrozumieć wydajność i moc wydań w fazie rozwoju. Aby zachować spójność między kompilacjami użytkownika i użytkownika debugowania oraz uzyskać wiarygodne metryki w kompilacjach używanych do debugowania, programiści urządzeń powinni przestrzegać następujących wskazówek:
- userdebug jest zdefiniowany jako kompilacja użytkownika z włączonym dostępem administratora, z wyjątkiem:
- aplikacje tylko do debugowania użytkownika, które są uruchamiane tylko na żądanie przez użytkownika
- Operacje, które działają tylko podczas bezczynności konserwacji (na ładowarce/w pełni naładowanej), takie jak używanie
dex2oatd
lubdex2oat
do kompilacji w tle
- Nie uwzględniaj funkcji, które są domyślnie włączone/wyłączone na podstawie typu kompilacji. Deweloperzy są zniechęceni do korzystania z jakiejkolwiek formy rejestrowania, która wpływa na żywotność baterii, takiej jak rejestrowanie debugowania lub zrzucanie sterty.
- Wszelkie funkcje debugowania, które są domyślnie włączone w userdebug, powinny być jasno zdefiniowane i udostępniane wszystkim deweloperom pracującym nad projektem. Funkcje debugowania należy włączać tylko przez ograniczony czas, dopóki problem, który próbujesz debugować, nie zostanie rozwiązany.
Dostosowywanie kompilacji za pomocą nakładek zasobów
System kompilacji Android używa nakładek zasobów, aby dostosować produkt w czasie kompilacji. Nakładki zasobów określają pliki zasobów, które są stosowane poza wartościami domyślnymi. Aby korzystać z nakładek zasobów, zmodyfikuj plik budowy projektu, ustawiając PRODUCT_PACKAGE_OVERLAYS
na ścieżkę względną do katalogu najwyższego poziomu. Ta ścieżka staje się ukrytym katalogiem głównym przeszukiwanym wraz z bieżącym katalogiem głównym, gdy system kompilacji szuka zasobów.
Najczęściej dostosowywane ustawienia są zawarte w plikach frameworks/base/core/res/res/values/config.xml .
Aby skonfigurować nakładkę zasobów w tym pliku, dodaj katalog nakładek do pliku budowania projektu, korzystając z jednej z następujących czynności:
PRODUCT_PACKAGE_OVERLAYS := device/device-implementer/device-name/overlay
lub
PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay
Następnie dodaj plik nakładki do katalogu, na przykład:
vendor/foobar/overlay/frameworks/base/core/res/res/values/config.xml
Wszelkie ciągi lub tablice ciągów znalezione w pliku nakładki config.xml
zastępują te znalezione w oryginalnym pliku.
Budowanie produktu
Pliki źródłowe urządzenia można organizować na wiele różnych sposobów. Oto krótki opis jednego ze sposobów organizacji implementacji Pixela.
Pixel jest zaimplementowany z główną konfiguracją urządzenia o nazwie marlin
. Na podstawie tej konfiguracji urządzenia tworzony jest produkt z plikiem makefile definicji produktu, który deklaruje informacje specyficzne dla produktu dotyczące urządzenia, takie jak nazwa i model. Możesz wyświetlić katalog device/google/marlin
, aby zobaczyć, jak to wszystko jest skonfigurowane.
Pisanie plików makefile produktów
Poniższe kroki opisują, jak skonfigurować pliki makefile produktów w sposób podobny do tego w linii produktów Pixel:
- Utwórz katalog
device/ <company-name> / <device-name>
dla swojego produktu. Na przykładdevice/google/marlin
. Ten katalog będzie zawierał kod źródłowy urządzenia wraz z plikami makefile do ich zbudowania. - Utwórz plik makefile
device.mk
, który deklaruje pliki i moduły potrzebne dla urządzenia. Na przykład zobaczdevice/google/marlin/device-marlin.mk
. - Utwórz plik makefile definicji produktu, aby utworzyć określony produkt na podstawie urządzenia. Poniższy plik makefile jest pobierany z
device/google/marlin/aosp_marlin.mk
jako przykład. Zwróć uwagę, że produkt dziedziczy z plikówdevice/google/marlin/device-marlin.mk
ivendor/google/marlin/device-vendor-marlin.mk
przez plik makefile, jednocześnie deklarując informacje dotyczące produktu, takie jak nazwa, marka, i model.# Inherit from the common Open Source product configuration $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk) PRODUCT_NAME := aosp_marlin PRODUCT_DEVICE := marlin PRODUCT_BRAND := Android PRODUCT_MODEL := AOSP on msm8996 PRODUCT_MANUFACTURER := Google PRODUCT_RESTRICT_VENDOR_FILES := true PRODUCT_COPY_FILES += device/google/marlin/fstab.common:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.marlin $(call inherit-product, device/google/marlin/device-marlin.mk) $(call inherit-product-if-exists, vendor/google_devices/marlin/device-vendor-marlin.mk) PRODUCT_PACKAGES += \ Launcher3QuickStep \ WallpaperPicker
Zobacz Ustawianie zmiennych definicji produktu, aby uzyskać dodatkowe zmienne specyficzne dla produktu, które możesz dodać do swoich plików makefile.
- Utwórz plik
AndroidProducts.mk
, który wskazuje pliki makefile produktu. W tym przykładzie potrzebny jest tylko plik makefile definicji produktu. Poniższy przykład pochodzi zdevice/google/marlin/AndroidProducts.mk
(który zawiera zarówno marlin, Pixel, jak i sailfish, Pixel XL, który współdzielił większość konfiguracji):PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/aosp_marlin.mk \ $(LOCAL_DIR)/aosp_sailfish.mk COMMON_LUNCH_CHOICES := \ aosp_marlin-userdebug \ aosp_sailfish-userdebug
- Utwórz plik makefile
BoardConfig.mk
, który zawiera konfiguracje specyficzne dla tablicy. Na przykład zobaczdevice/google/marlin/BoardConfig.mk
. - Tylko w przypadku systemu Android 9 i starszych , utwórz plik
vendorsetup.sh
, aby dodać swój produkt („zestaw obiadowy”) do kompilacji wraz z wariantem kompilacji oddzielonym myślnikiem. Na przykład:add_lunch_combo <product-name>-userdebug
- W tym momencie możesz stworzyć więcej wariantów produktu w oparciu o to samo urządzenie.
Ustawianie zmiennych definicji produktu
Zmienne specyficzne dla produktu są zdefiniowane w pliku makefile produktu. W tabeli przedstawiono niektóre zmienne przechowywane w pliku definicji produktu.
Zmienny | Opis | Przykład |
---|---|---|
PRODUCT_AAPT_CONFIG | aapt konfiguracje do użycia podczas tworzenia pakietów. | |
PRODUCT_BRAND | Marka (na przykład przewoźnik), do której oprogramowanie jest dostosowane, jeśli istnieje. | |
PRODUCT_CHARACTERISTICS | cechy aapt umożliwiające dodawanie zasobów specyficznych dla wariantu do pakietu. | tablet , nosdcard |
PRODUCT_COPY_FILES | Lista słów, takich jak source_path:destination_path . Plik w ścieżce źródłowej należy skopiować do ścieżki docelowej podczas tworzenia tego produktu. Reguły kroków kopiowania są zdefiniowane w config/makefile . | |
PRODUCT_DEVICE | Nazwa wzoru przemysłowego. Jest to również nazwa płyty, a system kompilacji używa jej do zlokalizowania BoardConfig.mk . | tuna |
PRODUCT_LOCALES | Rozdzielona spacjami lista dwuliterowych kodów języka i dwuliterowych par kodów krajów, które opisują kilka ustawień użytkownika, takich jak język interfejsu użytkownika i godzina, data i formatowanie waluty. Pierwszy język wymieniony w PRODUCT_LOCALES jest używany jako domyślny język produktu. | en_GB , de_DE , es_ES , fr_CA |
PRODUCT_MANUFACTURER | Nazwa producenta. | acme |
PRODUCT_MODEL | Widoczna dla użytkownika końcowego nazwa produktu końcowego. | |
PRODUCT_NAME | Widoczna dla użytkownika końcowego nazwa całego produktu. Pojawia się na ekranie Ustawienia > Informacje . | |
PRODUCT_OTA_PUBLIC_KEYS | Lista bezprzewodowych kluczy publicznych (OTA) dla produktu. | |
PRODUCT_PACKAGES | Lista pakietów APK i modułów do zainstalowania. | Kontakty z kalendarza |
PRODUCT_PACKAGE_OVERLAYS | Wskazuje, czy użyć zasobów domyślnych, czy dodać nakładki specyficzne dla produktu. | vendor/acme/overlay |
PRODUCT_SYSTEM_PROPERTIES | Lista przypisań właściwości systemowych w formacie "key=value" dla partycji systemowej. Właściwości systemu dla innych partycji można ustawić za pomocą PRODUCT_<PARTITION>_PROPERTIES , tak jak w PRODUCT_VENDOR_PROPERTIES dla partycji dostawcy. Obsługiwane nazwy partycji: SYSTEM , VENDOR , ODM , SYSTEM_EXT i PRODUCT . |
Konfigurowanie domyślnego języka systemu i filtra ustawień regionalnych
Użyj tych informacji, aby skonfigurować domyślny język i filtr ustawień regionalnych systemu, a następnie włącz filtr ustawień regionalnych dla nowego typu urządzenia.
Nieruchomości
Skonfiguruj zarówno język domyślny, jak i filtr ustawień regionalnych systemu, korzystając z dedykowanych właściwości systemu:
-
ro.product.locale
: do ustawiania domyślnych ustawień regionalnych. Jest to początkowo ustawione na pierwsze ustawienia regionalne w zmiennejPRODUCT_LOCALES
; możesz zastąpić tę wartość. (Aby uzyskać więcej informacji, zobacz tabelę Ustawianie zmiennych definicji produktu ). -
ro.localization.locale_filter
: do ustawiania filtru ustawień regionalnych, przy użyciu wyrażenia regularnego stosowanego do nazw ustawień regionalnych. Na przykład:- Filtr włączający:
^(de-AT|de-DE|en|uk).*
- dopuszcza tylko niemieckie (warianty austriackie i niemieckie), wszystkie angielskie warianty angielskiego i ukraińskie - Filtr wykluczający:
^(?!de-IT|es).*
- wyklucza niemiecki (wariant włoski) i wszystkie warianty hiszpańskiego.
- Filtr włączający:
Włączenie filtra ustawień regionalnych
Aby włączyć filtr, ustaw wartość ciągu właściwości systemowej ro.localization.locale_filter
.
Ustawiając wartość właściwości filtra i domyślny język za pomocą oem/oem.prop
podczas kalibracji fabrycznej, można skonfigurować ograniczenia bez umieszczania filtra w obrazie systemu. Możesz upewnić się, że te właściwości są pobierane z partycji OEM, dodając je do zmiennej PRODUCT_OEM_PROPERTIES
, jak wskazano poniżej:
# Delegation for OEM customization PRODUCT_OEM_PROPERTIES += \ ro.product.locale \ ro.localization.locale_filter
Następnie w produkcji rzeczywiste wartości są zapisywane w oem/oem.prop
, aby odzwierciedlić wymagania docelowe. Dzięki takiemu podejściu wartości domyślne są zachowywane podczas przywracania ustawień fabrycznych, więc początkowe ustawienia wyglądają dokładnie tak, jak pierwsza konfiguracja dla użytkownika.
Ustawianie ADB_VENDOR_KEYS do połączenia przez USB
Zmienna środowiskowa ADB_VENDOR_KEYS
umożliwia producentom urządzeń dostęp do kompilacji debugowalnych (-userdebug i -eng, ale nie -user) przez adb bez ręcznej autoryzacji. Zwykle adb generuje unikalny klucz uwierzytelniania RSA dla każdego komputera klienckiego, który wysyła do dowolnego podłączonego urządzenia. To jest klucz RSA wyświetlany w oknie autoryzacji adb. Alternatywnie możesz wbudować znane klucze do obrazu systemu i udostępnić je klientowi adb. Jest to przydatne do tworzenia systemu operacyjnego, a zwłaszcza do testowania, ponieważ pozwala uniknąć ręcznej interakcji z oknem autoryzacji adb.
Aby utworzyć klucze dostawcy, jedna osoba (zazwyczaj menedżer ds. wydania) powinna:
- Wygeneruj parę kluczy za pomocą
adb keygen
. W przypadku urządzeń Google Google generuje nową parę kluczy dla każdej nowej wersji systemu operacyjnego. - Sprawdź pary kluczy gdzieś w drzewie źródłowym. Google przechowuje je na przykład w
vendor/google/security/adb/
. - Ustaw zmienną kompilacji
PRODUCT_ADB_KEYS
tak, aby wskazywała katalog kluczy. Google robi to, dodając plikAndroid.mk
w katalogu kluczy o treściPRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub
, co pomaga pamiętać o wygenerowaniu nowej pary kluczy dla każdej wersji systemu operacyjnego.
Oto plik makefile, którego Google używa w katalogu, w którym przechowujemy nasze zarejestrowane pary kluczy dla każdej wersji:
PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub ifeq ($(wildcard $(PRODUCT_ADB_KEYS)),) $(warning ========================) $(warning The adb key for this release) $(warning ) $(warning $(PRODUCT_ADB_KEYS)) $(warning ) $(warning does not exist. Most likely PLATFORM_VERSION in build/core/version_defaults.mk) $(warning has changed and a new adb key needs to be generated.) $(warning ) $(warning Please run the following commands to create a new key:) $(warning ) $(warning make -j8 adb) $(warning LOGNAME=android-eng HOSTNAME=google.com adb keygen $(patsubst %.pub,%,$(PRODUCT_ADB_KEYS))) $(warning ) $(warning and upload/review/submit the changes) $(warning ========================) $(error done) endif
Aby użyć tych kluczy dostawcy, inżynier musi tylko ustawić zmienną środowiskową ADB_VENDOR_KEYS
, aby wskazywała katalog, w którym przechowywane są pary kluczy. To mówi adb
, aby najpierw wypróbował te klucze kanoniczne, zanim powróci do wygenerowanego klucza hosta, który wymaga ręcznej autoryzacji. Gdy adb
nie może połączyć się z nieautoryzowanym urządzeniem, komunikat o błędzie zasugeruje ustawienie ADB_VENDOR_KEYS
, jeśli nie jest jeszcze ustawione.