Quellgeneratoren

Diese Seite bietet einen allgemeinen Überblick darüber, wie generierte Quellen unterstützt werden und wie sie im Build-System verwendet werden können.

Alle Quellgeneratoren bieten ähnliche Build-System-Funktionen. Die drei vom Build-System unterstützten Anwendungsfälle für die Quellengenerierung sind die Generierung von C-Bindungen mithilfe von Bindgen-, AIDL-Schnittstellen und Protobuf-Schnittstellen.

Kisten aus generierter Quelle

Jedes Rust-Modul, das Quellcode generiert, kann als Crate verwendet werden, genau so, als ob es als rust_library definiert wäre. (Das bedeutet, dass er als Abhängigkeit in den Eigenschaften rustlibs , rlibs und dylibs definiert werden kann.) Das beste Verwendungsmuster für Plattformcode besteht darin, den generierten Quellcode als Kiste zu verwenden. Obwohl das include! Das Makro wird für die generierte Quelle unterstützt. Sein Hauptzweck besteht darin, Code von Drittanbietern zu unterstützen, der sich in external/ befindet.

Es gibt Fälle, in denen Plattformcode möglicherweise weiterhin generierte Quellen über das include!() verwendet, beispielsweise wenn Sie ein genrule Modul verwenden, um Quellen auf eindeutige Weise zu generieren.

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

Die Verwendung der generierten Quelle als Kiste wird durch die Beispiele auf der jeweiligen Modulseite abgedeckt. In diesem Abschnitt wird gezeigt, wie Sie über das Makro include!() auf die generierte Quelle verweisen. Beachten Sie, dass dieser Vorgang für alle Quellgeneratoren ähnlich ist.

Voraussetzung

Dieses Beispiel basiert auf der Annahme, dass Sie ein rust_bindgen Modul ( libbuzz_bindgen ) definiert haben und mit den Schritten zum Einschließen der generierten Quelle für die Verwendung des include!() Makros fortfahren können. Wenn nicht, gehen Sie bitte zu Definieren eines Rust-Bindgen-Moduls , erstellen Sie libbuzz_bindgen und kehren Sie dann hierher zurück.

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

Schritte zum Einbinden 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 Quellen?

Im Gegensatz zu C/C++-Compilern akzeptiert rustc nur eine einzige Quelldatei, die einen Einstiegspunkt zu einer Binärdatei oder Bibliothek darstellt. Es wird erwartet, dass der Quellbaum so strukturiert ist, dass alle erforderlichen Quelldateien automatisch erkannt werden können. Das bedeutet, dass die generierte Quelle entweder im Quellbaum platziert oder über eine Include-Direktive in der Quelle bereitgestellt werden muss:

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

Um mit diesem Unterschied zu arbeiten , ist die Rust-Community auf build.rs Skripte und Annahmen über die Cargo-Build-Umgebung angewiesen. Beim Erstellen legt der cargo -Befehl eine OUT_DIR Umgebungsvariable fest, in der build.rs Skripts den generierten Quellcode platzieren sollen. Verwenden Sie den folgenden Befehl, um Quellcode einzubinden:

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

Dies stellt für Soong eine Herausforderung dar, da die Ausgaben für jedes Modul in einem eigenen out/ -Verzeichnis 1 abgelegt werden. Es gibt kein einziges OUT_DIR , in dem Abhängigkeiten ihre generierte Quelle ausgeben.

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

  • Verhindern Sie, dass generierte Quelldateinamen kollidieren.
  • Reduzieren Sie den eingecheckten Boilerplate-Code im gesamten Baum, der gewartet werden muss. Alle Boilerplates, die erforderlich sind, um die generierte Quelle in eine Kiste zu kompilieren, können zentral verwaltet werden.
  • Vermeiden Sie implizite 2- Interaktionen zwischen generiertem Code und der umgebenden Kiste.
  • Reduzieren Sie die Belastung von Speicher und Festplatte, indem Sie häufig verwendete generierte Quellen dynamisch verknüpfen.

