Derleme sistemi, rust_bindgen
modül türü aracılığıyla bindgen bağlamalarının oluşturulmasını destekler. Bindgen, C kitaplıkları için Rust FFI bağlamaları sağlar (bazı sınırlı C++ desteğiyle birlikte, bu da cppstd
özelliğinin ayarlanmasını gerektirir).
Temel rust_bindgen kullanımı
Aşağıda, bindgen kullanan bir modülün nasıl tanımlanacağına ve bu modülün nasıl sandık olarak kullanılacağına dair bir örnek verilmiştir. Harici kod gibi durumlarda include!()
makrosu aracılığıyla bindgen bağlamalarını kullanmanız gerekiyorsa Kaynak Oluşturucular sayfasına bakın.
Rust'tan çağrılacak örnek C kitaplığı
Rust'ta kullanılacak bir yapı ve işlev tanımlayan örnek bir C kitaplığı aşağıda verilmiştir.
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 modülü tanımlama
Tüm alakalı üstbilgileri içeren bir sarmalayıcı üstbilgisi (external/rust/libbuzz/libbuzz_wrapper.h
) tanımlayın:
// Include headers that are required for generating bindings in a wrapper header.
#include "libbuzz.h"
Android.bp
dosyasını external/rust/libbuzz/Android.bp
olarak tanımlayın:
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 işaretlerini kullanma hakkında daha fazla bilgi edinmek için Özel Oluşturulan Bağlamalar bölümündeki bindgen kılavuzuna bakın.
rust_bindgen
modülünü include!()
makrosunu kullanmak için ön koşul olarak tanımlamak üzere bu bölümü kullandıysanız Kaynak Oluşturucular sayfasındaki Ön koşul'a dönün. Aksi takdirde, sonraki bölümlere geçin.
Bağlamaları sandık olarak kullanma
Aşağıdaki içeriklerle external/rust/hello_bindgen/Android.bp
oluşturun:
rust_binary {
name: "hello_bindgen",
srcs: ["main.rs"],
// Add the rust_bindgen module as if it were a rust_library dependency.
rustlibs: ["libbuzz_bindgen"],
}
Aşağıdaki içeriklerle external/rust/hello_bindgen/src/main.rs
oluşturun:
//! 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) }
}
Son olarak, ikiliyi oluşturmak için m hello_bindgen
işlevini çağırın.
Test Bindgen bağlamaları
Bindgen bağlamaları, genellikle bellek düzeni uyuşmazlıklarını önlemek için bir dizi oluşturulmuş düzen testi içerir. AOSP, bu testler için tanımlanmış bir test modülünüz olmasını ve testlerin projenizin normal test paketi kapsamında çalıştırılmasını önerir.
Bunlar için bir test ikilisi, rust_test
modülü
external/rust/hello_bindgen/Android.bp
içinde tanımlanarak kolayca oluşturulabilir:
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",
}
Görünürlük ve bağlantı
Oluşturulan bağlamalar, tür tanımları, işlev imzaları ve ilgili sabitlerden oluştuğu için genellikle çok küçüktür. Bu nedenle, bu kitaplıkları dinamik olarak bağlamak genellikle gereksizdir. Bu modüller için dinamik bağlantıyı devre dışı bıraktık. Böylece, bu modüller rustlibs
üzerinden kullanıldığında otomatik olarak statik bir varyant seçilecek.
Varsayılan olarak, rust_bindgen
modüllerinin visibility
özelliği [":__subpackages__"]
'dir. Bu özellik, yalnızca aynı Android.bp
dosyasındaki veya dizin hiyerarşisinde bu dosyanın altında yer alan modüllerin bu özelliği görmesine izin verir. Bu durum iki amaca hizmet eder:
- Ağacın başka yerlerinde ham C bağlamalarının kullanılmasını engeller.
- Statik ve dinamik bağlantı karışımıyla elmas bağlantı sorunlarını önler.
Genellikle, oluşturulan modülün etrafında güvenli bir sarmalayıcı kitaplık sağlamanız gerekir. Bu kitaplık, bağlamalarla aynı dizin ağacına eklenir ve diğer geliştiricilerin kullanması amaçlanır. Bu yöntem kullanım alanınız için işe yaramazsa görünürlüğe ek paketler ekleyebilirsiniz. Ek görünürlük kapsamları eklerken lütfen gelecekte aynı işleme bağlanabilecek iki kapsam eklememeye dikkat edin. Aksi takdirde bağlantı oluşturulamayabilir.
Önemli rust_bindgen özellikleri
Aşağıda tanımlanan özellikler, tüm modüller için geçerli olan önemli ortak özelliklere ek olarak verilmiştir. Bunlar, Rust bindgen modülleri için özellikle önemlidir veya rust_bindgen
modül türüne özgü benzersiz davranışlar sergiler.
stem, name, crate_name
rust_bindgen
, kitaplık varyantları oluşturur. Bu nedenle, stem
, name
ve crate_name
özellikleri için rust_library
modülleriyle aynı koşulları paylaşır. Referans için Önemli Rust kitaplığı özellikleri bölümüne bakın.
wrapper_src
Bu, bu bağlamalar için gerekli başlıkları içeren bir sarmalayıcı başlık dosyasının göreli yoludur. Dosya uzantısı, üstbilginin nasıl yorumlanacağını ve varsayılan olarak hangi -std
işaretinin kullanılacağını belirler. Uzantı .hh
veya .hpp
olmadığı sürece bunun bir C başlığı olduğu varsayılır. C++ başlığınızın başka bir uzantısı olması gerekiyorsa dosyanın C dosyası olduğunu varsayan varsayılan davranışı geçersiz kılmak için cpp_std
özelliğini ayarlayın.
source_stem
Bu, oluşturulan kaynak dosyanın dosya adıdır. Bu alan, bağlamaları bir sandık olarak kullanıyor olsanız bile tanımlanmalıdır. Bunun nedeni, stem
özelliğinin yalnızca oluşturulan kitaplık varyantlarının çıkış dosya adını kontrol etmesidir.
Bir modül, rustlibs
üzerinden paket olarak değil de kaynak olarak birden fazla kaynak oluşturucuya (ör. bindgen
ve protobuf
) bağlıysa bu modülün bağımlılıkları olan tüm kaynak oluşturucuların benzersiz source_stem
değerlerine sahip olduğundan emin olmanız gerekir. Bağımlı modüller, SourceProvider
içinde tanımlanan tüm srcs
bağımlılıklarından kaynakları ortak bir OUT_DIR
dizinine kopyalar. Bu nedenle, source_stem
içindeki çakışmalar, oluşturulan kaynak dosyaların OUT_DIR
dizininde üzerine yazılmasına neden olur.
c_std
Bu, hangi C standardı sürümünün kullanılacağını gösteren bir dizedir. Geçerli değerler aşağıda listelenmiştir:
"gnu11"
gibi belirli bir sürüm."experimental"
,build/soong/cc/config/global.go
içinde derleme sistemi tarafından tanımlanan bir değerdir. Bu değer, kullanıma sunulduğunda C++1z gibi taslak sürümleri kullanabilir.- Derleme sistemi varsayılanının kullanılması gerektiğini belirten ayarlanmamış veya
""
.
Bu ayar belirlenirse dosya uzantısı yoksayılır ve üstbilginin C üstbilgisi olduğu varsayılır. Bu ayar, cpp_std
ile aynı anda yapılamaz.
cpp_std
cpp_std
, hangi C standardı sürümünün kullanılacağını gösteren bir dizedir. Geçerli değerler:
- Belirli bir sürüm (ör.
"gnu++11"
) "experimental"
,build/soong/cc/config/global.go
içinde derleme sistemi tarafından tanımlanan bir değerdir. Bu değer, kullanıma sunulduğunda C++1z gibi taslak sürümleri kullanabilir.- Derleme sistemi varsayılanının kullanılması gerektiğini belirten ayarlanmamış veya
""
.
Bu ayar belirlenirse dosya uzantısı yoksayılır ve başlığın C++ başlığı olduğu varsayılır. Bu ayar, c_std
ile aynı anda yapılamaz.
cflags
cflags
, başlıkların doğru şekilde yorumlanması için gereken Clang işaretlerinin dize listesini sağlar.
custom_bindgen
İleri düzey kullanım alanları için bindgen, özel bir Rust ikilisinin parçası olarak değiştirilebilen bir API sağlayan bir kitaplık olarak kullanılabilir. custom_bindgen
alanı, normal bindgen
ikilisi yerine bindgen API'sini kullanan bir rust_binary_host
modülünün modül adını alır.
Bu özel ikili, bindgen
'ya benzer şekilde bağımsız değişkenler beklemelidir. Örneğin:
$ my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]
Bu işlemlerin çoğu bindgen
kitaplığı tarafından gerçekleştirilir. Bu kullanımın bir örneğini görmek için external/rust/crates/libsqlite3-sys/android/build.rs adresini ziyaret edin.
Ayrıca, kitaplığın derlenmesini kontrol etmek için kitaplık özelliklerinin tamamı kullanılabilir. Ancak bu özelliklerin tanımlanması veya değiştirilmesi nadiren gerekir.
handle_static_inline ve static_inline_library
Bu iki özellik birlikte kullanılmak üzere tasarlanmıştır ve dışa aktarılan bindgen bağlamalarına dahil edilebilecek statik satır içi işlevler için sarmalayıcıların oluşturulmasına olanak tanır.
Bu işlevleri kullanmak için handle_static_inline: true
ve static_inline_library
değerini, rust_bindgen
modülünü kaynak girişi olarak tanımlayan ilgili cc_library_static
olarak ayarlayın.
Örnek kullanım:
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"],
// The include path to the header file in the generated c file is
// relative to build top.
include_dirs: ["."],
}