Song-Build-System

Vor der Veröffentlichung von Android 7.0 verwendete Android GNU Make ausschließlich zur Beschreibung und Ausführung seiner Build-Regeln. Das Make-Build-System wird weitgehend unterstützt und verwendet, wurde jedoch im Android-Maßstab langsam, fehleranfällig, nicht skalierbar und schwer zu testen. Das Soong-Build-System bietet die für Android-Builds erforderliche Flexibilität.

Aus diesem Grund wird von Plattformentwicklern erwartet, dass sie schnellstmöglich von Make auf Soong umsteigen und Soong übernehmen. Senden Sie Fragen an die Google-Gruppe , die Android entwickelt, um Unterstützung zu erhalten.

Was ist Soong?

Das Soong-Build-System wurde in Android 7.0 (Nougat) eingeführt, um Make zu ersetzen. Es nutzt das Kati GNU Make-Klontool und die Ninja- Build-Systemkomponente, um die Erstellung von Android-Geräten zu beschleunigen.

Allgemeine Anweisungen finden Sie in der Beschreibung des Android Make Build Systems im Android Open Source Project (AOSP) und Build System Changes for Android.mk Writers , um mehr über die erforderlichen Änderungen für die Anpassung von Make an Soong zu erfahren.

Definitionen wichtiger Begriffe finden Sie in den Build-bezogenen Einträgen im Glossar und in den Soong-Referenzdateien für vollständige Details.

Make- und Soong-Vergleich

Hier ist ein Vergleich zwischen Make-Konfiguration und Soong, der dasselbe in einer Soong-Konfigurationsdatei (Blueprint oder .bp ) erreicht.

Machen Sie ein Beispiel

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)

Kurzes Beispiel

