Halaman ini memberikan gambaran umum tentang cara sumber yang dihasilkan didukung dan cara sumber tersebut dapat digunakan dalam sistem build.
Semua generator sumber menyediakan fungsi sistem build yang serupa. Tiga kasus penggunaan pembuatan kode yang didukung sistem build adalah pembuatan binding C menggunakan bindgen, antarmuka AIDL, dan antarmuka protobuf.
Crates dari sumber yang dihasilkan
Setiap modul Rust yang menghasilkan kode sumber dapat digunakan sebagai crate, persis seperti
jika ditentukan sebagai rust_library
. (Artinya, properti ini dapat ditentukan sebagai
dependensi di properti rustlibs
, rlibs
, dan dylibs
.) Pola penggunaan
terbaik untuk kode platform adalah dengan menggunakan sumber yang dihasilkan sebagai crate. Meskipun makro
include!
didukung untuk sumber yang dihasilkan, tujuan utamanya adalah
mendukung kode pihak ketiga yang berada di external/
.
Ada kasus ketika kode platform mungkin masih menggunakan sumber yang dihasilkan melalui makro
include!()
, seperti saat Anda menggunakan modul genrule
untuk menghasilkan sumber
dengan cara yang unik.
Gunakan include!() untuk menyertakan sumber yang dibuat
Penggunaan sumber yang dihasilkan sebagai crate tercakup dalam contoh di setiap halaman modul spesifik (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 menentukan modul rust_bindgen
(libbuzz_bindgen
) dan dapat melanjutkan ke Langkah-langkah untuk menyertakan sumber yang dihasilkan
untuk menggunakan makro include!()
. Jika belum, buka Menentukan modul bindgen Rust,
buat libbuzz_bindgen
, lalu kembali ke sini.
Perhatikan bahwa bagian file build ini berlaku untuk semua generator sumber.
Langkah-langkah untuk menyertakan sumber yang dihasilkan
Buat external/rust/hello_bindgen/Android.bp
dengan konten 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 konten 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 konten berikut:
mod bindings;
fn main() {
let mut x = bindings::foo { x: 2 };
unsafe { bindings::fizz(1, &mut x as *mut bindings::foo) }
}
Mengapa perlu membuat crate untuk sumber yang dihasilkan
Tidak seperti compiler C/C++, rustc
hanya menerima satu file sumber
yang merepresentasikan titik entri ke biner atau library. Gradle mengharapkan struktur
hierarki sumber disusun sedemikian rupa sehingga semua file sumber yang diperlukan dapat
ditemukan secara otomatis. Artinya, sumber yang dihasilkan harus ditempatkan di pohon sumber, atau disediakan melalui direktif include di sumber:
include!("/path/to/hello.rs");
Komunitas Rust bergantung pada skrip build.rs
, dan asumsi tentang
lingkungan build Cargo, untuk menangani perbedaan ini.
Saat membangun, perintah cargo
menetapkan variabel lingkungan OUT_DIR
yang diharapkan oleh skrip build.rs
untuk menempatkan kode sumber yang dihasilkan. Gunakan perintah
berikut untuk menyertakan kode sumber:
include!(concat!(env!("OUT_DIR"), "/hello.rs"));
Hal ini menimbulkan tantangan bagi Soong karena output untuk setiap modul ditempatkan di
direktori out/
-nya sendiri1. Tidak ada satu pun OUT_DIR
tempat
dependensi menghasilkan sumber yang dibuatnya.
Untuk kode platform, AOSP lebih memilih mengemas sumber yang dihasilkan ke dalam crate yang dapat diimpor, karena beberapa alasan:
- Mencegah nama file sumber yang dihasilkan agar tidak bertabrakan.
- Mengurangi kode boilerplate yang di-check in di seluruh hierarki yang memerlukan pemeliharaan. Boilerplate apa pun yang diperlukan untuk membuat kompilasi sumber yang dihasilkan ke dalam crate dapat dikelola secara terpusat.
- Hindari interaksi2 implisit antara kode yang dihasilkan dan crate di sekitarnya.
- Mengurangi tekanan pada memori dan disk dengan menautkan secara dinamis sumber yang dihasilkan dan umum digunakan.
Oleh karena itu, semua jenis modul pembuatan sumber Rust Android menghasilkan kode yang dapat dikompilasi dan digunakan sebagai crate.
Soong masih mendukung crate pihak ketiga tanpa modifikasi jika semua
dependensi sumber yang dihasilkan untuk modul disalin ke dalam satu direktori
per modul, mirip dengan Cargo. Dalam kasus seperti itu, Soong menetapkan variabel lingkungan OUT_DIR
ke direktori tersebut saat mengompilasi modul, sehingga sumber yang dihasilkan dapat ditemukan.
Namun, karena alasan yang telah dijelaskan, praktik terbaiknya adalah hanya menggunakan
mekanisme ini dalam kode platform jika benar-benar diperlukan.
-
Hal ini tidak menimbulkan masalah apa pun untuk C/C++ dan bahasa serupa, karena jalur ke sumber yang dihasilkan diberikan langsung ke compiler. ↩
-
Karena
include!
berfungsi dengan penyertaan tekstual,include!
dapat mereferensikan nilai dari namespace yang melampirkan, mengubah namespace, atau menggunakan konstruksi seperti#![foo]
. Interaksi implisit ini mungkin sulit dipertahankan. Selalu pilih makro jika interaksi dengan crate lainnya benar-benar diperlukan. ↩