Infolgedessen erzeugen alle Rust-Quellgenerierungsmodultypen von Android Code, der kompiliert und als Crate verwendet werden kann. Soong unterstützt weiterhin Crates von Drittanbietern ohne Änderungen, wenn alle generierten Quellabhängigkeiten für ein Modul in ein einziges Modulverzeichnis kopiert werden, ähnlich wie bei Cargo. In solchen Fällen setzt Soong beim Kompilieren des Moduls die Umgebungsvariable OUT_DIR auf dieses Verzeichnis, damit die generierte Quelle gefunden werden kann. Aus den bereits beschriebenen Gründen empfiehlt es sich jedoch, diesen Mechanismus nur dann im Plattformcode zu verwenden, wenn dies unbedingt erforderlich ist.


  1. Für C/C++ und ähnliche Sprachen stellt dies kein Problem dar, da der Pfad zur generierten Quelle direkt dem Compiler bereitgestellt wird.

  2. Da include! funktioniert durch Texteinbindung, es kann auf Werte aus dem umschließenden Namespace verweisen, den Namespace ändern oder Konstrukte wie #![foo] verwenden. Es kann schwierig sein, diese impliziten Interaktionen aufrechtzuerhalten. Bevorzugen Sie immer Makros, wenn die Interaktion mit dem Rest der Kiste wirklich erforderlich ist.

,

Diese Seite bietet einen allgemeinen Überblick darüber, wie generierte Quellen unterstützt werden und wie sie im Build-System verwendet werden können.

Alle Quellgeneratoren bieten ähnliche Build-System-Funktionen. Die drei vom Build-System unterstützten Anwendungsfälle für die Quellengenerierung sind die Generierung von C-Bindungen mithilfe von Bindgen-, AIDL-Schnittstellen und Protobuf-Schnittstellen.

Kisten aus generierter Quelle

Jedes Rust-Modul, das Quellcode generiert, kann als Crate verwendet werden, genau so, als ob es als rust_library definiert wäre. (Das bedeutet, dass er als Abhängigkeit in den Eigenschaften rustlibs , rlibs und dylibs definiert werden kann.) Das beste Verwendungsmuster für Plattformcode besteht darin, den generierten Quellcode als Kiste zu verwenden. Obwohl das include! Das Makro wird für die generierte Quelle unterstützt. Sein Hauptzweck besteht darin, Code von Drittanbietern zu unterstützen, der sich in external/ befindet.

Es gibt Fälle, in denen Plattformcode möglicherweise weiterhin generierte Quellen über das include!() verwendet, beispielsweise wenn Sie ein genrule Modul verwenden, um Quellen auf eindeutige Weise zu generieren.

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

Die Verwendung der generierten Quelle als Kiste wird durch die Beispiele auf der jeweiligen Modulseite abgedeckt. In diesem Abschnitt wird gezeigt, wie Sie über das Makro include!() auf die generierte Quelle verweisen. Beachten Sie, dass dieser Vorgang für alle Quellgeneratoren ähnlich ist.

Voraussetzung

Dieses Beispiel basiert auf der Annahme, dass Sie ein rust_bindgen Modul ( libbuzz_bindgen ) definiert haben und mit den Schritten zum Einschließen der generierten Quelle für die Verwendung des include!() Makros fortfahren können. Wenn nicht, gehen Sie bitte zu Definieren eines Rust-Bindgen-Moduls , erstellen Sie libbuzz_bindgen und kehren Sie dann hierher zurück.

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

Schritte zum Einbinden 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 Quellen?

Im Gegensatz zu C/C++-Compilern akzeptiert rustc nur eine einzige Quelldatei, die einen Einstiegspunkt zu einer Binärdatei oder Bibliothek darstellt. Es wird erwartet, dass der Quellbaum so strukturiert ist, dass alle erforderlichen Quelldateien automatisch erkannt werden können. Das bedeutet, dass die generierte Quelle entweder im Quellbaum platziert oder über eine Include-Direktive in der Quelle bereitgestellt werden muss:

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