cc_library_shared {
     name: “libxmlrpc++”,

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

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

Testspezifische Soong-Konfigurationsbeispiele finden Sie unter Einfache Build-Konfiguration .

Android.bp-Dateiformat

Android.bp Dateien sind vom Design her einfach. Sie enthalten keine Bedingungen oder Kontrollflussanweisungen; Die gesamte Komplexität wird durch die in Go geschriebene Build-Logik bewältigt. Wenn möglich, ähneln Syntax und Semantik von Android.bp Dateien denen von Bazel BUILD-Dateien .

Module

Ein Modul in einer Android.bp Datei beginnt mit einem Modultyp , gefolgt von einer Reihe von Eigenschaften im name: "value", Format:

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

Jedes Modul muss über eine name verfügen und der Wert muss in allen Android.bp Dateien eindeutig sein, mit Ausnahme der name in Namespaces und vorgefertigten Modulen, die sich wiederholen können.

Die Eigenschaft srcs gibt die zum Erstellen des Moduls verwendeten Quelldateien als Liste von Zeichenfolgen an. Sie können auf die Ausgabe anderer Module verweisen, die Quelldateien erzeugen, wie z. B. genrule oder filegroup , indem Sie die Modulreferenzsyntax ":<module-name>" verwenden.

Eine Liste der gültigen Modultypen und ihrer Eigenschaften finden Sie in der Soong Modules Reference .

Typen

Variablen und Eigenschaften sind stark typisiert, wobei Variablen dynamisch auf der ersten Zuweisung basieren und Eigenschaften statisch durch den Modultyp festgelegt werden. Die unterstützten Typen sind:

  • Boolesche Werte ( true oder false )
  • Ganze Zahlen ( int )
  • Zeichenfolgen ( "string" )
  • Listen von Strings ( ["string1", "string2"] )
  • Karten ( {key1: "value1", key2: ["value2"]} )

Karten können Werte jeglicher Art enthalten, einschließlich verschachtelter Karten. Listen und Karten können nach dem letzten Wert Kommas enthalten.

Kugeln

Eigenschaften, die eine Liste von Dateien annehmen, wie z. B. srcs , können auch Glob-Muster annehmen. Glob-Muster können den normalen UNIX-Platzhalter * enthalten, zum Beispiel *.java . Glob-Muster können auch einen einzelnen ** Platzhalter als Pfadelement enthalten, der mit null oder mehr Pfadelementen übereinstimmt. Beispielsweise entspricht java/**/*.java sowohl den Mustern java/Main.java als auch java/com/android/Main.java .

Variablen

Eine Android.bp Datei kann Variablenzuweisungen der obersten Ebene enthalten:

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

Variablen gelten für den Rest der Datei, in der sie deklariert sind, sowie für alle untergeordneten Blueprint-Dateien. Variablen sind mit einer Ausnahme unveränderlich: Sie können mit einer += Zuweisung angehängt werden, jedoch nur, bevor auf sie verwiesen wurde.

Kommentare

Android.bp Dateien können mehrzeilige /* */ C-Stil und einzeilige // Kommentare im C++-Stil enthalten.

Betreiber

Strings, String-Listen und Karten können mit dem +-Operator angehängt werden. Ganzzahlen können mit dem + -Operator summiert werden. Das Anhängen einer Karte erzeugt die Vereinigung der Schlüssel in beiden Karten und fügt die Werte aller Schlüssel an, die in beiden Karten vorhanden sind.

Bedingungen

Soong unterstützt keine Bedingungen in Android.bp Dateien. Stattdessen wird die Komplexität von Build-Regeln, die Bedingungen erfordern würden, in Go behandelt, wo Hochsprachenfunktionen verwendet werden können und implizite Abhängigkeiten, die durch Bedingungen eingeführt werden, verfolgt werden können. Die meisten Bedingungen werden in eine Karteneigenschaft umgewandelt, wobei einer der Werte in der Karte ausgewählt und an die Eigenschaften der obersten Ebene angehängt wird.

Um beispielsweise architekturspezifische Dateien zu unterstützen:

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

Formatierer

Soong enthält einen kanonischen Formatierer für Blueprint-Dateien, ähnlich wie gofmt . Führen Sie Folgendes aus, um alle Android.bp Dateien im aktuellen Verzeichnis rekursiv neu zu formatieren:

bpfmt -w .

Das kanonische Format umfasst Einzüge mit vier Leerzeichen, neue Zeilen nach jedem Element einer Liste mit mehreren Elementen und ein abschließendes Komma in Listen und Karten.

Spezielle Module

Einige spezielle Modulgruppen weisen einzigartige Eigenschaften auf.

Standardmodule

Ein Standardmodul kann verwendet werden, um dieselben Eigenschaften in mehreren Modulen zu wiederholen. Zum Beispiel:

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

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

Vorgefertigte Module

Bei einigen vorgefertigten Modultypen kann ein Modul denselben Namen haben wie seine quellbasierten Gegenstücke. Beispielsweise kann es eine cc_prebuilt_binary mit dem Namen foo geben, wenn es bereits eine cc_binary mit demselben Namen gibt. Dies gibt Entwicklern die Flexibilität zu wählen, welche Version sie in ihr Endprodukt aufnehmen möchten. Wenn eine Build-Konfiguration beide Versionen enthält, bestimmt der Wert des prefer Flags in der Definition des vorgefertigten Moduls, welche Version Priorität hat. Beachten Sie, dass einige vorgefertigte Module Namen haben, die nicht mit prebuilt beginnen, z. B. android_app_import .

Namespace-Module

Bis Android vollständig von Make zu Soong konvertiert, muss in der Make-Produktkonfiguration ein PRODUCT_SOONG_NAMESPACES -Wert angegeben werden. Sein Wert sollte eine durch Leerzeichen getrennte Liste von Namespaces sein, die Soong nach Make exportiert, um mit dem Befehl m erstellt zu werden. Nachdem die Umstellung von Android auf Soong abgeschlossen ist, können sich die Details zur Aktivierung von Namespaces ändern.

Soong bietet Modulen in verschiedenen Verzeichnissen die Möglichkeit, denselben Namen anzugeben, sofern jedes Modul in einem separaten Namensraum deklariert wird. Ein Namespace kann wie folgt deklariert werden:

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

Beachten Sie, dass ein Namespace keine Namenseigenschaft hat. Sein Pfad wird automatisch als Name zugewiesen.

Jedem Soong-Modul wird basierend auf seiner Position im Baum ein Namespace zugewiesen. Jedes Soong-Modul wird als in dem Namensraum liegend betrachtet, der durch den soong_namespace definiert wird, der in einer Android.bp Datei im aktuellen Verzeichnis oder im nächstgelegenen Vorgängerverzeichnis gefunden wird. Wenn kein solches soong_namespace Modul gefunden wird, wird davon ausgegangen, dass sich das Modul im impliziten Root-Namespace befindet.

Hier ist ein Beispiel: Soong versucht, die vom Modul M im Namespace N deklarierte Abhängigkeit D aufzulösen, die die Namespaces I1, I2, I3 … importiert.

  1. Wenn D dann ein vollständig qualifizierter Name der Form //namespace:module ist, wird nur der angegebene Namespace nach dem angegebenen Modulnamen durchsucht.
  2. Andernfalls sucht Soong zunächst nach einem Modul namens D, das im Namespace N deklariert ist.
  3. Wenn dieses Modul nicht existiert, sucht Soong in den Namespaces I1, I2, I3 ... nach einem Modul namens D.
  4. Zuletzt sucht Soong im Root-Namespace.