Quellgeneratoren

Auf dieser Seite erhalten Sie einen Überblick darüber, wie die generierte Quelle unterstützt wird, und wie es im Build-System verwendet werden kann.

Alle Quellgeneratoren bieten ähnliche Build-Systemfunktionen. Die drei Vom Build-System unterstützte Anwendungsfälle für die Quellengenerierung sind das Generieren von C-Bindungen. mit Bindgen-, AIDL- und protobuf-Schnittstellen.

Kisten aus generierter Quelle

Jedes Rust-Modul, das Quellcode generiert, kann wie eine Kiste verwendet werden, wenn es als rust_library definiert wäre. (Das heißt, sie kann definiert werden als Abhängigkeit in den Attributen rustlibs, rlibs und dylibs.) Optimale Nutzung Muster für Plattformcode besteht darin, die generierte Quelle als Kiste zu verwenden. Obwohl die Für die generierte Quelle wird das include!-Makro unterstützt. Der Hauptzweck besteht darin, Drittanbietercode unterstützen, der sich in external/ befindet.

Es kann vorkommen, dass Plattformcode immer noch die generierte Quelle über die include!()-Makro, z. B. wenn Sie ein genrule-Modul zum Generieren einer Quelle verwenden auf einzigartige Weise nutzen.

Verwenden Sie „include!()“, um die generierte Quelle einzuschließen

Die Verwendung der generierten Quelle als Kiste wird durch die Beispiele in den einzelnen bzw. der jeweiligen Modulseite. In diesem Abschnitt wird gezeigt, wie auf die generierte Quelle verwiesen wird. über das include!()-Makro. Dieser Vorgang ist für alle Quellen ähnlich Generatoren.

Voraussetzung

Bei diesem Beispiel wird davon ausgegangen, dass Sie eine rust_bindgen definiert haben. (libbuzz_bindgen) und können mit den Schritten zum Einbeziehen der generierten Quelle fortfahren. für die Verwendung des include!()-Makros. Wenn Sie dies noch nicht getan haben, lesen Sie den Abschnitt Rost-Bindgen-Modul definieren. Erstellen Sie libbuzz_bindgen und kehren Sie dann hierher zurück.

Beachten Sie, dass die darin enthaltenen Build-Datei-Teile für alle Quellgeneratoren gelten.

Schritte zum Einbeziehen der generierten Quelle

Erstellen Sie external/rust/hello_bindgen/Android.bp mit folgendem Inhalt:

rust_binary {
   name: "hello_bzip_bindgen_include",
   srcs: [
         // The primary rust source file must come first in this list.
         "src/lib.rs",

         // The module providing the bindgen bindings is
         // included in srcs prepended by ":".
         ":libbuzz_bindgen",
    ],

    // Dependencies need to be redeclared when generated source is used via srcs.
    shared_libs: [
        "libbuzz",
    ],
}

Erstellen Sie external/rust/hello_bindgen/src/bindings.rs mit folgendem Inhalt:

#![allow(clippy::all)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
#![allow(missing_docs)]

// Note that "bzip_bindings.rs" here must match the source_stem property from
// the rust_bindgen module.
include!(concat!(env!("OUT_DIR"), "/bzip_bindings.rs"));

Erstellen Sie external/rust/hello_bindgen/src/lib.rs mit folgendem Inhalt:

mod bindings;

fn main() {
    let mut x = bindings::foo { x: 2 };
    unsafe { bindings::fizz(1, &mut x as *mut bindings::foo) }
}

Warum Kisten für generierte Quelle

Im Gegensatz zu C/C++-Compilern akzeptiert rustc nur eine einzelne Quelldatei die einen Einstiegspunkt für eine Binärdatei oder eine Bibliothek darstellen. Es wird erwartet, dass die Quelle ist so strukturiert, dass alle erforderlichen Quelldateien automatisch gefunden. Das bedeutet, dass die generierte Quelle entweder in der Quelle platziert werden muss oder über eine Einschlussanweisung in der Quelle bereitgestellt werden:

include!("/path/to/hello.rs");

Die Rust-Community hängt von build.rs-Skripten und Annahmen über der Cargo-Build-Umgebung, um mit diesem Unterschied zu arbeiten. Beim Erstellen wird mit dem Befehl cargo eine Umgebungsvariable OUT_DIR festgelegt. in die build.rs-Skripts voraussichtlich den generierten Quellcode einfügen. Verwenden Sie die Methode folgenden Befehl, um Quellcode einzubinden:

include!(concat!(env!("OUT_DIR"), "/hello.rs"));

Das stellt für Soong eine Herausforderung dar, da die Ausgaben für jedes Modul ein eigenes out/-Verzeichnis1 erstellen. Es gibt nicht eine einzige OUT_DIR, bei der Abhängigkeiten ihre generierte Quelle ausgeben.

Für Plattformcode bevorzugt AOSP die Verpackung der generierten Quelle in eine Kiste, die kann aus verschiedenen Gründen importiert werden:

  • Verhindern, dass generierte Quelldateinamen kollidieren.
  • Boilerplate-Code reduzieren in dem Baum, der gewartet werden muss, eingecheckt haben. Textbausteine, die erforderlich, damit die generierte Quelle kompiliert wird in einer Kiste zentral gepflegt werden.
  • Vermeiden Sie implizite2 Interaktionen zwischen dem generierten Code und dem umgebenden Container.
  • Reduzieren Sie Speicher- und Laufwerksauslastung, indem Sie häufig verwendete Quellen dynamisch verknüpfen.

Infolgedessen erzeugen alle Modultypen der Rust-Quellengenerierung von Android Code das zusammengestellt und als Kiste verwendet werden kann. Soong unterstützt Kisten von Drittanbietern weiterhin, ohne dass Änderungen erforderlich sind, wenn alle Die generierten Quellabhängigkeiten für ein Modul werden pro Modul in ein einzelnes kopiert ähnlich wie Cargo. In solchen Fällen legt Soong die Umgebungsvariable OUT_DIR fest. in dieses Verzeichnis verschieben, wenn Sie das Modul kompilieren, damit die generierte Quelle gefunden werden kann. Aus den bereits beschriebenen Gründen ist es jedoch eine bewährte Methode, nur dieser Mechanismus im Plattformcode ein, wenn es unbedingt erforderlich ist.


  1. Dies stellt keine Probleme für C/C++ und ähnliche Sprachen dar, da die Der Pfad zur generierten Quelle wird dem Compiler direkt bereitgestellt.

  2. Da include! auf Text eingeschlossen ist, kann es auf Werte aus den einschließenden Namespace, ändern Sie den Namespace oder verwenden Sie Konstrukte wie #![foo]. Es kann schwierig sein, diese impliziten Interaktionen zu verwalten. Immer bevorzugen wenn eine Interaktion mit dem Rest der Kiste wirklich erforderlich ist.