O sistema de compilação dá suporte à geração de associações de bindgen por meio do tipo de módulo rust_bindgen
. Bindgen fornece ligações Rust FFI para bibliotecas C (com algum suporte C++ limitado, que requer a configuração da propriedade cppstd
).
Uso básico de rust_bindgen
O que se segue é um exemplo de como definir um módulo que usa bindgen e como usar esse módulo como um engradado. Se você precisar usar ligações bindgen por meio de uma macro include!()
, como para código externo, consulte a página Geradores de código-fonte.
Exemplo de biblioteca C para chamar de Rust
Segue um exemplo de biblioteca C que define uma estrutura e uma função para uso em 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);
}
Definindo um módulo rust_bindgen
Defina um cabeçalho de wrapper, external/rust/libbuzz/libbuzz_wrapper.h
, que inclui todos os cabeçalhos relevantes:
// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"
Defina o arquivo 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 saber mais sobre o uso de sinalizadores de bindgen, consulte a seção do manual do bindgen em Personalizando vinculações geradas .
Se você usou esta seção para definir um módulo rust_bindgen
como um pré-requisito para usar a macro include!()
, retorne para Pré -requisito na página Geradores de código-fonte. Se não, continue com as próximas seções.
Usando ligações como uma caixa
Crie external/rust/hello_bindgen/Android.bp
com o seguinte conteúdo:
rust_binary {
name: "hello_bindgen",
srcs: ["main.rs"],
// Add the rust_bindgen module as if it were a rust_library dependency.
rustlibs: ["libbuzz_bindgen"],
}
Crie external/rust/hello_bindgen/src/main.rs
com o seguinte conteúdo:
//! 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, chame m hello_bindgen
para construir o binário.
Testando ligações do Bindgen
As associações de Bindgen normalmente contêm vários testes de layout gerados para evitar incompatibilidades de layout de memória. O AOSP recomenda que você tenha um módulo de teste definido para esses testes e que os testes sejam executados como parte do conjunto de testes normal do seu projeto.
Um binário de teste para estes pode ser facilmente produzido definindo um módulo rust_test
em 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",
}
Propriedades notáveis de rust_bindgen
As propriedades definidas abaixo são adicionais às propriedades comuns importantes que se aplicam a todos os módulos. Eles são particularmente importantes para os módulos Rust bindgen ou exibem um comportamento exclusivo específico para o tipo de módulo rust_bindgen
.
haste, nome, crate_name
rust_bindgen
produz variantes de biblioteca, portanto, eles compartilham os mesmos requisitos com os módulos rust_library
para as propriedades stem
, name
e crate_name
. Consulte as propriedades da biblioteca Notable Rust para referência.
wrapper_src
Este é o caminho relativo para um arquivo de cabeçalho wrapper que inclui os cabeçalhos necessários para essas ligações. A extensão do arquivo determina como interpretar o cabeçalho e determina qual sinalizador -std
usar por padrão. Supõe-se que seja um cabeçalho C, a menos que a extensão seja .hh
ou .hpp
. Se o seu cabeçalho C++ deve ter alguma outra extensão, defina a propriedade cpp_std
para substituir o comportamento padrão que assume que o arquivo é um arquivo C.
fonte_haste
Este é o nome do arquivo de origem gerado . Este campo deve ser definido, mesmo se você estiver usando as ligações como uma grade, pois a propriedade stem
controla apenas o nome do arquivo de saída para as variantes de biblioteca geradas. Se um módulo depende de vários geradores de origem (como bindgen
e protobuf
) como origem em vez de caixas por meio de rustlibs
, você deve garantir que todos os geradores de origem que são dependências desse módulo tenham valores source_stem
exclusivos. Módulos dependentes copiam fontes de todas as dependências SourceProvider
que são definidas em srcs
para um diretório OUT_DIR
comum, então colisões em source_stem
resultariam em arquivos fonte gerados sendo sobrescritos no diretório OUT_DIR
.
c_std
Esta é uma string que representa qual versão do padrão C usar. Os valores válidos estão listados abaixo:
- Uma versão específica, como "gnu11"
- O valor "experimental" definido pelo sistema de compilação em
build/soong/cc/config/global.go
, pode usar versões de rascunho como C++1z quando estiverem disponíveis. - "default" ou " " ambos usam o padrão do sistema de compilação.
- O valor "experimental" definido pelo sistema de compilação em
Se estiver definido, a extensão do arquivo será ignorada e o cabeçalho será considerado um cabeçalho C. Isso não pode ser definido ao mesmo tempo que cpp_std
.
cpp_std
cpp_std
é uma string que representa qual versão padrão C usar. Valores válidos:
Uma versão específica, como "gnu++11"
- O valor "experimental" definido pelo sistema de compilação em
build/soong/cc/config/global.go
, pode usar versões de rascunho como C++1z quando estiverem disponíveis. - "default" ou " " ambos o padrão do sistema de compilação.
- O valor "experimental" definido pelo sistema de compilação em
Se isso for definido, a extensão do arquivo será ignorada e o cabeçalho será considerado um cabeçalho C++. Isso não pode ser definido ao mesmo tempo que c_std
.
cflags
cflags
fornece uma lista de strings de sinalizadores Clang necessários para interpretar corretamente os cabeçalhos.
custom_bindgen
Para casos de uso avançados, o bindgen pode ser usado como uma biblioteca, fornecendo uma API que pode ser manipulada como parte de um binário Rust personalizado. O campo custom_bindgen
recebe o nome do módulo de um módulo rust_binary_host
, que usa a API bindgen em vez do binário bindgen
normal.
Este binário personalizado deve esperar argumentos de forma semelhante ao bindgen
, como " my_bindgen [flags] wrapper_header.h -o [output\_path] -- [clang flags]
". A maior parte disso é tratada pela própria biblioteca bindgen
. Para ver um exemplo desse uso, visite external/rust/crates/libsqlite3-sys/android/build.rs .
Além disso, o conjunto completo de propriedades da biblioteca está disponível para controlar a compilação da biblioteca, embora raramente precisem ser definidas ou alteradas.