Wkrótce zbuduj system

Przed wydaniem Androida 7.0 Android używał GNU Make wyłącznie do opisywania i wykonywania zasad kompilacji. System kompilacji Make jest szeroko obsługiwany i używany, ale w skali Androida stał się powolny, podatny na błędy, nieskalowalny i trudny do przetestowania. System kompilacji Soong zapewnia elastyczność wymaganą w przypadku kompilacji Androida.

Z tego powodu oczekuje się, że twórcy platform przejdą z Make i zaadoptują Soong tak szybko, jak to możliwe. Wyślij pytania do grupy dyskusyjnej Google zajmującej się tworzeniem Androida , aby otrzymać pomoc.

Co to jest wkrótce?

System kompilacji Soong został wprowadzony w systemie Android 7.0 (Nougat) w celu zastąpienia Make. Wykorzystuje narzędzie do klonowania Kati GNU Make i komponent systemu kompilacji Ninja , aby przyspieszyć kompilację Androida.

Zobacz opis systemu Android Make Build w projekcie Android Open Source Project (AOSP), aby uzyskać ogólne instrukcje , a także Zmiany systemu kompilacji dla autorów Android.mk, aby dowiedzieć się o modyfikacjach niezbędnych do dostosowania się z Make do Soon.

Zobacz wpisy związane z kompilacją w glosariuszu, aby uzyskać definicje kluczowych terminów, oraz pliki referencyjne Soong, aby uzyskać szczegółowe informacje.

Porównanie marki i wkrótce

Oto porównanie konfiguracji Make z Soongiem wykonującym to samo w pliku konfiguracyjnym Soong (Blueprint lub .bp ).

Zrób przykład

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libxmlrpc++
LOCAL_MODULE_HOST_OS := linux

LOCAL_RTTI_FLAG := -frtti
LOCAL_CPPFLAGS := -Wall -Werror -fexceptions
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src

LOCAL_SRC_FILES := $(call \
     all-cpp-files-under,src)
include $(BUILD_SHARED_LIBRARY)

Wkrótce przykład

cc_library_shared {
     name: “libxmlrpc++”,

     rtti: true,
     cppflags: [
           “-Wall”,
           “-Werror”,
           “-fexceptions”,
     ],
     export_include_dirs: [“src”],
     srcs: [“src/**/*.cpp”],

     target: {
           darwin: {
                enabled: false,
           },
     },
}

Zobacz konfigurację prostej kompilacji , aby zapoznać się z przykładami konfiguracji Soonga specyficznymi dla testu.

Format pliku Android.bp

Z założenia pliki Android.bp są proste. Nie zawierają instrukcji warunkowych ani instrukcji przepływu sterującego; cała złożoność jest obsługiwana przez logikę kompilacji napisaną w Go. Jeśli to możliwe, składnia i semantyka plików Android.bp są podobne do plików Bazel BUILD .

Moduły

Moduł w pliku Android.bp zaczyna się od typu modułu , po którym następuje zestaw właściwości w name: "value", format:

cc_binary {
    name: "gzip",
    srcs: ["src/test/minigzip.c"],
    shared_libs: ["libz"],
    stl: "none",
}

Każdy moduł musi mieć właściwość name , a wartość musi być unikatowa we wszystkich plikach Android.bp , z wyjątkiem wartości właściwości name w przestrzeniach nazw i gotowych modułach, które mogą się powtarzać.

Właściwość srcs określa pliki źródłowe użyte do zbudowania modułu w postaci listy ciągów znaków. Możesz odwoływać się do danych wyjściowych innych modułów tworzących pliki źródłowe, takich jak genrule lub filegroup , używając składni odniesienia do modułu ":<module-name>" .

Aby zapoznać się z listą prawidłowych typów modułów i ich właściwości, zobacz Dokumentacja modułów Soong .

Typy

