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 der Quellengenerierung sind das Generieren von C-Bindungen mit Bindgen-, AIDL- und protobuf-Schnittstellen.
Crates aus generierter Quelle
Jedes Rust-Modul, das Quellcode generiert, kann als Crate verwendet werden, genau so, als wäre es als rust_library
definiert. Das bedeutet, dass es als Abhängigkeit in den Properties rustlibs
, rlibs
und dylibs
definiert werden kann. Das beste Nutzungsmuster für Plattformcode besteht darin, generierte Quellcodedateien als Crate zu verwenden. Das include!
-Makro wird zwar für generierte Quellen unterstützt, sein Hauptzweck besteht jedoch darin, Drittanbietercode zu unterstützen, der sich in external/
befindet.
In einigen Fällen wird für Plattformcode möglicherweise weiterhin generierter Code über das include!()
-Makro verwendet, z. B. wenn Sie ein genrule
-Modul verwenden, um Code auf einzigartige Weise zu generieren.
Mit include!() generierte Quelle einfügen
Die Verwendung der generierten Quelle als Crate wird in den Beispielen auf den jeweiligen Modulseiten behandelt. In diesem Abschnitt wird gezeigt, wie Sie über das Makro include!()
auf die generierte Quelle verweisen. 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 Einfügen 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 im Quellbaum platziert oder über eine Include-Anweisung in der Quelle bereitgestellt werden muss:
include!("/path/to/hello.rs");
Die Rust-Community verwendet build.rs
-Scripts und Annahmen zur 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 den folgenden Befehl, um Quellcode einzufügen:
include!(concat!(env!("OUT_DIR"), "/hello.rs"));
Das stellt eine Herausforderung für Soong dar, da die Ausgaben für jedes Modul in einem eigenen out/
-Verzeichnis abgelegt werden1. Es gibt keine einzelne OUT_DIR
, in der Abhängigkeiten ihre generierte Quelle ausgeben.
Für Plattformcode bevorzugt AOSP das Verpacken der generierten Quelle in eine Kiste, die kann aus verschiedenen Gründen importiert werden:
- Verhindern, dass generierte Quelldateinamen kollidieren.
- Reduzieren Sie den Standardcode, der im gesamten Baum eingecheckt ist und gewartet werden muss. Textbausteine, die erforderlich, damit die generierte Quelle kompiliert wird in einer Kiste zentral gepflegt werden.
- Vermeiden Sie implizite2-Interaktionen zwischen generiertem Code und dem umgebenden Crate.
- Reduzieren Sie die Belastung von Arbeitsspeicher und Laufwerk, indem Sie häufig verwendete generierte 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 beim Kompilieren des Moduls die Umgebungsvariable OUT_DIR
auf dieses Verzeichnis fest, damit die generierte Quelle gefunden werden kann.
Aus den bereits genannten Gründen sollten Sie diesen Mechanismus jedoch nur dann im Plattformcode verwenden, wenn es unbedingt erforderlich ist.
-
Bei C/C++ und ähnlichen Sprachen stellt das kein Problem dar, da der Pfad zur generierten Quelle direkt an den Compiler übergeben wird.↩
-
Da
include!
durch Texteinschluss funktioniert, kann es auf Werte aus dem umschließenden Namespace verweisen, den Namespace ändern oder Konstrukte wie#![foo]
verwenden. Es kann schwierig sein, diese impliziten Interaktionen zu verwalten. Verwenden Sie Makros immer dann, wenn eine Interaktion mit dem Rest des Crates wirklich erforderlich ist.↩