El sistema de compilación admite la generación de enlaces bindgen a través del tipo de módulo rust_bindgen
. Bindgen proporciona enlaces Rust FFI a bibliotecas C (con cierta compatibilidad limitada con C++, lo que requiere configurar la propiedad cppstd
).
Uso básico de Rust_bindgen
Lo que sigue es un ejemplo de cómo definir un módulo que usa bindgen y cómo usar ese módulo como una caja. Si necesita utilizar enlaces bindgen a través de una macro include!()
, como para código externo, consulte la página Generadores de código fuente .
Ejemplo de biblioteca C para llamar desde Rust
A continuación se muestra un ejemplo de biblioteca C que define una estructura y una función para usar en 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);
}
Definir un módulo Rust_bindgen
Defina un encabezado contenedor, external/rust/libbuzz/libbuzz_wrapper.h
, que incluya todos los encabezados relevantes:
// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"
Defina el archivo Android.bp
como 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"],
}
Para obtener más información sobre el uso de indicadores de bindgen, consulte la sección del manual de bindgen sobre Personalización de enlaces generados .
Si utilizó esta sección para definir un módulo rust_bindgen
como requisito previo para usar la macro include!()
, regrese a Requisito previo en la página Generadores de código fuente. Si no, continúe con las siguientes secciones.
Utilice fijaciones como caja
Cree external/rust/hello_bindgen/Android.bp
con el siguiente contenido:
rust_binary {
name: "hello_bindgen",
srcs: ["main.rs"],
// Add the rust_bindgen module as if it were a rust_library dependency.
rustlibs: ["libbuzz_bindgen"],
}
Cree external/rust/hello_bindgen/src/main.rs
con el siguiente contenido:
//! 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) }
}
Finalmente, llame m hello_bindgen
para compilar el binario.
Pruebe las fijaciones de Bindgen
Los enlaces de Bindgen normalmente contienen una serie de pruebas de diseño generadas para evitar discrepancias en el diseño de la memoria. AOSP recomienda tener un módulo de prueba definido para estas pruebas y que las pruebas se ejecuten como parte del conjunto de pruebas normal de su proyecto.
Se puede producir fácilmente un binario de prueba para estos definiendo un módulo rust_test
en 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",
}
Visibilidad y vinculación
Los enlaces generados suelen ser muy pequeños, ya que constan de definiciones de tipos, firmas de funciones y constantes relacionadas. Como resultado, generalmente resulta un desperdicio vincular estas bibliotecas dinámicamente. Hemos deshabilitado el enlace dinámico para estos módulos para que al usarlos a través de rustlibs
se seleccione automáticamente una variante estática.
De forma predeterminada, los módulos rust_bindgen
tienen una propiedad visibility
de [":__subpackages__"]
, que solo permitirá que los módulos en el mismo archivo Android.bp
o aquellos debajo de él en la jerarquía de directorios lo vean. Esto tiene dos propósitos:
- Desalienta el uso de enlaces C sin procesar en otras partes del árbol.
- Evita problemas de vinculación de diamantes con una combinación de vinculación estática y dinámica.
Por lo general, debe proporcionar una biblioteca contenedora segura alrededor del módulo generado que ha agregado en el mismo árbol de directorios que los enlaces destinados a que lo utilicen otros desarrolladores. Si esto no funciona para su caso de uso, puede agregar paquetes adicionales a la visibilidad . Al agregar ámbitos de visibilidad adicionales, tenga cuidado de no agregar dos ámbitos que puedan vincularse al mismo proceso en el futuro, ya que es posible que no se vinculen.
Propiedades notables de Rust_bindgen
Las propiedades definidas a continuación se suman a las propiedades comunes importantes que se aplican a todos los módulos. Estos son particularmente importantes para los módulos bindgen de Rust o exhiben un comportamiento único específico del tipo de módulo rust_bindgen
.
tallo, nombre, nombre_caja
rust_bindgen
produce variantes de biblioteca, por lo que comparten los mismos requisitos con los módulos rust_library
para las propiedades stem
, name
y crate_name
. Consulte Propiedades notables de la biblioteca Rust como referencia.
envoltura_src
Esta es la ruta relativa a un archivo de encabezado contenedor que incluye los encabezados necesarios para estos enlaces. La extensión del archivo determina cómo interpretar el encabezado y determina qué indicador -std
usar de forma predeterminada. Se supone que es un encabezado C a menos que la extensión sea .hh
o .hpp
. Si su encabezado C++ debe tener alguna otra extensión, configure la propiedad cpp_std
para anular el comportamiento predeterminado que supone que el archivo es un archivo C.
fuente_tallo
Este es el nombre del archivo fuente generado . Este campo debe definirse, incluso si está utilizando los enlaces como una caja, ya que la propiedad stem
solo controla el nombre del archivo de salida para las variantes de biblioteca generadas. Si un módulo depende de múltiples generadores de fuente (como bindgen
y protobuf
) como fuente en lugar de cajas a través de rustlibs
, debe asegurarse de que todos los generadores de fuente que dependen de ese módulo tengan valores source_stem
únicos. Los módulos dependientes copian fuentes de todas las dependencias SourceProvider
que están definidas en srcs
a un directorio OUT_DIR
común, por lo que las colisiones en source_stem
darían como resultado que los archivos fuente generados se sobrescriban en el directorio OUT_DIR
.
c_std
Esta es una cadena que representa qué versión del estándar C usar. Los valores válidos se enumeran a continuación:
- Una versión específica, como
"gnu11"
. -
"experimental"
, que es un valor definido por el sistema de compilación enbuild/soong/cc/config/global.go
, puede usar versiones borrador como C++1z cuando estén disponibles. - Unset o
""
, que indica que se debe utilizar el sistema de compilación predeterminado.
Si se establece esto, se ignora la extensión del archivo y se supone que el encabezado es un encabezado C. Esto no se puede configurar al mismo tiempo que cpp_std
.
cpp_std
cpp_std
es una cadena que representa qué versión estándar de C usar. Valores válidos:
- Una versión específica, como
"gnu++11"
-
"experimental"
, que es un valor definido por el sistema de compilación enbuild/soong/cc/config/global.go
, puede usar versiones borrador como C++1z cuando estén disponibles. - Unset o
""
, que indica que se debe utilizar el sistema de compilación predeterminado.
Si se establece esto, se ignora la extensión del archivo y se supone que el encabezado es un encabezado C++. Esto no se puede configurar al mismo tiempo que c_std
.
banderas
cflags
proporciona una lista de cadenas de indicadores Clang necesarios para interpretar correctamente los encabezados.
enlace_personalizado
Para casos de uso avanzados, bindgen se puede utilizar como biblioteca, proporcionando una API que se puede manipular como parte de un binario Rust personalizado. El campo custom_bindgen
toma el nombre del módulo de un módulo rust_binary_host
, que utiliza la API de bindgen en lugar del binario bindgen
normal.
Este binario personalizado debe contar con argumentos similares a bindgen
, como por ejemplo
$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]
La mayor parte de esto lo maneja la propia biblioteca bindgen
. Para ver un ejemplo de este uso, visite external/rust/crates/libsqlite3-sys/android/build.rs .
Además, el conjunto completo de propiedades de la biblioteca está disponible para controlar la compilación de la biblioteca, aunque rara vez es necesario definirlas o cambiarlas.