หน้านี้จะแสดงภาพรวมระดับสูงเกี่ยวกับวิธีรองรับแหล่งที่มาที่สร้างขึ้น และวิธีใช้ในระบบการสร้าง
เครื่องมือสร้างแหล่งที่มาทั้งหมดมีฟังก์ชันการทำงานระบบการสร้างที่คล้ายกัน Use Case การสร้างแหล่งที่มาที่ระบบบิลด์รองรับมี 3 กรณี ได้แก่ การสร้างการเชื่อมโยง 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
แล้วกลับมาที่นี่
โปรดทราบว่าส่วนไฟล์บิลด์ของข้อมูลนี้ใช้ได้กับเครื่องมือสร้างแหล่งที่มาทั้งหมด
ขั้นตอนในการรวมแหล่งที่มาที่สร้างขึ้น
สร้าง 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) }
}
เหตุผลที่ต้องมีที่เก็บสำหรับแหล่งที่มาที่สร้างขึ้น
rustc
ยอมรับเฉพาะไฟล์ซอร์สไฟล์เดียวที่แสดงถึงจุดแรกเข้าของไฟล์ไบนารีหรือไลบรารี ซึ่งแตกต่างจากคอมไพเลอร์ C/C++ โดยคาดว่าโครงสร้างของลําดับชั้นแหล่งที่มาจะค้นพบไฟล์ต้นฉบับที่จําเป็นทั้งหมดโดยอัตโนมัติ ซึ่งหมายความว่าแหล่งที่มาที่สร้างขึ้นจะต้องวางไว้ในแผนผังต้นทางหรือระบุผ่านคำสั่ง include ในซอร์ส
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 ต้องการแพ็กเกจแหล่งที่มาที่สร้างขึ้นลงในแพ็กเกจที่นําเข้าได้ เนื่องด้วยเหตุผลหลายประการ ดังนี้
- ป้องกันไม่ให้ชื่อไฟล์ต้นฉบับที่สร้างขึ้นซ้ำกัน
- ลดโค้ด Boilerplate ที่มีการเช็คอินทั่วทั้งแผนผังที่ต้องบำรุงรักษา คุณสามารถดูแลรักษาข้อมูลโค้ดที่ซ้ำกันซึ่งจําเป็นต่อการคอมไพล์แหล่งที่มาที่สร้างขึ้นเป็นแพ็กเกจได้จากส่วนกลาง
- หลีกเลี่ยงการโต้ตอบโดยนัย2 ระหว่างโค้ดที่สร้างขึ้นกับแพ็กเกจรอบข้าง
- ลดภาระของหน่วยความจำและดิสก์ด้วยการลิงก์แหล่งที่มาที่สร้างขึ้นซึ่งใช้กันโดยทั่วไปแบบไดนามิก
ด้วยเหตุนี้ โมดูลการสร้างซอร์สโค้ด Rust ทั้งหมดของ Android จึงสร้างโค้ดที่คอมไพล์และใช้เป็นแพ็กเกจได้
Soong จะยังคงรองรับ Crate ของบุคคลที่สามโดยไม่ต้องแก้ไขหากมีการคัดลอกแหล่งที่มาทั้งหมดที่สร้างขึ้นสำหรับโมดูลไปยังไดเรกทอรีต่อโมดูลเดียว คล้ายกับ Cargo ในกรณีเช่นนี้ Soong จะตั้งค่าตัวแปรสภาพแวดล้อม OUT_DIR
ให้กับไดเรกทอรีนั้นเมื่อคอมไพล์โมดูล เพื่อให้ระบบพบแหล่งที่มาที่สร้างขึ้น
อย่างไรก็ตาม เนื่องด้วยเหตุผลที่อธิบายไว้แล้ว แนวทางปฏิบัติแนะนำคือให้ใช้กลไกนี้ในโค้ดแพลตฟอร์มก็ต่อเมื่อจำเป็นจริงๆ
-
ซึ่งไม่ได้ก่อให้เกิดปัญหาใดๆ กับ C/C++ และภาษาที่คล้ายกัน เนื่องจากมีการระบุเส้นทางไปยังแหล่งที่มาที่สร้างขึ้นไปยังคอมไพเลอร์โดยตรง ↩
-
เนื่องจาก
include!
ทํางานโดยการรวมข้อความ จึงอาจอ้างอิงค่าจากเนมสเปซที่กํากับ แก้ไขเนมสเปซ หรือใช้คอนสตรัคต์อย่าง#![foo]
การโต้ตอบโดยนัยเหล่านี้อาจรักษาให้คงอยู่ได้ยาก โปรดใช้มาโครเสมอเมื่อจำเป็นต้องโต้ตอบกับส่วนที่เหลือของกล่อง ↩