Um mit diesem Unterschied zu arbeiten , ist die Rust-Community auf build.rs Skripte und Annahmen über die Cargo-Build-Umgebung angewiesen. Beim Erstellen legt der cargo -Befehl eine OUT_DIR Umgebungsvariable fest, in der build.rs Skripts den generierten Quellcode platzieren sollen. Verwenden Sie den folgenden Befehl, um Quellcode einzubinden:

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

Dies stellt für Soong eine Herausforderung dar, da die Ausgaben für jedes Modul in einem eigenen out/ -Verzeichnis 1 abgelegt werden. Es gibt kein einziges OUT_DIR , in dem Abhängigkeiten ihre generierte Quelle ausgeben.

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

  • Verhindern Sie, dass generierte Quelldateinamen kollidieren.
  • Reduzieren Sie den eingecheckten Boilerplate-Code im gesamten Baum, der gewartet werden muss. Alle Boilerplates, die erforderlich sind, um die generierte Quelle in eine Kiste zu kompilieren, können zentral verwaltet werden.
  • Vermeiden Sie implizite 2- Interaktionen zwischen generiertem Code und der umgebenden Kiste.
  • Reduzieren Sie die Belastung von Speicher und Festplatte, indem Sie häufig verwendete generierte Quellen dynamisch verknüpfen.

Infolgedessen erzeugen alle Rust-Quellgenerierungsmodultypen von Android Code, der kompiliert und als Crate verwendet werden kann. Soong unterstützt weiterhin Crates von Drittanbietern ohne Änderungen, wenn alle generierten Quellabhängigkeiten für ein Modul in ein einziges Modulverzeichnis kopiert werden, ähnlich wie bei Cargo. In solchen Fällen setzt Soong beim Kompilieren des Moduls die Umgebungsvariable OUT_DIR auf dieses Verzeichnis, damit die generierte Quelle gefunden werden kann. Aus den bereits beschriebenen Gründen empfiehlt es sich jedoch, diesen Mechanismus nur dann im Plattformcode zu verwenden, wenn dies unbedingt erforderlich ist.


  1. Für C/C++ und ähnliche Sprachen stellt dies kein Problem dar, da der Pfad zur generierten Quelle direkt dem Compiler bereitgestellt wird.

  2. Da include! funktioniert durch Texteinbindung, es kann auf Werte aus dem umschließenden Namespace verweisen, den Namespace ändern oder Konstrukte wie #![foo] verwenden. Es kann schwierig sein, diese impliziten Interaktionen aufrechtzuerhalten. Bevorzugen Sie immer Makros, wenn eine Interaktion mit dem Rest der Kiste wirklich erforderlich ist.

,

Diese Seite bietet einen allgemeinen Überblick darüber, wie generierte Quellen unterstützt werden und wie sie im Build-System verwendet werden können.

Alle Quellgeneratoren bieten ähnliche Build-System-Funktionen. Die drei vom Build-System unterstützten Anwendungsfälle für die Quellengenerierung sind die Generierung von C-Bindungen mithilfe von Bindgen-, AIDL-Schnittstellen und Protobuf-Schnittstellen.

Kisten aus generierter Quelle

Jedes Rust-Modul, das Quellcode generiert, kann als Crate verwendet werden, genau so, als ob es als rust_library definiert wäre. (Das bedeutet, dass er als Abhängigkeit in den Eigenschaften rustlibs , rlibs und dylibs definiert werden kann.) Das beste Verwendungsmuster für Plattformcode besteht darin, den generierten Quellcode als Kiste zu verwenden. Obwohl das include! Das Makro wird für die generierte Quelle unterstützt. Sein Hauptzweck besteht darin, Code von Drittanbietern zu unterstützen, der sich in external/ befindet.

Es gibt Fälle, in denen Plattformcode möglicherweise weiterhin generierte Quellen über das include!() verwendet, beispielsweise wenn Sie ein genrule Modul verwenden, um Quellen auf eindeutige Weise zu generieren.

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

