Il sistema di compilazione supporta la generazione di associazioni bindgen tramite rust_bindgen
tipo di modulo. Bindgen fornisce associazioni Rust FFI alle librerie C (con alcune
supporto limitato C++, che richiede l'impostazione della proprietà cppstd
).
Utilizzo di base di rust_bindgen
Di seguito è riportato un esempio di come definire un modulo che utilizza bindgen e
a usare quel modulo come cassa. Se devi utilizzare associazioni bindgen tramite
una macro include!()
, come il codice esterno, consulta
Generatori di codice sorgente
.
Esempio di libreria C da chiamare da Rust
Segue una libreria C di esempio che definisce uno struct e una funzione da utilizzare in 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);
}
Definire un modulo rust_bindgen
Definisci un'intestazione del wrapper, external/rust/libbuzz/libbuzz_wrapper.h
, che include
tutte le intestazioni pertinenti:
// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"
Definisci il file Android.bp
come 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"],
}
Per saperne di più sull'uso dei flag bindgen, consulta la sezione del manuale bindgen su Personalizzazione delle associazioni generate.
Se hai utilizzato questa sezione per definire un modulo rust_bindgen
come prerequisito per
utilizzando la macro include!()
, torna alla sezione Prerequisito
nella pagina generatori di codice sorgente. In caso contrario, procedi con le sezioni successive.
Utilizza le associazioni come cassa
Crea external/rust/hello_bindgen/Android.bp
con i seguenti contenuti:
rust_binary {
name: "hello_bindgen",
srcs: ["main.rs"],
// Add the rust_bindgen module as if it were a rust_library dependency.
rustlibs: ["libbuzz_bindgen"],
}
Crea external/rust/hello_bindgen/src/main.rs
con i seguenti contenuti:
//! 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) }
}
Infine, chiama m hello_bindgen
per creare il file binario.
Testa le associazioni Bindgen
Le associazioni Bindgen contengono in genere una serie di test di layout generati per evitare layout della memoria non corrispondenti. AOSP consiglia di definire un modulo di test per eseguire questi test come parte della normale suite di test del progetto.
Un programma binario di test può essere facilmente generato definendo un modulo rust_test
tra 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",
}
Visibilità e collegamento
Le associazioni generate sono di solito molto piccole perché sono costituite da definizioni di tipo,
le firme di funzioni e le costanti correlate. Di conseguenza, in genere
per collegare le librerie in modo dinamico. Il collegamento dinamico è stato disattivato
per questi moduli in modo che il loro utilizzo tramite rustlibs
selezioni automaticamente un
una variante statica.
Per impostazione predefinita, rust_bindgen
moduli hanno una proprietà visibility
pari a
[":__subpackages__"]
, che consentirà solo moduli nello stesso Android.bp
o quelli sottostanti nella gerarchia di directory. Questo serve a due
scopi:
- Scoraggia l'utilizzo di associazioni C non elaborate in altre parti dell'albero.
- Evita i problemi di collegamento a rombo con una combinazione di collegamenti statici e dinamici.
Di solito, devi fornire una libreria di wrapper sicura per il modulo generato che hai aggiunto nella stessa struttura di directory delle associazioni destinate utilizzabili da altri sviluppatori. Se non funziona per il tuo caso d'uso, puoi aggiungere pacchetti aggiuntivi alla visibility. Quando aggiungi ulteriori ambiti di visibilità, assicurati di non due ambiti che in futuro potrebbero essere collegati allo stesso processo, non riescono a collegarsi.
Proprietà rust_bindgen degne di nota
Le proprietà definite di seguito si aggiungono alle proprietà comuni importanti
che si applicano a tutti i moduli. Questi sono particolarmente importanti per Rust
moduli bindgen o presentare un comportamento univoco specifico del tipo di modulo rust_bindgen
.
radice, nome, crate_name
rust_bindgen
produce varianti della libreria, quindi condividono gli stessi requisiti con
i moduli rust_library
per le proprietà stem
, name
e crate_name
. Consulta:
Proprietà della libreria di Rust degne di nota
come riferimento.
wrapper_src
Si tratta del percorso relativo di un file di intestazione wrapper che include le intestazioni richieste
per queste associazioni. L'estensione del file determina come interpretare l'intestazione
e determina quale flag -std
usare per impostazione predefinita. Si presume che sia una C
intestazione a meno che l'estensione sia .hh
o .hpp
. Se l'intestazione C++ deve avere
un'altra estensione, imposta la proprietà cpp_std
in modo che sostituisca il comportamento predefinito
che presuppone che si tratti di un file C.
origine_origine
Si tratta del nome del file di origine generato. Questo campo deve
anche se utilizzi le associazioni come cassa, dato che stem
controlla solo il nome file di output per le varianti della libreria generate.
Se un modulo dipende da più generatori di codice sorgente (ad esempio bindgen
e protobuf
)
come sorgente anziché come casse tramite rustlibs
, devi assicurarti che tutti i generatori di codice sorgente
che sono dipendenze di quel modulo hanno valori source_stem
univoci. Moduli dipendenti
copia le origini da tutte le dipendenze SourceProvider
definite in
srcs
a una directory OUT_DIR
comune, quindi le collisioni in source_stem
potrebbero
comporta la sovrascrittura dei file di origine generati nella directory OUT_DIR
.
c_std
Questa è una stringa che rappresenta la versione dello standard C da utilizzare. Valori validi sono elencati di seguito:
- Una versione specifica, ad esempio
"gnu11"
. "experimental"
, che è un valore definito dal sistema di compilazionebuild/soong/cc/config/global.go
, può utilizzare versioni bozza come C++1z quando sono disponibili.- Non impostato o
""
, che indica che deve essere utilizzato il valore predefinito del sistema di build.
Se impostato, l'estensione del file viene ignorata e si presume che l'intestazione
un'intestazione C. Impossibile impostare questa impostazione contemporaneamente a cpp_std
.
cpp_std
cpp_std
è una stringa che rappresenta la versione standard C da utilizzare. Valori validi:
- Una versione specifica, ad esempio
"gnu++11"
"experimental"
, che è un valore definito dal sistema di compilazionebuild/soong/cc/config/global.go
, può utilizzare versioni bozza come C++1z quando sono disponibili.- Non impostato o
""
, che indica che deve essere utilizzato il valore predefinito del sistema di build.
Se impostato, l'estensione del file viene ignorata e si presume che l'intestazione
essere un'intestazione C++. Non può essere impostato contemporaneamente a c_std
.
cflag
cflags
fornisce un elenco di stringhe dei flag Clang necessari per interpretare correttamente il
intestazioni.
associazione_personalizzata
Per casi d'uso avanzati, bindgen può essere utilizzato come libreria, fornendo un'API
può essere manipolato come parte di un file binario Rust personalizzato. Il campo custom_bindgen
prende il modulo
nome di un modulo rust_binary_host
, che utilizza invece l'API bindgen
del normale binario bindgen
.
Questo programma binario personalizzato deve prevedere argomenti in modo simile a bindgen
, ad esempio
come
$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]
La maggior parte di queste operazioni viene gestita dalla libreria bindgen
stessa. Per vedere un esempio
visita external/rust/crates/libsqlite3-sys/android/build.rs.
Inoltre, puoi controllare l'insieme completo delle proprietà delle librerie compilation della libreria, anche se raramente devono essere definite o modificate.
handle_static_inline e static_inline_library
Queste due proprietà devono essere usate insieme e consentono di produrre wrapper per le funzioni in linea statiche che possono essere incluse nella bindgen.
Per usarle, imposta handle_static_inline: true
e static_inline_library
su
un cc_library_static
corrispondente che definisce il modulo rust_bindgen
come
l'input di origine.
Esempio di utilizzo:
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/"],
}