Generator Sumber

Halaman ini memberikan tampilan tingkat tinggi tentang bagaimana sumber yang dihasilkan didukung dan bagaimana sumber tersebut dapat digunakan dalam sistem pembangunan.

Semua generator sumber menyediakan fungsionalitas sistem build yang serupa. Tiga kasus penggunaan generasi sumber yang didukung sistem build menghasilkan binding C menggunakan bindgen, antarmuka AIDL, dan antarmuka protobuf.

Peti dari sumber yang dihasilkan

Setiap modul Rust yang menghasilkan kode sumber dapat digunakan sebagai peti, persis seperti jika didefinisikan sebagai rust_library . (Ini berarti dapat didefinisikan sebagai ketergantungan pada properti rustlibs , rlibs , dan dylibs .) Pola penggunaan terbaik untuk kode platform adalah menggunakan sumber yang dihasilkan sebagai peti. Meskipun include! makro didukung untuk sumber yang dihasilkan, tujuan utamanya adalah untuk mendukung kode pihak ketiga yang berada di external/ .

Ada kasus di mana kode platform mungkin masih menggunakan sumber yang dihasilkan melalui makro include!() , seperti saat Anda menggunakan modul genrule untuk menghasilkan sumber dengan cara yang unik.

Menggunakan include!() untuk memasukkan sumber yang dihasilkan

Menggunakan sumber yang dihasilkan sebagai peti dicakup oleh contoh di setiap halaman modul tertentu (masing-masing). Bagian ini menunjukkan cara mereferensikan sumber yang dihasilkan melalui makro include!() . Perhatikan bahwa proses ini serupa untuk semua generator sumber.

Prasyarat

Contoh ini didasarkan pada asumsi bahwa Anda telah mendefinisikan modul rust_bindgen ( libbuzz_bindgen ) dan dapat melanjutkan ke Langkah-langkah untuk menyertakan sumber yang dihasilkan untuk menggunakan makro include!() . Jika belum, silakan buka Mendefinisikan modul rust bindgen , buat libbuzz_bindgen , lalu kembali ke sini.

Perhatikan bahwa bagian file build ini berlaku untuk semua generator sumber.

Langkah-langkah untuk memasukkan sumber yang dihasilkan

Buat external/rust/hello_bindgen/Android.bp dengan isi sebagai berikut:

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",
    ],
}

Buat external/rust/hello_bindgen/src/bindings.rs dengan isi sebagai berikut:

#![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"));

Buat external/rust/hello_bindgen/src/lib.rs dengan isi sebagai berikut:

mod bindings;

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

Mengapa peti untuk sumber yang dihasilkan

Tidak seperti kompiler C/C++, rustc hanya menerima satu file sumber yang mewakili titik masuk ke biner atau pustaka. Ia mengharapkan bahwa pohon sumber terstruktur sedemikian rupa sehingga semua file sumber yang diperlukan dapat ditemukan secara otomatis. Ini berarti bahwa sumber yang dihasilkan harus ditempatkan di pohon sumber, atau disediakan melalui direktif sertakan di sumber:

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

Komunitas Rust bergantung pada skrip build.rs , dan asumsi tentang lingkungan build Cargo, untuk bekerja dengan perbedaan ini . Saat dibangun, perintah cargo menyetel variabel OUT_DIR OUT_DIR di mana skrip build.rs diharapkan menempatkan kode sumber yang dihasilkan. Gunakan perintah berikut untuk memasukkan kode sumber:

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

Hal ini memberikan tantangan bagi Soong karena output untuk setiap modul ditempatkan di direktori out/ mereka sendiri 1 . Tidak ada OUT_DIR tunggal di mana dependensi menghasilkan sumber yang dihasilkan.

Untuk kode platform, AOSP lebih memilih mengemas sumber yang dihasilkan ke dalam peti yang dapat diimpor, karena beberapa alasan:

  • Cegah nama file sumber yang dihasilkan agar tidak bertabrakan.
  • Kurangi kode boilerplate check-in di seluruh struktur yang memerlukan pemeliharaan. Setiap boilerplate yang diperlukan untuk membuat kompilasi sumber yang dihasilkan menjadi peti dapat dipertahankan secara terpusat.
  • Hindari 2 interaksi implisit antara kode yang dihasilkan dan peti di sekitarnya.
  • Kurangi tekanan pada memori dan disk dengan menautkan secara dinamis sumber yang dihasilkan yang umum digunakan.

Akibatnya, semua jenis modul pembangkitan sumber Rust Android menghasilkan kode yang dapat dikompilasi dan digunakan sebagai peti . Soong masih mendukung peti pihak ketiga tanpa modifikasi jika semua dependensi sumber yang dihasilkan untuk sebuah modul disalin ke satu direktori per modul, mirip dengan Cargo. Dalam kasus seperti itu, Soong menyetel variabel lingkungan OUT_DIR ke direktori tersebut saat mengompilasi modul, sehingga sumber yang dihasilkan dapat ditemukan. Namun, untuk alasan yang telah dijelaskan, praktik terbaiknya adalah hanya menggunakan mekanisme ini dalam kode platform jika benar-benar diperlukan.


  1. Ini tidak menimbulkan masalah untuk C/C++ dan bahasa serupa, karena jalur ke sumber yang dihasilkan disediakan langsung ke kompiler. ↩.

  2. Sejak include! bekerja dengan penyertaan tekstual, ini mungkin mereferensikan nilai dari namespace terlampir, memodifikasi namespace, atau menggunakan konstruksi seperti #![foo] . Interaksi implisit ini mungkin sulit untuk dipertahankan. Selalu lebih suka makro ketika interaksi dengan peti lainnya benar-benar diperlukan. ↩.