ระบบบิลด์สนับสนุนการสร้างการผูกมัดผ่านประเภทโมดูล rust_bindgen
Bindgen จัดเตรียมการเชื่อมโยง Rust FFI ให้กับไลบรารี C (ด้วยการรองรับ C++ ที่จำกัด ซึ่งจำเป็นต้องตั้งค่าคุณสมบัติ cppstd
)
การใช้งานพื้นฐานrust_bindgen
สิ่งต่อไปนี้คือตัวอย่างวิธีการกำหนดโมดูลที่ใช้การเชื่อม และวิธีใช้โมดูลนั้นเป็นลัง หากคุณต้องการใช้การผูกมัดผ่านมาโคร include!()
เช่น สำหรับโค้ดภายนอก โปรดดูที่หน้า Source Generators
ตัวอย่างไลบรารี C ที่จะโทรจาก Rust
ตัวอย่างไลบรารี C ซึ่งกำหนดโครงสร้างและฟังก์ชันสำหรับใช้ใน Rust ดังต่อไปนี้
external/rust/libbuzz/libbuzz.h
typedef struct foo {
int x;
} foo;
void fizz(int i, foo* cs);
external/rust/libbuzz/libbuzz.c
#include <stdio.h>
#include "libbuzz.h"
void fizz(int i, foo* my_foo){
printf("hello from c! i = %i, my_foo->x = %i\n", i, my_foo->x);
}
กำหนดโมดูลrust_bindgen
กำหนดส่วนหัวของ wrapper external/rust/libbuzz/libbuzz_wrapper.h
ซึ่งรวมถึงส่วนหัวที่เกี่ยวข้องทั้งหมด:
// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"
กำหนดไฟล์ Android.bp
เป็น external/rust/libbuzz/Android.bp
:
cc_library {
name: "libbuzz",
srcs: ["libbuzz.c"],
}
rust_bindgen {
name: "libbuzz_bindgen",
// Crate name that's used to generate the rust_library variants.
crate_name: "buzz_bindgen",
// Path to the wrapper source file.
wrapper_src: "libbuzz_wrapper.h",
// 'source_stem' controls the output filename.
// This is the filename that's used in an include! macro.
//
// In this case, we just use "bindings", which produces
// "bindings.rs".
source_stem: "bindings",
// Bindgen-specific flags and options to customize the bindings.
// See the bindgen manual for more information.
bindgen_flags: ["--verbose"],
// Clang flags to be used when generating the bindings.
cflags: ["-DSOME_FLAG"],
// Shared, static, and header libraries which export the necessary
// include directories must be specified.
//
// These libraries will also be included in the crate if static,
// or propagated to dependents if shared.
// static_libs: ["libbuzz"]
// header_libs: ["libbuzz"]
shared_libs: ["libbuzz"],
}
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการใช้แฟล็ก Bingen โปรดดูส่วนคู่มือ Binding ใน การปรับแต่ง Bindings ที่สร้างขึ้น
หากคุณใช้ส่วนนี้เพื่อกำหนดโมดูล rust_bindgen
เป็นข้อกำหนดเบื้องต้นในการใช้แมโคร include!()
ให้กลับไปที่ ข้อกำหนดเบื้องต้น ในหน้า Source Generators ถ้าไม่ ให้ดำเนินการในส่วนถัดไป
ใช้การผูกเป็นลัง
สร้าง external/rust/hello_bindgen/Android.bp
ด้วยเนื้อหาต่อไปนี้:
rust_binary {
name: "hello_bindgen",
srcs: ["main.rs"],
// Add the rust_bindgen module as if it were a rust_library dependency.
rustlibs: ["libbuzz_bindgen"],
}
สร้าง external/rust/hello_bindgen/src/main.rs
ด้วยเนื้อหาต่อไปนี้:
//! Example crate for testing bindgen bindings
fn main() {
let mut x = buzz_bindgen::foo { x: 2 };
unsafe { buzz_bindgen::fizz(1, &mut x as *mut buzz_bindgen::foo) }
}
สุดท้ายโทรหา m hello_bindgen
เพื่อสร้างไบนารี่
ทดสอบการเชื่อมโยง Bindgen
โดยทั่วไปการผูก Bindgen จะมีการทดสอบโครงร่างที่สร้างขึ้นจำนวนหนึ่งเพื่อป้องกันเค้าโครงหน่วยความจำไม่ตรงกัน AOSP ขอแนะนำให้คุณกำหนดโมดูลการทดสอบสำหรับการทดสอบเหล่านี้ และให้การทดสอบดำเนินการเป็นส่วนหนึ่งของชุดการทดสอบปกติของโครงการของคุณ
ไบนารีทดสอบสำหรับสิ่งเหล่านี้สามารถสร้างได้อย่างง่ายดายโดยการกำหนดโมดูล rust_test
ใน external/rust/hello_bindgen/Android.bp
:
rust_test {
name: "bindings_test",
srcs: [
":libbuzz_bindgen",
],
crate_name: "buzz_bindings_test",
test_suites: ["general-tests"],
auto_gen_config: true,
// Be sure to disable lints as the generated source
// is not guaranteed to be lint-free.
clippy_lints: "none",
lints: "none",
}
การมองเห็นและการเชื่อมโยง
การเชื่อมโยงที่สร้างขึ้นมักจะมีขนาดเล็กมาก เนื่องจากประกอบด้วยคำจำกัดความของประเภท ลายเซ็นของฟังก์ชัน และค่าคงที่ที่เกี่ยวข้อง ด้วยเหตุนี้ โดยทั่วไปแล้วการเชื่อมโยงไลบรารีเหล่านี้แบบไดนามิกจึงสิ้นเปลือง เราได้ปิดใช้งานการเชื่อมโยงแบบไดนามิกสำหรับโมดูลเหล่านี้ เพื่อให้การใช้ผ่าน rustlibs
จะเลือกตัวเลือกคงที่โดยอัตโนมัติ
ตามค่าเริ่มต้น โมดูล rust_bindgen
จะมีคุณสมบัติ visibility
เป็น [":__subpackages__"]
ซึ่งจะอนุญาตเฉพาะโมดูลในไฟล์ Android.bp
เดียวกันหรือที่อยู่ข้างใต้ในลำดับชั้นไดเรกทอรีเท่านั้นที่จะเห็นมัน สิ่งนี้มีจุดประสงค์สองประการ:
- ไม่สนับสนุนการใช้การผูก C แบบดิบที่อื่นในแผนผัง
- หลีกเลี่ยงปัญหาการเชื่อมโยงเพชรด้วยการเชื่อมโยงแบบคงที่และไดนามิกผสมกัน
โดยปกติ คุณควรจัดเตรียมไลบรารี wrapper ที่ปลอดภัยรอบๆ โมดูลที่สร้างขึ้นซึ่งคุณได้เพิ่มไว้ในแผนผังไดเร็กทอรีเดียวกันกับการเชื่อมโยงซึ่งมีไว้เพื่อให้นักพัฒนารายอื่นใช้ หากวิธีนี้ใช้ไม่ได้กับกรณีการใช้งานของคุณ คุณสามารถเพิ่มแพ็คเกจเพิ่มเติมเพื่อ ให้มองเห็นได้ เมื่อเพิ่มขอบเขตการมองเห็นเพิ่มเติม โปรดระวังอย่าเพิ่มสองขอบเขตซึ่งอาจเชื่อมโยงเข้ากับกระบวนการเดียวกันในอนาคต เนื่องจากอาจเชื่อมโยงไม่ได้
คุณสมบัติการยึดเกาะของสนิมที่โดดเด่น
คุณสมบัติที่กำหนดไว้ด้านล่างเป็นส่วนเพิ่มเติมจาก คุณสมบัติทั่วไปที่สำคัญ ที่ใช้กับโมดูลทั้งหมด สิ่งเหล่านี้มีความสำคัญอย่างยิ่งต่อโมดูล Rust Bindgen หรือแสดงลักษณะการทำงานเฉพาะสำหรับประเภทโมดูล rust_bindgen
โดยเฉพาะ
ก้านชื่อ crate_name
rust_bindgen
สร้างตัวแปรไลบรารี ดังนั้นจึงมีข้อกำหนดเดียวกันกับโมดูล rust_library
สำหรับคุณสมบัติ stem
, name
และ crate_name
ดู คุณสมบัติไลบรารี Notable Rust สำหรับการอ้างอิง
wrapper_src
นี่คือเส้นทางสัมพัทธ์ไปยังไฟล์ส่วนหัวของ wrapper ที่มีส่วนหัวที่จำเป็นสำหรับการเชื่อมโยงเหล่านี้ นามสกุลไฟล์กำหนดวิธีการตีความส่วนหัวและกำหนดแฟล็ก -std
ที่จะใช้เป็นค่าเริ่มต้น นี่ถือเป็นส่วนหัว C เว้นแต่ ส่วนขยายจะเป็น .hh
หรือ .hpp
หากส่วนหัว C++ ของคุณต้องมีส่วนขยายอื่น ให้ตั้งค่าคุณสมบัติ cpp_std
เพื่อแทนที่ลักษณะการทำงานเริ่มต้นที่ถือว่าไฟล์นั้นเป็นไฟล์ C
แหล่งที่มา_ต้นกำเนิด
นี่คือชื่อไฟล์สำหรับ ไฟล์ต้นฉบับที่สร้างขึ้น ต้อง กำหนดช่องนี้ แม้ว่าคุณจะใช้การเชื่อมโยงเป็นลังก็ตาม เนื่องจากคุณสมบัติ stem
จะควบคุมเฉพาะชื่อไฟล์เอาต์พุตสำหรับตัวแปรไลบรารีที่สร้างขึ้นเท่านั้น หากโมดูลขึ้นอยู่กับตัวสร้างแหล่งที่มาหลายตัว (เช่น bindgen
และ protobuf
) เป็นแหล่งที่มาแทนที่จะเป็นลังผ่าน rustlibs
คุณต้องตรวจสอบให้แน่ใจว่าตัวสร้างแหล่งที่มาทั้งหมดที่มีการขึ้นต่อกันของโมดูลนั้นมีค่า source_stem
ที่ไม่ซ้ำกัน โมดูลที่ต้องพึ่งพาจะคัดลอกแหล่งที่มาจากการพึ่งพา SourceProvider
ทั้งหมดซึ่งกำหนดไว้ใน srcs
ไปยังไดเร็กทอรี OUT_DIR
ทั่วไป ดังนั้นการชนกันใน source_stem
จะส่งผลให้ไฟล์ต้นฉบับที่สร้างขึ้นถูกเขียนทับในไดเร็กทอรี OUT_DIR
c_std
นี่คือสตริงที่แสดงถึงเวอร์ชันมาตรฐาน C ที่จะใช้ ค่าที่ถูกต้องแสดงอยู่ด้านล่าง:
- เวอร์ชันเฉพาะ เช่น
"gnu11"
-
"experimental"
ซึ่งเป็นค่าที่กำหนดโดยระบบบิลด์ในbuild/soong/cc/config/global.go
อาจใช้ เวอร์ชันร่าง เช่น C++1z เมื่อพร้อมใช้งาน - Unset หรือ
""
ซึ่งบ่งชี้ว่าควรใช้ค่าเริ่มต้นของระบบ build
หากตั้งค่านี้ นามสกุลไฟล์จะถูกละเว้น และส่วนหัวจะถือว่าเป็นส่วนหัว C ไม่สามารถตั้งค่านี้พร้อมกับ cpp_std
ได้
cpp_std
cpp_std
เป็นสตริงที่แสดงถึงเวอร์ชันมาตรฐานของ C ที่จะใช้ ค่าที่ถูกต้อง:
- เวอร์ชันเฉพาะ เช่น
"gnu++11"
-
"experimental"
ซึ่งเป็นค่าที่กำหนดโดยระบบบิลด์ในbuild/soong/cc/config/global.go
อาจใช้ เวอร์ชันร่าง เช่น C++1z เมื่อพร้อมใช้งาน - Unset หรือ
""
ซึ่งบ่งชี้ว่าควรใช้ค่าเริ่มต้นของระบบ build
หากตั้งค่านี้ นามสกุลไฟล์จะถูกละเว้น และส่วนหัวจะถือว่าเป็นส่วนหัว C++ ไม่สามารถตั้งค่านี้พร้อมกับ c_std
ได้
แฟล็ก
cflags
จัดเตรียมรายการสตริงของแฟล็ก Clang ที่จำเป็นในการตีความส่วนหัวอย่างถูกต้อง
custom_bindgen
สำหรับกรณีการใช้งานขั้นสูง สามารถใช้ bindgen เป็นไลบรารีได้ โดยมี API ที่สามารถจัดการได้โดยเป็นส่วนหนึ่งของไบนารี Rust แบบกำหนดเอง ฟิลด์ custom_bindgen
ใช้ชื่อโมดูลของโมดูล rust_binary_host
ซึ่งใช้ Bingen API แทนไบนารี bindgen
ปกติ
ไบนารี่แบบกำหนดเองนี้ต้องคาดหวังให้เกิดอาร์กิวเมนต์ในลักษณะเดียวกันกับ bindgen
เช่น
$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]
ส่วนใหญ่ได้รับการจัดการโดยไลบรารี bindgen
เอง หากต้องการดูตัวอย่างการใช้งานนี้ ให้ไปที่ external/rust/crates/libsqlite3-sys/android/build.rs
นอกจากนี้ คุณสมบัติไลบรารีทั้งชุดยังพร้อมใช้งานเพื่อควบคุมการคอมไพล์ของไลบรารี แม้ว่าจะแทบไม่จำเป็นต้องกำหนดหรือเปลี่ยนแปลงก็ตาม