ระบบบิลด์รองรับการสร้างการเชื่อมโยง Bindgen ผ่าน rust_bindgen
ประเภทโมดูล Bindgen แสดงการเชื่อมโยง FFI แบบสนิมกับไลบรารี C (พร้อมด้วย
รองรับ C++ แบบจำกัด ซึ่งต้องตั้งค่าพร็อพเพอร์ตี้ cppstd
)
การใช้งาน rust_bindgen พื้นฐาน
ต่อไปนี้เป็นตัวอย่างวิธีกำหนดโมดูลที่ใช้ Bindgen และ
วิธีใช้โมดูลดังกล่าวเป็นกรงได้ หากคุณต้องใช้การเชื่อมโยง Bindgen ผ่าน
มาโคร include!()
เช่น สำหรับโค้ดภายนอก โปรดดู
เครื่องมือสร้างแหล่งที่มา
ตัวอย่างไลบรารี 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"],
}
หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้แฟล็ก Bindgen โปรดดูส่วน Bindgen ด้วยตนเอง เกี่ยวกับการปรับแต่งการเชื่อมโยงที่สร้างขึ้น
หากคุณใช้ส่วนนี้เพื่อกำหนดโมดูล rust_bindgen
เป็นข้อกำหนดเบื้องต้นสำหรับ
ใช้มาโคร include!()
ให้กลับไปที่สิ่งที่ต้องมีก่อน
ในหน้าเครื่องมือสร้างแหล่งที่มา หากยัง ดำเนินการต่อได้ในส่วนถัดไป
ใช้การเชื่อมโยงเป็นลัง
สร้าง 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 มักมีการทดสอบรูปแบบที่สร้างขึ้นจำนวนหนึ่งเพื่อป้องกัน รูปแบบหน่วยความจำไม่ตรงกัน 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
เดียวกัน
หรือไฟล์ที่อยู่ใต้ไดเรกทอรีนั้นในลำดับชั้นของไดเรกทอรีเพื่อดูไฟล์ วิธีนี้สำหรับ 2 อย่าง
วัตถุประสงค์:
- ไม่สนับสนุนให้ใช้การเชื่อมโยงแบบ Raw C ส่วนอื่นๆ ของต้นไม้
- ช่วยหลีกเลี่ยงปัญหาการเชื่อมโยงเพชรจากทั้งการลิงก์แบบคงที่และแบบไดนามิก
โดยปกติแล้วคุณควรมีไลบรารี Wrapper ที่ปลอดภัยรอบๆ โมดูลที่สร้างขึ้น ซึ่งคุณได้เพิ่มไว้ในแผนผังไดเรกทอรีเดียวกันกับการเชื่อมโยงที่มีไว้สำหรับ รายอื่นๆ ได้เลือกใช้ หากวิธีนี้ไม่ได้ผลกับกรณีการใช้งานของคุณ คุณสามารถเพิ่ม แพ็กเกจเพิ่มเติมที่จะเปิดเผยได้ เมื่อเพิ่มขอบเขตการมองเห็นเพิ่มเติม โปรดระมัดระวังอย่าเพิ่ม 2 ขอบเขต ซึ่งอาจลิงก์กับกระบวนการเดียวกันในอนาคต เนื่องจาก ลิงก์ไม่สำเร็จ
คุณสมบัติสำคัญของrust_bindgen
พร็อพเพอร์ตี้ที่ระบุด้านล่างเป็นพร็อพเพอร์ตี้เพิ่มเติมจากพร็อพเพอร์ตี้ทั่วไปที่สำคัญ
ซึ่งมีผลกับโมดูลทั้งหมด สิ่งเหล่านี้มีความสำคัญอย่างยิ่งต่อ Rust
โมดูล Bindgen หรือแสดงลักษณะการทำงานที่เฉพาะเจาะจงสำหรับประเภทโมดูล rust_bindgen
ต้นกำเนิด, ชื่อ, ชื่อลัง
rust_bindgen
สร้างตัวแปรไลบรารี จึงมีข้อกำหนดเดียวกันนี้กับ
โมดูล rust_library
สำหรับพร็อพเพอร์ตี้ stem
, name
และ crate_name
โปรดดู
พร็อพเพอร์ตี้ไลบรารีของ Rust ที่โดดเด่น
เพื่อเป็นข้อมูลอ้างอิง
Wrapper_src
นี่คือเส้นทางแบบสัมพัทธ์ไปยังไฟล์ส่วนหัว Wrapper ที่มีส่วนหัวที่จำเป็น
สำหรับการเชื่อมโยงเหล่านี้ นามสกุลไฟล์เป็นตัวกำหนดวิธีตีความส่วนหัว
และกำหนดว่าจะใช้ Flag -std
ใดโดยค่าเริ่มต้น จะถือว่าเป็น C
ส่วนหัวเว้นแต่ส่วนขยายจะเป็น .hh
หรือ .hpp
หากส่วนหัว C++ ต้องมี
ส่วนขยายอื่นๆ ให้ตั้งค่าพร็อพเพอร์ตี้ cpp_std
เพื่อลบล้างลักษณะการทำงานเริ่มต้น
ซึ่งจะถือว่าไฟล์ดังกล่าวเป็นไฟล์ C
ต้นกำเนิด
นี่คือชื่อไฟล์ของไฟล์ต้นฉบับที่สร้างขึ้น ช่องนี้ต้อง
แม้ว่าคุณจะใช้การเชื่อมโยงเป็นลัง เนื่องจาก stem
พร็อพเพอร์ตี้จะควบคุมชื่อไฟล์เอาต์พุตสำหรับรูปแบบไลบรารีที่สร้างขึ้นเท่านั้น
ในกรณีที่โมดูลต้องใช้เครื่องมือสร้างแหล่งที่มาหลายรายการ (เช่น bindgen
และ protobuf
)
เป็นแหล่งที่มา ไม่ใช่แบบคลังข้อมูลผ่าน rustlibs
คุณต้องตรวจสอบว่าตัวสร้างแหล่งที่มาทั้งหมด
ทรัพยากร Dependency ของโมดูลนั้นมีค่า source_stem
ที่ไม่ซ้ำกัน โมดูลที่เกี่ยวข้อง
คัดลอกแหล่งที่มาจากทรัพยากร Dependency ทั้งหมด SourceProvider
รายการที่ระบุไว้ใน
srcs
ไปยังไดเรกทอรี OUT_DIR
ทั่วไป ดังนั้นการขัดแย้งใน source_stem
จะ
ทำให้ไฟล์ต้นฉบับที่สร้างขึ้นถูกเขียนทับในไดเรกทอรี OUT_DIR
C_Std
นี่คือสตริงที่บอกว่าจะใช้เวอร์ชัน C-Standard ใด ค่าที่ถูกต้อง มีดังนี้
- เวอร์ชันที่เฉพาะเจาะจง เช่น
"gnu11"
"experimental"
ซึ่งเป็นค่าที่กำหนดโดยระบบบิลด์ในbuild/soong/cc/config/global.go
อาจใช้ เวอร์ชันร่าง เช่น C++1z เมื่อพร้อมให้บริการ- ยกเลิกการตั้งค่าหรือ
""
ซึ่งบ่งชี้ว่าควรใช้ค่าเริ่มต้นของระบบบิลด์
หากตั้งค่านี้ ระบบจะไม่สนใจนามสกุลไฟล์และจะถือว่าส่วนหัวเป็น
เป็นส่วนหัว C ตั้งค่านี้พร้อมกับ cpp_std
ไม่ได้
cpp_std
cpp_std
คือสตริงที่บอกว่าจะใช้เวอร์ชันมาตรฐาน C ใด ค่าที่ถูกต้อง:
- เวอร์ชันที่เฉพาะเจาะจง เช่น
"gnu++11"
"experimental"
ซึ่งเป็นค่าที่กำหนดโดยระบบบิลด์ในbuild/soong/cc/config/global.go
อาจใช้ เวอร์ชันร่าง เช่น C++1z เมื่อพร้อมให้บริการ- ยกเลิกการตั้งค่าหรือ
""
ซึ่งบ่งชี้ว่าควรใช้ค่าเริ่มต้นของระบบบิลด์
หากตั้งค่านี้ ระบบจะไม่สนใจนามสกุลไฟล์และจะถือว่าส่วนหัวเป็น
เป็นส่วนหัว C++ ตั้งค่านี้พร้อมกับ c_std
ไม่ได้
ธง
cflags
แสดงรายการสตริงของแฟล็ก Clang ที่จำเป็นต่อการตีความ
ส่วนหัว
การเชื่อมโยงที่กำหนดเอง [custom_bindgen]
สำหรับกรณีการใช้งานขั้นสูง สามารถใช้ Bindgen เป็นไลบรารีโดยให้ API ที่
จัดการได้เป็นส่วนหนึ่งของไบนารี Rust ที่กำหนดเอง ช่อง custom_bindgen
เข้าสู่โมดูลนี้
ชื่อของโมดูล rust_binary_host
ซึ่งใช้ Bindgen API แทน
ของไบนารี bindgen
ปกติ
ไบนารีที่กำหนดเองนี้ต้องคาดหวังอาร์กิวเมนต์ในลักษณะเดียวกับ bindgen
เช่น
ในฐานะ
$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]
การดำเนินการนี้ส่วนใหญ่จะจัดการโดยไลบรารีของ bindgen
เอง ถ้าต้องการดูตัวอย่าง
ให้ไปที่ external/rust/crates/libsqlite3-sys/android/build.rs
นอกจากนี้ คุณยังควบคุมชุดคุณสมบัติไลบรารีทั้งหมดได้ด้วย จากการรวบรวมไลบรารี แต่สิ่งเหล่านี้ไม่ค่อยต้องมีการกำหนดหรือเปลี่ยนแปลง
contact_static_inline และ static_inline_library
พร็อพเพอร์ตี้ 2 รายการนี้มีไว้เพื่อใช้ร่วมกันและอนุญาตให้สร้าง Wrapper สำหรับฟังก์ชันในบรรทัดแบบคงที่ซึ่งสามารถรวมไว้ใน Bindgen
หากต้องการใช้งาน ให้ตั้งค่า handle_static_inline: true
และตั้งค่า static_inline_library
เป็น
cc_library_static
ที่เกี่ยวข้องซึ่งกำหนดโมดูล rust_bindgen
เป็น
อินพุตแหล่งที่มา
ตัวอย่างการใช้:
rust_bindgen {
name: "libbindgen",
wrapper_src: "src/any.h",
crate_name: "bindgen",
stem: "libbindgen",
source_stem: "bindings",
// Produce bindings for static inline fucntions
handle_static_inline: true,
static_inline_library: "libbindgen_staticfns"
}
cc_library_static {
name: "libbindgen_staticfns",
// This is the rust_bindgen module defined above
srcs: [":libbindgen"],
include_dirs: ["src/"],
}