Zmienne i właściwości są silnie typowane, ze zmiennymi dynamicznie opartymi na pierwszym przypisaniu, a właściwości ustawiane statycznie przez typ modułu. Obsługiwane typy to:

  • Wartości logiczne ( true lub false )
  • Liczby całkowite ( int )
  • Ciągi znaków ( "string" )
  • Listy ciągów ( ["string1", "string2"] )
  • Mapy ( {key1: "value1", key2: ["value2"]}

Mapy mogą zawierać wartości dowolnego typu, w tym mapy zagnieżdżone. Listy i mapy mogą zawierać przecinki po ostatniej wartości.

Globy

Właściwości pobierające listę plików, takie jak srcs , mogą również przyjmować wzorce globalne. Wzorce globów mogą zawierać normalne symbole wieloznaczne UNIX * , na przykład *.java . Wzorce glob mogą również zawierać pojedynczy symbol wieloznaczny ** jako element ścieżki, który pasuje do zera lub większej liczby elementów ścieżki. Na przykład java/**/*.java dopasowuje wzorce java/Main.java i java/com/android/Main.java .

Zmienne

Plik Android.bp może zawierać przypisania zmiennych najwyższego poziomu:

gzip_srcs = ["src/test/minigzip.c"],
cc_binary {
    name: "gzip",
    srcs: gzip_srcs,
    shared_libs: ["libz"],
    stl: "none",
}

Zmienne są ograniczone do pozostałej części pliku, w którym są zadeklarowane, a także do wszelkich podrzędnych plików Blueprint. Zmienne są niezmienne z jednym wyjątkiem: można do nich dołączyć przypisanie += , ale tylko przed odwołaniem do nich.

Uwagi

Pliki Android.bp mogą zawierać wielowierszowe /* */ komentarze w stylu C i jednowierszowe // w stylu C++.

Operatorzy

Ciągi, listy ciągów i mapy można dołączać za pomocą operatora +. Liczby całkowite można podsumować za pomocą operatora + . Dołączenie mapy powoduje utworzenie unii kluczy na obu mapach, poprzez dodanie wartości dowolnych kluczy obecnych na obu mapach.

Warunki

Soong nie obsługuje warunków warunkowych w plikach Android.bp . Zamiast tego złożoność reguł kompilacji, która wymagałaby warunków warunkowych, jest obsługiwana w Go, gdzie można używać funkcji języka wysokiego poziomu i można śledzić niejawne zależności wprowadzone przez warunki. Większość warunków warunkowych jest konwertowana na właściwość mapy, gdzie wybierana jest jedna z wartości na mapie i dołączana do właściwości najwyższego poziomu.

Na przykład, aby obsługiwać pliki specyficzne dla architektury:

cc_library {
    ...
    srcs: ["generic.cpp"],
    arch: {
        arm: {
            srcs: ["arm.cpp"],
        },
        x86: {
            srcs: ["x86.cpp"],
        },
    },
}

Formater

Soong zawiera kanoniczny formater plików Blueprint, podobny do gofmt . Aby rekurencyjnie sformatować wszystkie pliki Android.bp w bieżącym katalogu, uruchom:

bpfmt -w .

Format kanoniczny obejmuje wcięcia z czterema spacjami, nowe linie po każdym elemencie listy wieloelementowej oraz końcowy przecinek na listach i mapach.

Moduły specjalne

Niektóre specjalne grupy modułów mają unikalne cechy.

Domyślne moduły

Modułu defaults można użyć do powtórzenia tych samych właściwości w wielu modułach. Na przykład:

cc_defaults {
    name: "gzip_defaults",
    shared_libs: ["libz"],
    stl: "none",
}

cc_binary {
    name: "gzip",
    defaults: ["gzip_defaults"],
    srcs: ["src/test/minigzip.c"],
}

Gotowe moduły

Niektóre wstępnie zbudowane typy modułów pozwalają na to, aby moduł miał taką samą nazwę jak jego odpowiedniki oparte na źródle. Na przykład może istnieć plik cc_prebuilt_binary o nazwie foo , gdy istnieje już plik cc_binary o tej samej nazwie. Daje to programistom elastyczność w wyborze wersji, którą chcą uwzględnić w swoim produkcie końcowym. Jeśli konfiguracja kompilacji zawiera obie wersje, wartość flagi prefer w definicji wstępnie zbudowanego modułu określa, która wersja ma priorytet. Zauważ, że niektóre prekompilowane moduły mają nazwy, które nie zaczynają się od prebuilt , na przykład android_app_import .

Moduły przestrzeni nazw

Dopóki system Android nie zostanie w pełni przekonwertowany z Make na Soong, konfiguracja produktu Make musi zawierać wartość PRODUCT_SOONG_NAMESPACES . Jego wartością powinna być oddzielona spacjami lista przestrzeni nazw, które Soong eksportuje do Make w celu zbudowania za pomocą polecenia m . Po zakończeniu konwersji Androida na Soong szczegóły włączania przestrzeni nazw mogą ulec zmianie.

Soong umożliwia modułom w różnych katalogach określenie tej samej nazwy, o ile każdy moduł jest zadeklarowany w osobnej przestrzeni nazw. Przestrzeń nazw można zadeklarować w następujący sposób:

soong_namespace {
    imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}

Należy pamiętać, że przestrzeń nazw nie ma właściwości name; jego ścieżka jest automatycznie przypisywana jako nazwa.

Każdemu modułowi Soong przypisana jest przestrzeń nazw na podstawie jego lokalizacji w drzewie. Uważa się, że każdy moduł Soong znajduje się w przestrzeni nazw zdefiniowanej przez soong_namespace znalezioną w pliku Android.bp w katalogu bieżącym lub katalogu najbliższego przodka. Jeśli nie zostanie znaleziony żaden taki moduł soong_namespace , uważa się, że moduł znajduje się w ukrytej głównej przestrzeni nazw.

Oto przykład: Soong próbuje rozwiązać zależność D zadeklarowaną przez moduł M w przestrzeni nazw N, która importuje przestrzenie nazw I1, I2, I3…

  1. Następnie, jeśli D jest w pełni kwalifikowaną nazwą w postaci //namespace:module , pod kątem określonej nazwy modułu przeszukiwana jest tylko określona przestrzeń nazw.
  2. W przeciwnym razie Soong najpierw szuka modułu o nazwie D zadeklarowanego w przestrzeni nazw N.
  3. Jeśli ten moduł nie istnieje, Soong szuka modułu o nazwie D w przestrzeniach nazw I1, I2, I3…
  4. Na koniec Soong zagląda do głównej przestrzeni nazw.