Die Verwendung der generierten Quelle als Kiste wird durch die Beispiele auf der jeweiligen Modulseite abgedeckt. In diesem Abschnitt wird gezeigt, wie Sie über das Makro include!() auf die generierte Quelle verweisen. Beachten Sie, dass dieser Vorgang für alle Quellgeneratoren ähnlich ist.

Voraussetzung

Dieses Beispiel basiert auf der Annahme, dass Sie ein rust_bindgen Modul ( libbuzz_bindgen ) definiert haben und mit den Schritten zum Einschließen der generierten Quelle für die Verwendung des include!() Makros fortfahren können. Wenn nicht, gehen Sie bitte zu Definieren eines Rust-Bindgen-Moduls , erstellen Sie libbuzz_bindgen und kehren Sie dann hierher zurück.

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

Schritte zum Einbinden 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 Quellen?

Im Gegensatz zu C/C++-Compilern akzeptiert rustc nur eine einzige Quelldatei, die einen Einstiegspunkt zu einer Binärdatei oder Bibliothek darstellt. Es wird erwartet, dass der Quellbaum so strukturiert ist, dass alle erforderlichen Quelldateien automatisch erkannt werden können. Das bedeutet, dass die generierte Quelle entweder im Quellbaum platziert oder über eine Include-Direktive in der Quelle bereitgestellt werden muss:

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

Um mit diesem Unterschied zu arbeiten , ist die Rust-Community auf build.rs Skripte und Annahmen über die Cargo-Build-Umgebung angewiesen. Beim Erstellen legt der cargo -Befehl eine OUT_DIR Umgebungsvariable fest, in der build.rs Skripts den generierten Quellcode platzieren sollen. Verwenden Sie den folgenden Befehl, um Quellcode einzubinden:

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

Dies stellt für Soong eine Herausforderung dar, da die Ausgaben für jedes Modul in einem eigenen out/ -Verzeichnis 1 abgelegt werden. Es gibt kein einziges OUT_DIR , in dem Abhängigkeiten ihre generierte Quelle ausgeben.

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

  • Verhindern Sie, dass generierte Quelldateinamen kollidieren.
  • Reduzieren Sie den eingecheckten Boilerplate-Code im gesamten Baum, der gewartet werden muss. Alle Boilerplates, die erforderlich sind, um die generierte Quelle in eine Kiste zu kompilieren, können zentral verwaltet werden.
  • Vermeiden Sie implizite 2- Interaktionen zwischen generiertem Code und der umgebenden Kiste.
  • Reduzieren Sie die Belastung von Speicher und Festplatte, indem Sie häufig verwendete generierte Quellen dynamisch verknüpfen.

Infolgedessen erzeugen alle Rust-Quellgenerierungsmodultypen von Android Code, der kompiliert und als Crate verwendet werden kann. Soong unterstützt weiterhin Crates von Drittanbietern ohne Änderungen, wenn alle generierten Quellabhängigkeiten für ein Modul in ein einziges Modulverzeichnis kopiert werden, ähnlich wie bei Cargo. In solchen Fällen setzt Soong beim Kompilieren des Moduls die Umgebungsvariable OUT_DIR auf dieses Verzeichnis, damit die generierte Quelle gefunden werden kann. Aus den bereits beschriebenen Gründen empfiehlt es sich jedoch, diesen Mechanismus nur dann im Plattformcode zu verwenden, wenn dies unbedingt erforderlich ist.


  1. Für C/C++ und ähnliche Sprachen stellt dies kein Problem dar, da der Pfad zur generierten Quelle direkt dem Compiler bereitgestellt wird.

  2. Da include! funktioniert durch Texteinbindung, es kann auf Werte aus dem umschließenden Namespace verweisen, den Namespace ändern oder Konstrukte wie #![foo] verwenden. Es kann schwierig sein, diese impliziten Interaktionen aufrechtzuerhalten. Bevorzugen Sie immer Makros, wenn die Interaktion mit dem Rest der Kiste wirklich erforderlich ist.