Wkrótce system budowania

Przed wydaniem Androida 7.0, Android używał GNU Make wyłącznie do opisywania i wykonywania swoich reguł kompilacji. System kompilacji Make jest powszechnie 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 deweloperzy platform przejdą z Make i zastosują Soong tak szybko, jak to możliwe. Wyślij pytania do grupy dyskusyjnej Google zajmującej się tworzeniem systemu Android, aby uzyskać pomoc.

Co to jest wkrótce?

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

Zapoznaj się z opisem systemu Android Make Build System w projekcie Android Open Source Project (AOSP), aby uzyskać ogólne instrukcje i zmiany systemu kompilacji dla twórców Android.mk , aby dowiedzieć się o modyfikacjach potrzebnych do dostosowania z Make do Soong.

Zobacz wpisy dotyczące kompilacji 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 Soong osiągającą 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)

Niedługo 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 Simple Build Configuration , aby zapoznać się z przykładami konfiguracji Soong specyficznymi dla testu.

Format pliku Android.bp

Z założenia pliki Android.bp są proste. Nie zawierają instrukcji warunkowych ani instrukcji przepływu sterowania; 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 wstępnie utworzonych modułach, które mogą się powtarzać.

Właściwość srcs określa pliki źródłowe użyte do zbudowania modułu jako listę ciągów. Możesz odwoływać się do danych wyjściowych innych modułów, które generują pliki źródłowe, takie jak genrule lub filegroup , przy użyciu składni odwołania do modułu ":<module-name>" .

Aby uzyskać listę prawidłowych typów modułów i ich właściwości, zobacz Soong Modules Reference .

Rodzaje

Zmienne i właściwości są silnie wpisane, przy czym zmienne są dynamicznie oparte na pierwszym przypisaniu, a właściwości są ustawiane statycznie przez typ modułu. Obsługiwane typy to:

  • Boole'a ( true lub false )
  • Liczby całkowite ( int )
  • Ciągi ( "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ą mieć końcowe przecinki po ostatniej wartości.

Globy

Właściwości, które pobierają listę plików, takie jak srcs , mogą również przyjmować wzorce glob. Wzorce glob mogą zawierać normalny symbol wieloznaczny UNIX * , na przykład *.java . Wzorce glob mogą również zawierać pojedynczy symbol wieloznaczny ** jako element ścieżki, który odpowiada zero lub większej liczbie elementów ścieżki. Na przykład java/**/*.java pasuje zarówno do java/Main.java , jak 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ą objęte zakresem pozostałej części pliku, w którym są zadeklarowane, jak również wszelkich podrzędnych plików Blueprint. Zmienne są niezmienne z jednym wyjątkiem: można je dołączyć za pomocą przypisania += , ale tylko przed wywołaniem.

Uwagi

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

Operatorzy

Łańcuchy, listy łańcuchów i mapy mogą być dołączane za pomocą operatora +. Liczby całkowite można sumować za pomocą operatora + . Dołączanie mapy tworzy sumę kluczy w obu mapach, dołączając wartości dowolnych kluczy, które są obecne na obu mapach.

Warunkowe

Soong nie obsługuje instrukcji 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, w której jedna z wartości na mapie jest wybierana 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 program do formatowania 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 wiersze po każdym elemencie listy wieloelementowej oraz końcowy przecinek w listach i mapach.

Moduły specjalne

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

Moduły domyślne

Moduł ustawień domyślnych może służyć do powtarzania 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 skompilowane typy modułów pozwalają modułowi mieć taką samą nazwę, jak jego odpowiedniki oparte na źródle. Na przykład może istnieć cc_prebuilt_binary o nazwie foo , gdy istnieje już cc_binary o tej samej nazwie. Daje to programistom elastyczność w wyborze wersji, którą mają uwzględnić w ich produkcie końcowym. Jeśli konfiguracja kompilacji zawiera obie wersje, prefer wartość flagi we wstępnie zbudowanej definicji modułu określa, która wersja ma priorytet. Zwróć uwagę, że niektóre wstępnie zbudowane moduły mają nazwy, które nie zaczynają się od prebuilt , na przykład android_app_import .

Moduły przestrzeni nazw

Do czasu pełnej konwersji Androida z Make na Soong, konfiguracja produktu Make musi określać wartość PRODUCT_SOONG_NAMESPACES . Jego wartość powinna być rozdzieloną spacjami listą przestrzeni nazw, które Soong eksportuje do Make, aby zostały zbudowane 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 oddzielnej przestrzeni nazw. Przestrzeń nazw można zadeklarować w następujący sposób:

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

Zauważ, że przestrzeń nazw nie ma właściwości name; jego ścieżka jest automatycznie przypisywana jako nazwa.

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

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

  1. Następnie, jeśli D jest w pełni kwalifikowaną nazwą postaci //namespace:module , tylko określona przestrzeń nazw jest przeszukiwana dla określonej nazwy modułu.
  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. Wreszcie Soong szuka w głównej przestrzeni nazw.