این صفحه نمای سطح بالایی از نحوه پشتیبانی منبع تولید شده و نحوه استفاده از آن در سیستم ساخت ارائه می دهد.
همه مولدهای منبع عملکرد سیستم ساخت مشابهی را ارائه می دهند. سه مورد استفاده از نسل منبع که از سیستم ساخت پشتیبانی میشوند، اتصالات C را با استفاده از رابطهای bindgen، AIDL و رابطهای protobuf ایجاد میکنند.
جعبه ها از منبع تولید شده
هر ماژول Rust که کد منبع تولید می کند، می تواند به عنوان یک جعبه استفاده شود، دقیقاً همانطور که به عنوان rust_library
تعریف شده است. (این بدان معنی است که می توان آن را به عنوان یک وابستگی در ویژگی های rustlibs
، rlibs
و dylibs
تعریف کرد.) بهترین الگوی استفاده برای کد پلت فرم استفاده از منبع تولید شده به عنوان یک جعبه است. اگر چه include!
ماکرو برای منبع تولید شده پشتیبانی می شود، هدف اصلی آن پشتیبانی از کدهای شخص ثالث است که در external/
.
مواردی وجود دارد که کد پلتفرم ممکن است همچنان از منبع تولید شده از طریق ماکرو include!()
استفاده کند، مانند زمانی که از یک ماژول genrule
برای تولید منبع به شیوه ای منحصر به فرد استفاده می کنید.
برای گنجاندن منبع تولید شده از include!() استفاده کنید
استفاده از منبع تولید شده به عنوان جعبه توسط مثالهای موجود در هر صفحه ماژول خاص (مرتبط) پوشش داده میشود. این بخش نحوه ارجاع منبع تولید شده را از طریق ماکرو include!()
نشان می دهد. توجه داشته باشید که این فرآیند برای همه مولدهای منبع مشابه است.
پیش نیاز
این مثال بر اساس این فرض است که شما یک ماژول rust_bindgen
( libbuzz_bindgen
) تعریف کردهاید و میتوانید به مراحل اضافه کردن منبع تولید شده برای استفاده از ماکرو include!()
بروید. اگر این کار را نکرده اید، لطفاً به تعریف ماژول rust bindgen بروید، libbuzz_bindgen
ایجاد کنید، سپس به اینجا بازگردید.
توجه داشته باشید که بخشهای build-file این برای همه مولدهای منبع قابل اجرا هستند.
مراحل گنجاندن منبع تولید شده
external/rust/hello_bindgen/Android.bp
را با محتویات زیر ایجاد کنید:
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",
],
}
external/rust/hello_bindgen/src/bindings.rs
را با محتویات زیر ایجاد کنید:
#![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"));
external/rust/hello_bindgen/src/lib.rs
را با محتویات زیر ایجاد کنید:
mod bindings;
fn main() {
let mut x = bindings::foo { x: 2 };
unsafe { bindings::fizz(1, &mut x as *mut bindings::foo) }
}
چرا جعبه ها برای منبع تولید شده
برخلاف کامپایلرهای C/C++، rustc
فقط یک فایل منبع واحد را می پذیرد که یک نقطه ورودی به یک باینری یا کتابخانه را نشان می دهد. انتظار می رود که درخت منبع به گونه ای ساختار یافته باشد که تمام فایل های منبع مورد نیاز به طور خودکار کشف شوند. این بدان معنی است که منبع تولید شده یا باید در درخت منبع قرار داده شود یا از طریق یک دستورالعمل شامل در منبع ارائه شود:
include!("/path/to/hello.rs");
جامعه Rust برای کار با این تفاوت به اسکریپتهای build.rs
و فرضیات در مورد محیط ساخت Cargo وابسته است. هنگام ساخت، فرمان cargo
یک متغیر محیطی OUT_DIR
را تنظیم می کند که انتظار می رود اسکریپت های build.rs
کد منبع تولید شده را در آن قرار دهند. برای درج کد منبع از دستور زیر استفاده کنید:
include!(concat!(env!("OUT_DIR"), "/hello.rs"));
این یک چالش برای Soong است زیرا خروجیهای هر ماژول در out/
دایرکتوری 1 خودشان قرار میگیرند. یک OUT_DIR
وجود ندارد که وابستگی ها منبع تولید شده خود را خروجی دهند.
برای کد پلت فرم، AOSP به چند دلیل، منبع تولید بسته بندی را به جعبه ای که می تواند وارد کند ترجیح می دهد:
- از برخورد نام فایل های منبع تولید شده جلوگیری کنید.
- کد ورود به دیگ بخار را در سراسر درختی که نیاز به تعمیر و نگهداری دارد، کاهش دهید. هر دیگ بخاری که برای کامپایل کردن منبع تولید شده در یک جعبه لازم است، می تواند به صورت مرکزی نگهداری شود.
- از تعاملات ضمنی 2 بین کد تولید شده و جعبه اطراف خودداری کنید.
- کاهش فشار بر روی حافظه و دیسک با پیوند دینامیکی منابع تولید شده معمولاً مورد استفاده.
در نتیجه، همه انواع ماژول های تولید منبع Rust اندروید کدی را تولید می کنند که می تواند کامپایل شود و به عنوان جعبه استفاده شود. اگر تمام وابستگیهای منبع تولید شده برای یک ماژول در یک فهرست راهنمای هر ماژول، مشابه Cargo، کپی شوند، Soong همچنان از جعبههای شخص ثالث بدون تغییر پشتیبانی میکند. در چنین مواردی، Soong هنگام کامپایل ماژول، متغیر محیطی OUT_DIR
را روی آن دایرکتوری تنظیم می کند، بنابراین منبع تولید شده را می توان پیدا کرد. با این حال، به دلایلی که قبلاً توضیح داده شد، بهترین روش استفاده از این مکانیسم در کد پلت فرم تنها در مواقعی است که کاملاً ضروری است.
این هیچ مشکلی برای C/C++ و زبان های مشابه ایجاد نمی کند، زیرا مسیر منبع تولید شده مستقیماً در اختیار کامپایلر قرار می گیرد. ↩
از آنجا که
include!
با گنجاندن متن کار می کند، ممکن است به مقادیری از فضای نام محصور ارجاع دهد، فضای نام را تغییر دهد یا از ساختارهایی مانند#![foo]
استفاده کند. حفظ این تعاملات ضمنی ممکن است دشوار باشد. وقتی واقعاً نیاز به تعامل با بقیه جعبه است، همیشه ماکروها را ترجیح دهید. ↩