構建系統支持通過rust_bindgen
模塊類型生成 bindgen 綁定。 Bindgen 為 C 庫提供 Rust FFI 綁定(具有一些有限的 C++ 支持,這需要設置cppstd
屬性)。
基本的 rust_bindgen 用法
下面是一個示例,說明如何定義使用 bindgen 的模塊,以及如何將該模塊用作 crate。如果您需要通過include!()
宏使用 bindgen 綁定,例如外部代碼,請參閱Source Generators頁面。
從 Rust 調用的示例 C 庫
下面是一個示例 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 模塊
定義一個包裝頭文件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 綁定
Bindgen 綁定通常包含許多生成的佈局測試,以防止內存佈局不匹配。 AOSP 建議您為這些測試定義一個測試模塊,並將這些測試作為項目正常測試套件的一部分運行。
通過在external/rust/hello_bindgen/Android.bp
中定義一個rust_test
模塊,可以輕鬆生成這些測試二進製文件:
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",
}
值得注意的 rust_bindgen 屬性
下面定義的屬性是對適用於所有模塊的重要公共屬性的補充。這些要么對 Rust bindgen 模塊特別重要,要么表現出特定於rust_bindgen
模塊類型的獨特行為。
莖,名稱,箱子名稱
rust_bindgen
生成庫變體,因此它們與rust_library
模塊對stem
、 name
和crate_name
屬性的要求相同。請參閱值得注意的 Rust 庫屬性以供參考。
wrapper_src
這是包含這些綁定所需的頭文件的包裝頭文件的相對路徑。文件擴展名確定如何解釋標頭並確定默認使用哪個-std
標誌。除非擴展名是 .hh 或.hh
,否則假定為 C 標.hpp
。如果您的 C++ 標頭必須具有其他擴展名,請設置cpp_std
屬性以覆蓋假定文件是 C 文件的默認行為。
源幹
這是生成的源文件的文件名。即使您將綁定用作 crate,也必須定義此字段,因為stem
屬性僅控制生成的庫變體的輸出文件名。如果一個模塊依賴多個源生成器(例如bindgen
和protobuf
)作為源而不是通過rustlibs
作為 crates,則必須確保作為該模塊依賴項的所有源生成器都具有唯一的source_stem
值。依賴模塊將srcs
中定義的所有SourceProvider
依賴項中的源複製到一個公共的OUT_DIR
目錄中,因此source_stem
中的衝突將導致生成的源文件在OUT_DIR
目錄中被覆蓋。
c_std
這是一個字符串,表示要使用的 C 標準版本。下面列出了有效值:
- 特定版本,例如“gnu11”
- 由構建系統在
build/soong/cc/config/global.go
中定義的“實驗”值,當它們可用時,可能會使用像 C++1z 這樣的草稿版本。 - "default" 或 " " 都使用構建系統默認值。
- 由構建系統在
如果設置了此項,則忽略文件擴展名並假定標頭是 C 標頭。這不能與cpp_std
同時設置。
cpp_std
cpp_std
是一個字符串,表示要使用哪個 C 標準版本。有效值:
特定版本,例如“gnu++11”
- 由構建系統在
build/soong/cc/config/global.go
中定義的“實驗”值,當它們可用時,可能會使用像 C++1z 這樣的草稿版本。 - “default”或“”都是構建系統的默認值。
- 由構建系統在
如果設置了此項,則忽略文件擴展名,並且假定標頭是 C++ 標頭。這不能與c_std
同時設置。
標誌
cflags
提供正確解釋標頭所需的 Clang 標誌的字符串列表。
custom_bindgen
對於高級用例,bindgen 可以用作庫,提供可以作為自定義 Rust 二進製文件的一部分進行操作的 API。 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 。
此外,完整的庫屬性集可用於控制庫的編譯,儘管這些屬性很少需要定義或更改。