Trang này cung cấp thông tin tổng quan cấp cao về cách nguồn đã tạo được hỗ trợ và cách sử dụng nguồn đó trong hệ thống bản dựng.
Tất cả các trình tạo nguồn đều cung cấp chức năng tương tự của hệ thống bản dựng. 3 trường hợp sử dụng tạo nguồn được hệ thống bản dựng hỗ trợ là tạo các liên kết C bằng bindgen, giao diện AIDL và giao diện protobuf.
Các thùng chứa từ nguồn được tạo
Mọi mô-đun Rust tạo mã nguồn đều có thể được dùng làm một crate, giống như khi mô-đun đó được xác định là một rust_library
. (Điều này có nghĩa là bạn có thể xác định thuộc tính này là một phần phụ thuộc trong các thuộc tính rustlibs
, rlibs
và dylibs
.) Mẫu sử dụng tốt nhất cho mã nền tảng là sử dụng nguồn đã tạo làm một thùng. Mặc dù macro include!
được hỗ trợ cho nguồn đã tạo, nhưng mục đích chính của macro này là hỗ trợ mã của bên thứ ba nằm trong external/
.
Có những trường hợp mã nền tảng vẫn có thể sử dụng nguồn đã tạo thông qua macro include!()
, chẳng hạn như khi bạn sử dụng mô-đun genrule
để tạo nguồn theo cách riêng.
Sử dụng include!() để đưa nguồn đã tạo vào
Việc sử dụng nguồn đã tạo làm thùng được đề cập trong các ví dụ ở từng trang mô-đun cụ thể (tương ứng). Phần này cho biết cách tham chiếu nguồn đã tạo thông qua macro include!()
. Xin lưu ý rằng quy trình này tương tự nhau đối với tất cả các trình tạo nguồn.
Điều kiện tiên quyết
Ví dụ này dựa trên giả định rằng bạn đã xác định một mô-đun rust_bindgen
(libbuzz_bindgen
) và có thể chuyển sang Các bước để thêm nguồn đã tạo để sử dụng macro include!()
. Nếu bạn chưa làm, vui lòng chuyển đến phần Xác định một mô-đun rust bindgen, tạo libbuzz_bindgen
rồi quay lại đây.
Xin lưu ý rằng các phần tệp bản dựng của phần này áp dụng cho tất cả các trình tạo nguồn.
Các bước để đưa nguồn được tạo vào
Tạo external/rust/hello_bindgen/Android.bp
có nội dung sau:
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",
],
}
Tạo external/rust/hello_bindgen/src/bindings.rs
có nội dung sau:
#![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"));
Tạo external/rust/hello_bindgen/src/lib.rs
có nội dung sau:
mod bindings;
fn main() {
let mut x = bindings::foo { x: 2 };
unsafe { bindings::fizz(1, &mut x as *mut bindings::foo) }
}
Vì sao tạo cho nguồn được tạo
Không giống như trình biên dịch C/C++, rustc
chỉ chấp nhận một tệp nguồn duy nhất đại diện cho một điểm truy cập vào một tệp nhị phân hoặc thư viện. Thư viện này giả định rằng cây nguồn được cấu trúc sao cho tất cả các tệp nguồn bắt buộc đều có thể được tự động phát hiện. Điều này có nghĩa là nguồn được tạo phải được đặt trong cây nguồn hoặc được cung cấp thông qua chỉ thị include trong nguồn:
include!("/path/to/hello.rs");
Cộng đồng Rust phụ thuộc vào các tập lệnh build.rs
và các giả định về môi trường bản dựng Cargo để xử lý sự khác biệt này.
Khi tạo, lệnh cargo
sẽ đặt biến môi trường OUT_DIR
mà các tập lệnh build.rs
dự kiến sẽ đặt mã nguồn đã tạo vào đó. Hãy dùng lệnh sau để thêm mã nguồn:
include!(concat!(env!("OUT_DIR"), "/hello.rs"));
Điều này gây ra một thách thức cho Soong vì đầu ra cho mỗi mô-đun được đặt trong thư mục out/
riêng1. Không có một OUT_DIR
nào mà các phần phụ thuộc xuất ra nguồn đã tạo.
Đối với mã nền tảng, AOSP ưu tiên đóng gói nguồn đã tạo vào một thùng chứa có thể nhập được vì một số lý do:
- Ngăn chặn tên tệp nguồn đã tạo bị trùng lặp.
- Giảm mã nguyên mẫu được kiểm tra trong suốt cây cần bảo trì. Mọi mã chuẩn cần thiết để biên dịch nguồn đã tạo thành một thùng chứa đều có thể được duy trì tập trung.
- Tránh các lượt tương tác ngầm định2 giữa mã được tạo và thùng xung quanh.
- Giảm áp lực lên bộ nhớ và ổ đĩa bằng cách liên kết động các nguồn được tạo thường dùng.
Do đó, tất cả các loại mô-đun tạo nguồn Rust của Android đều tạo ra mã có thể được biên dịch và sử dụng dưới dạng một crate.
Soong vẫn hỗ trợ các crate của bên thứ ba mà không cần sửa đổi nếu tất cả các phần phụ thuộc nguồn được tạo cho một mô-đun được sao chép vào một thư mục duy nhất cho mỗi mô-đun, tương tự như Cargo. Trong những trường hợp như vậy, Soong sẽ đặt biến môi trường OUT_DIR
thành thư mục đó khi biên dịch mô-đun, nhờ đó có thể tìm thấy nguồn đã tạo.
Tuy nhiên, vì những lý do đã mô tả, bạn chỉ nên sử dụng cơ chế này trong mã nền tảng khi thực sự cần thiết.
-
Điều này không gây ra vấn đề nào cho C/C++ và các ngôn ngữ tương tự, vì đường dẫn đến nguồn đã tạo được cung cấp trực tiếp cho trình biên dịch. ↩
-
Vì
include!
hoạt động bằng cách bao gồm văn bản, nên nó có thể tham chiếu các giá trị từ không gian tên bao quanh, sửa đổi không gian tên hoặc sử dụng các cấu trúc như#![foo]
. Bạn có thể gặp khó khăn khi duy trì những lượt tương tác ngầm này. Luôn ưu tiên các macro khi thực sự cần tương tác với phần còn lại của crate. ↩