เครื่องมือสร้างแหล่งที่มา

หน้านี้จะให้มุมมองระดับสูงว่าระบบรองรับแหล่งที่มาที่สร้างขึ้นอย่างไร และ จะใช้ในระบบบิลด์ได้อย่างไร

เครื่องมือสร้างแหล่งที่มาทั้งหมดมีฟังก์ชันการทำงานระบบการสร้างที่คล้ายกัน กรณีการใช้งานการสร้างแหล่งที่มาที่ระบบบิลด์รองรับมี 3 กรณี ได้แก่ การสร้างการเชื่อมโยง C โดยใช้ bindgen, อินเทอร์เฟซ AIDL และอินเทอร์เฟซ protobuf

ลังจากแหล่งที่มาที่สร้างขึ้น

โมดูล Rust ทุกโมดูลที่สร้างซอร์สโค้ดสามารถใช้เป็นแพ็กเกจได้ เหมือนกับที่กําหนดเป็น rust_library (ซึ่งหมายความว่าสามารถให้คำจำกัดความเป็น ในพร็อพเพอร์ตี้ rustlibs, rlibs และ dylibs) รูปแบบการใช้งานที่ดีที่สุดสำหรับโค้ดแพลตฟอร์มคือการใช้แหล่งที่มาที่สร้างขึ้นเป็นแพ็กเกจ แม้ว่าระบบจะรองรับมาโคร include! สำหรับแหล่งที่มาที่สร้างขึ้น แต่วัตถุประสงค์หลักคือเพื่อรองรับโค้ดของบุคคลที่สามที่อยู่ใน external/

มีหลายกรณีที่โค้ดแพลตฟอร์มอาจยังคงใช้แหล่งที่มาที่สร้างขึ้นผ่านมาโคร include!() เช่น เมื่อคุณใช้โมดูล genrule เพื่อสร้างแหล่งที่มาในลักษณะที่ไม่ซ้ำกัน

ใช้ include!() เพื่อรวมแหล่งที่มาที่สร้างขึ้น

การใช้แหล่งที่มาที่สร้างขึ้นเป็นลังจะครอบคลุมโดยตัวอย่างในแต่ละ (ตามลำดับ) ส่วนนี้จะแสดงวิธีอ้างอิงแหล่งที่มาที่สร้างขึ้น ผ่านมาโคร include!() โปรดทราบว่าขั้นตอนนี้จะคล้ายกันสำหรับแหล่งข้อมูลทุกแหล่ง โปรแกรมสร้าง

วิชาบังคับก่อน

ตัวอย่างนี้อิงตามสมมติฐานว่าคุณได้กําหนดrust_bindgen โมดูล (libbuzz_bindgen) แล้ว และสามารถไปยังขั้นตอนสําหรับรวมแหล่งที่มาที่สร้างขึ้นเพื่อใช้มาโครinclude!() หากยังไม่มี โปรดไปที่การระบุโมดูลสนิมคอนกรีต สร้าง 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 แห่งเดียวที่ ทรัพยากร Dependency จะแสดงแหล่งที่มาที่สร้างขึ้น

สำหรับโค้ดแพลตฟอร์ม AOSP ต้องการแพ็กเกจแหล่งที่มาที่สร้างขึ้นลงในแพ็กเกจที่นําเข้าได้ เนื่องด้วยเหตุผลหลายประการดังนี้

  • ป้องกันไม่ให้ชื่อไฟล์ต้นฉบับที่สร้างขึ้นขัดแย้งกัน
  • ลดโค้ดเทมเพลตที่เช็คอินไว้ทั่วทั้งต้นไม้ซึ่งต้องบำรุงรักษา คุณสามารถดูแลรักษาข้อมูลโค้ดที่ซ้ำกันซึ่งจําเป็นต่อการคอมไพล์แหล่งที่มาที่สร้างขึ้นเป็นแพ็กเกจได้จากส่วนกลาง
  • หลีกเลี่ยงการโต้ตอบโดยนัย2 ระหว่างโค้ดที่สร้างขึ้นกับแพ็กเกจรอบข้าง
  • ลดภาระของหน่วยความจําและดิสก์ด้วยการลิงก์แหล่งที่มาที่สร้างขึ้นซึ่งใช้กันโดยทั่วไปแบบไดนามิก

ด้วยเหตุนี้ โมดูลการสร้างแหล่งที่มา Rust ทั้งหมดของ Android จึงสร้างโค้ด ที่เรียบเรียงและใช้เป็นลังได้ Soong จะยังคงรองรับ Crate ของบุคคลที่สามโดยไม่ต้องแก้ไขหากคัดลอกแหล่งที่มาทั้งหมดที่จำเป็นต้องใช้ในการคอมไพล์โมดูลไปยังไดเรกทอรีเดียวต่อโมดูล คล้ายกับ Cargo ในกรณีเช่นนี้ Soong จะตั้งค่าตัวแปรสภาพแวดล้อม OUT_DIR ให้กับไดเรกทอรีนั้นเมื่อคอมไพล์โมดูล เพื่อให้ระบบพบแหล่งที่มาที่สร้างขึ้น อย่างไรก็ตาม แนวทางปฏิบัติแนะนำคือให้ใช้กลไกนี้ในโค้ดแพลตฟอร์มก็ต่อเมื่อจำเป็นจริงๆ เท่านั้น เนื่องด้วยเหตุผลที่อธิบายไว้แล้ว


  1. การดำเนินการนี้จะไม่ก่อให้เกิดปัญหาสำหรับ C/C++ และภาษาที่คล้ายกัน เนื่องจากระบบจะส่งเส้นทางไปยังแหล่งที่มาที่สร้างขึ้นไปยังคอมไพเลอร์โดยตรง 

  2. เนื่องจาก include! ทำงานโดยการรวมข้อความ จึงอาจอ้างอิงค่าจาก เนมสเปซที่รวมอยู่ แก้ไขเนมสเปซ หรือใช้โครงสร้าง เช่น #![foo] การโต้ตอบโดยนัยเหล่านี้อาจจัดการได้ยาก ชอบเสมอ เมื่อต้องโต้ตอบกับส่วนที่เหลือของลังนั้นจริงๆ