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